QMediaPlayer.play() не работает, если я вызываю функцию с ним

Я создаю аудиоплеер с Qt, и я реализую это, когда я загружаю песню, она запускается автоматически, но когда я вызываю функцию для запуска песни и вычисляю продолжительность, песня не запускается. Я использовал отладку, и когда я добрался до функции воспроизведения, отладка остановилась с end-step-range. Я также попытался издать сигнал, но ничего не поделать, песня запускается, только если я нажимаю кнопку Play.

Здесь есть код

void AudioPlayer::loadClicked()
{
    QString filename = QFileDialog::getOpenFileName(this, "Select an audio file", "C:/Users/belli/Music" ,"File Mp3 (*.mp3)");

    if(!filename.isEmpty())
    {
        qDebug("%s", filename.toLatin1().constData());
        player.setMedia(QUrl::fromLocalFile(filename));
        this->volumeSliderMoved();
        QFileInfo fi(filename);
        QString name = fi.fileName();
        ui->label->setText(name);
        this->playClicked();
    }
}

void AudioPlayer::playClicked()
{
    player.play();
    songLength = player.duration();
    ui->horizontalSliderPosition->setRange(0, songLength);
}

void AudioPlayer::stopClicked()
{
    player.stop();
    ui->horizontalSliderPosition->setValue(0);
}

void AudioPlayer::playerPositionChanged(qint64 pos)
{
   ui->horizontalSliderPosition->setValue(pos);
   if(pos == songLength)
       this->stopClicked();
}

void AudioPlayer::volumeSliderMoved()
{
    player.setVolume(ui->horizontalSliderVolume->value());
}

void AudioPlayer::positionSliderMoved()
{
    player.setPosition((quint64) ui->horizontalSliderPosition->value());
}

И соединяет

ui(new Ui::AudioPlayer)
{
    ui->setupUi(this);
    connect(ui->pushButtonLoad, SIGNAL(clicked(bool)), SLOT(loadClicked()));
    connect(ui->pushButtonPlay, SIGNAL(clicked(bool)), SLOT(playClicked()));
    connect(ui->pushButtonStop, SIGNAL(clicked(bool)), SLOT(stopClicked()));
    connect(ui->horizontalSliderVolume, SIGNAL(valueChanged(int)), SLOT(volumeSliderMoved()));
    connect(ui->horizontalSliderPosition, SIGNAL(sliderReleased()), SLOT(positionSliderMoved()));

    connect(&player, SIGNAL(positionChanged(qint64)), SLOT(playerPositionChanged(qint64)));
}

1 ответ

Решение

Вам не хватает этого setMedia работает асинхронно То есть он возвращает без гарантии, что медиа-файл загружен из документов:

Эта функция возвращается сразу после записи указанного источника носителя. Он не ожидает окончания загрузки носителя и не проверяет наличие ошибок. Слушай mediaStatusChanged() а также error() сигналы для уведомления, когда носитель загружен и когда происходит ошибка во время загрузки.

Это означает, что когда вы звоните this->playClicked(); после того как ты позвонил player.setMedia(...);, есть большой шанс, что медиа-файл еще не был загружен, и вызов player.duration() терпит неудачу (он не возвращает реальную длительность медиа-файла, который вы пытаетесь воспроизвести). Итак, у вас есть ползунок продолжительности, имеющий диапазон (0, 0) и это вызывает вызов player.stop() позже, так как вы думаете, что достигли конца вашего медиа-файла.,,

Чтобы решить эту проблему, вам нужно следовать тому, что написано в документации. Удостоверьтесь, чтобы не продвигаться к вашему playClicked слот, если вы не убедитесь, что ваш медиа-файл полностью загружен. Вы можете сделать это, заменив:

this->playClicked();

С чем-то вроде этого:

connect(&player, &QMediaPlayer::mediaStatusChanged,
        this, [&](QMediaPlayer::MediaStatus status){
    if(status == QMediaPlayer::LoadedMedia) playClicked();
});
Другие вопросы по тегам