Qt wiki will be updated on October 12th 2023 starting at 11:30 AM (EEST) and the maintenance will last around 2-3 hours. During the maintenance the site will be unavailable.

Seek in Sound File: Difference between revisions

From Qt Wiki
Jump to navigation Jump to search
(Add "cleanup" tag)
(Sub-categorize)
 
(2 intermediate revisions by 2 users not shown)
Line 1: Line 1:
{{Cleanup | reason=Auto-imported from ExpressionEngine.}}
[[Category:Snippets::Misc]]
 
[[Category:Snippets]]
[[Category:HowTo]]
[[Category:HowTo]]
= How to Seek in Sound File =
I tried to play a sound file not at the beginning but with an offset of 20 seconds.
I tried to play a sound file not at the beginning but with an offset of 20 seconds.


The following way of setting an offset '''fails''':
The following way of setting an offset '''fails''':
<code>player = new QMediaPlayer(this);
 
<code>
player = new QMediaPlayer(this);
player->setMedia(QUrl::fromLocalFile("myCoolSong.mp3"));
player->setMedia(QUrl::fromLocalFile("myCoolSong.mp3"));
player->setVolume(50);
player->setVolume(50);
player->play(); // music can be heard
player->play(); // music can be heard
qDebug() << player->isSeekable(); // is always false
qDebug() << player->isSeekable(); // is always false
player->setPosition ( 20*1000 ); //does not work</code>
player->setPosition ( 20*1000 ); //does not work
</code>


'''''It does not work because QMediaPlayer works asynchronously.'''''
'''It does not work because QMediaPlayer works asynchronously.'''


As soon as the seek operations are delayed everything works as intended. For example:
As soon as the seek operations are delayed everything works as intended. For example:


<code>CoolPlayer::on_Button1_clicked()
<code>
CoolPlayer::on_Button1_clicked()
{
{
  qDebug() << player->isSeekable(); // true
  qDebug() << player->isSeekable(); // true
  player->setPosition ( 20*1000 );
  player->setPosition ( 20*1000 );
}</code>
}
</code>


To make my life easier I have derived a class MediaPlayer from QMediaPlayer and added a blocking load method:
To make my life easier I have derived a class MediaPlayer from QMediaPlayer and added a blocking load method:


<code>void MediaPlayer::loadBlocking(const QString &amp;file;)
<code>
void MediaPlayer::loadBlocking(const QString &file;)
{
{
  setMedia(QUrl::fromLocalFile(file));
  setMedia(QUrl::fromLocalFile(file));
Line 37: Line 38:
  timer.setSingleShot(true);
  timer.setSingleShot(true);
  timer.setInterval(2000);
  timer.setInterval(2000);
  loop.connect(&amp;timer;, SIGNAL (timeout()), &amp;loop;, SLOT (quit()) );
  loop.connect(&timer;, SIGNAL (timeout()), &loop;, SLOT (quit()) );
  loop.connect(this, SIGNAL (seekableChanged(bool)), &amp;loop;, SLOT (quit()));
  loop.connect(this, SIGNAL (seekableChanged(bool)), &loop;, SLOT (quit()));
  loop.exec();
  loop.exec();
  }
  }
}</code>
}
</code>


When files are loaded with this blocking load method <code>setPosition()</code> can be called right in the next source line.
When files are loaded with this blocking load method <code>setPosition()</code> can be called right in the next source line.
<code>loadBlocking</code> blocks until signal <code>seekableChanged()</code> is emitted. To avoid a deadlock, maximum waiting time is 2 seconds.
<code>loadBlocking</code> blocks until signal <code>seekableChanged()</code> is emitted. To avoid a deadlock, maximum waiting time is 2 seconds.

Latest revision as of 12:11, 28 November 2016

I tried to play a sound file not at the beginning but with an offset of 20 seconds.

The following way of setting an offset fails:

player = new QMediaPlayer(this);
player->setMedia(QUrl::fromLocalFile("myCoolSong.mp3"));
player->setVolume(50);
player->play(); // music can be heard
qDebug() << player->isSeekable(); // is always false
player->setPosition ( 20*1000 ); //does not work

It does not work because QMediaPlayer works asynchronously.

As soon as the seek operations are delayed everything works as intended. For example:

CoolPlayer::on_Button1_clicked()
{
 qDebug() << player->isSeekable(); // true
 player->setPosition ( 20*1000 );
}

To make my life easier I have derived a class MediaPlayer from QMediaPlayer and added a blocking load method:

void MediaPlayer::loadBlocking(const QString &file;)
{
 setMedia(QUrl::fromLocalFile(file));
 if(!isSeekable())
 {
 QEventLoop loop;
 QTimer timer;
 timer.setSingleShot(true);
 timer.setInterval(2000);
 loop.connect(&timer;, SIGNAL (timeout()), &loop;, SLOT (quit()) );
 loop.connect(this, SIGNAL (seekableChanged(bool)), &loop;, SLOT (quit()));
 loop.exec();
 }
}

When files are loaded with this blocking load method

setPosition()

can be called right in the next source line.

loadBlocking

blocks until signal

seekableChanged()

is emitted. To avoid a deadlock, maximum waiting time is 2 seconds.