Is there any way to start a stream in a Phonon Media Object from an arbitrary point?
Frage
I'm writing an application to listen to podcasts in Qt 4.8.1 on Mac OS X. Right now, I'm setting my MediaObject
to use the enclosure URL from the podcast's RSS item, like so:
mediaObj->setCurrentSource(Phonon::MediaSource(QUrl(idx.data(Metadata::Enclosure).toString())));
Note: idx
is a QModelIndex
that corresponds to the QStandardItem
within my model that the user clicked on in a QTreeView
widget.
I've got two problems right now, though.
- Whenever I pause the stream and start it again, it starts from the beginning. Not so helpful. :-(
- If I use my
Phonon::SeekSlider
widget to skip ahead to a part of the stream I haven't yet buffered, I'm getting bounced back to the beginning of the stream.
My (potentially flawed) thinking is that if I could figure out a way to get mediaObj
to start playing from a specific time in the stream, I could fix both these problems. And so, I've tried this:
void BrodCastMainWin::pauseStream()
{
//save the "left off at" point in the stream
qDebug() << "current time is:" << currentTime;
qDebug() << "Saving place at" << currentTimeString
<< "in item" << nowPlaying.data(Qt::DisplayRole).toString();
//need to use QModelIndex for setData()
QModelIndex nowPlayingHandle = nowPlaying;
feed.setData(nowPlayingHandle, QVariant(currentTime), Metadata::LeftOffAt);
//pause the stream
mediaObj->pause();
}
void BrodCastMainWin::playStream()
{
//seek to the "left off at" point in the stream
qDebug() << "Trying to seek to" << convertTime(nowPlaying.data(Metadata::LeftOffAt).toLongLong())
<< "in item" << nowPlaying.data(Qt::DisplayRole).toString();
mediaObj->seek(nowPlaying.data(Metadata::LeftOffAt).toLongLong());
//play the file
mediaObj->play();
}
Note: currentTime
is the time as of the last tick()
signal mediaObj
emitted. I tried to get this data using the currentTime()
method within mediaObj
, and it didn't work. But that's a battle for another day. Similarly, currentTimeString
is the same info in a human-readable format.
Alas, it doesn't work :-(. This is what happens with that code when I play the stream:
current time is: 32153
Saving place at "00:32" in item "Leo Laporte - The Tech Guy 867"
switching button to 'play'
Groovy. But when I try to play again:
Trying to seek to "00:32" in item "Leo Laporte - The Tech Guy 867"
Playing/Loading/Buffering; switching button to 'pause'
current time is: 0
Saving place at "00:00" in item "Leo Laporte - The Tech Guy 867"
switching button to 'play'
Trying to seek to "00:00" in item "Leo Laporte - The Tech Guy 867"
Playing/Loading/Buffering; switching button to 'pause'
I'm totally confused. It seems like I'm trying to make Phonon behave in a way it doesn't want to. My fear is that this seems like a long-standing problem with the Phonon module, and I might have to implement the stream some other way. Help?
Lösung
Well, it appears I got too fancy. I'm using a single button for play/pause. I simply had to change this:
void BrodCastMainWin::handleMediaState(Phonon::State state, Phonon::State)
{
switch (state)
{
case Phonon::PlayingState:
case Phonon::LoadingState:
case Phonon::BufferingState:
qDebug() << "Playing/Loading/Buffering; switching button to 'pause'";
//If we're playing, the button should pause
ui->playPauseButton->setIcon(QIcon(":/assets/stock_media-pause.svg"));
connect(ui->playPauseButton, SIGNAL(clicked()),
this, SLOT(pauseStream()));
break;
case Phonon::PausedState:
case Phonon::StoppedState:
qDebug() << "switching button to 'play'";
//if we're paused, the button should play
ui->playPauseButton->setIcon(QIcon(":/assets/stock_media-play.svg"));
connect(ui->playPauseButton, SIGNAL(clicked()),
this, SLOT(playStream()));
case Phonon::ErrorState:
//additionally, if there's an error, do error handling.
break;
default:
break;
}
}
...to this:
void BrodCastMainWin::handleMediaState(Phonon::State state, Phonon::State)
{
switch (state)
{
case Phonon::PlayingState:
qDebug() << "Playing/Loading/Buffering; switching button to 'pause'";
//If we're playing, the button should pause
ui->playPauseButton->setIcon(QIcon(":/assets/stock_media-pause.svg"));
connect(ui->playPauseButton, SIGNAL(clicked()),
this, SLOT(pauseStream()));
break;
case Phonon::PausedState:
qDebug() << "switching button to 'play'";
//if we're paused, the button should play
ui->playPauseButton->setIcon(QIcon(":/assets/stock_media-play.svg"));
connect(ui->playPauseButton, SIGNAL(clicked()),
this, SLOT(playStream()));
break;
case Phonon::ErrorState:
//additionally, if there's an error, do error handling.
break;
case Phonon::LoadingState:
case Phonon::BufferingState:
case Phonon::StoppedState:
default:
break;
}
}
Of course, I'm eventually going to want to handle those other states, too. But this solves the first of my problems. The other problem will probably have to wait until another day.