Is there any way to start a stream in a Phonon Media Object from an arbitrary point?

StackOverflow https://stackoverflow.com/questions/10400731

  •  04-06-2021
  •  | 
  •  

Question

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.

  1. Whenever I pause the stream and start it again, it starts from the beginning. Not so helpful. :-(
  2. 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?

Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top