Media player not working for multiple videos
-
Hi,
Because in your slot you are using the
mediaPlayer
member variable which is basically the last media player you created.If you want to control them all at the same time, you have to iterate through your vector of media players and apply what you want to do to all of them.
-
@Kinesis Please do not ask same question in a new thread.
Here https://forum.qt.io/topic/92058/multiple-media-player-for-each-video your question was already answered, but you apparently did not do as suggested. This is what I suggested:QMediaPlayer *mediaPlayer = new QMediaPlayer(); mediaPlayer->setMedia(QUrl::fromLocalFile(finfo.absoluteFilePath())); ... mediaPlayer->setVideoOutput(m_videoItem); m_mediaPlayer.append(mediaPlayer);
So, here mediaPlayer is a not a MEMBER variable (as @SGaist suggested above).
And I don't see the list to store the pointers to media players - did you actually try what was suggested? -
@jsulm
Here is waht I tried as u said . I placed "mediaPlayer" at the start of the program because I need it to use in slots. But it doesn't work .QMediaPlayer *mediaPlayer = new QMediaPlayer(); MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); ui->listWidget->setFlow(QListView::LeftToRight); ui->listWidget->setMinimumSize(760,350); ui->listWidget->setGridSize(QSize(360, 360)); ui->listWidget->setResizeMode(QListView::Adjust); ui->listWidget->setViewMode(QListView::ListMode); ui->listWidget->setWrapping(true); QDir directory = QFileDialog::getExistingDirectory(this, tr("Open Directory"),"/home", QFileDialog::ShowDirsOnly| QFileDialog::DontResolveSymlinks); directory.setNameFilters({"*.mp4" , "*.avi" , "*.flv" , "*.mwv"}); for(const QFileInfo & finfo: directory.entryInfoList()){ //player = new QMediaPlayer(this,QMediaPlayer::VideoSurface); //player = new QVector<QMediaPlayer*>(); //playlist = new QMediaPlaylist; // playlist->addMedia(QUrl::fromLocalFile(finfo.absoluteFilePath())); //mediaPlayer = new QMediaPlayer(); mediaPlayer->setMedia(QUrl::fromLocalFile(finfo.absoluteFilePath())); // mediaPlayer->setMedia(playlist); videoItem = new QGraphicsVideoItem; //videoItem->setSize(QSize(320,240)); QGraphicsScene *scene = new QGraphicsScene(this); QGraphicsView *graphicsView = new QGraphicsView(scene); scene->addItem(videoItem); mediaPlayer->setVideoOutput(videoItem); player.append(mediaPlayer); m_playButton = new QPushButton; m_playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay)); m_positionSlider = new QSlider(Qt::Horizontal); m_positionSlider->setRange(0, 0); connect(m_playButton, &QAbstractButton::clicked, this, &MainWindow::play); connect(m_positionSlider, &QAbstractSlider::sliderMoved,this, &MainWindow::setPosition); connect(mediaPlayer, &QMediaPlayer::stateChanged, this, &MainWindow::mediaStateChanged); connect(mediaPlayer, &QMediaPlayer::positionChanged, this, &MainWindow::positionChanged); connect(mediaPlayer, &QMediaPlayer::durationChanged, this, &MainWindow::durationChanged); auto item = new QListWidgetItem("", ui->listWidget); auto widget = new QWidget; auto label = new QLabel(finfo.fileName()); auto vb = new QVBoxLayout; QBoxLayout *controlLayout = new QHBoxLayout; controlLayout->setMargin(0); controlLayout->addWidget(m_playButton); controlLayout->addWidget(m_positionSlider); vb->addWidget(label,1); vb->addWidget(graphicsView,9); vb->addLayout(controlLayout); widget->setLayout(vb); widget->setMinimumSize(340, 340); ui->listWidget->setItemWidget(item,widget); } }
-
@Kinesis Sorry, but this is not what I suggested, not at all. Why do you use SAME QMediaPlayer for all videos?
What you are currently doing is: you're using the SAME QMediaPlayer for all the video files! This is not going to do what you expect it to do. And I don't see any need to have mediaPlayer as global variable.
I post the code here once more:for(const QFileInfo & finfo: directory.entryInfoList()){ QMediaPlayer *mediaPlayer = new QMediaPlayer(); // You need to create one for each video as you want to show all at the same time, right? mediaPlayer->setMedia(QUrl::fromLocalFile(finfo.absoluteFilePath())); ... mediaPlayer->setVideoOutput(m_videoItem); m_mediaPlayer.append(mediaPlayer);
-
@jsulm
AHH , OK .
But what should I do about slots . I am using slots to play and pause functions . Slots need mediaPlayer to link with actions. In that case *mediaPlayer is not member variable . So I can't use *mediaPlayer in slots. What should I do? -
@Kinesis What is the problem with connect()? You have the pointer to QMediaPlayer inside the loop where you call connect():
for(const QFileInfo & finfo: directory.entryInfoList()){ QMediaPlayer *mediaPlayer = new QMediaPlayer(); // You need to create one for each video as you want to show all at the same time, right? mediaPlayer->setMedia(QUrl::fromLocalFile(finfo.absoluteFilePath())); connect(mediaPlayer, &QMediaPlayer::stateChanged, this, &MainWindow::mediaStateChanged); ... mediaPlayer->setVideoOutput(m_videoItem); m_mediaPlayer.append(mediaPlayer);
-
@jsulm
It keeps showing "error: use of undeclared identifier 'mediaPlayer' " like in this slotvoid MainWindow::play() { switch (mediaPlayer->state()) { case QMediaPlayer::PlayingState: mediaPlayer->pause(); break; default: mediaPlayer->play(); break; } }
-
@Kinesis And how is this related to connect() call?
You need to understand: you have MANY media players, not just one. You put all of them in a list. That means if user presses play you need to get the one media player user wants to play. And then use this player.
Something like:void MainWindow::play() { QMediaPlayer *mediaPlayer = player[currentIndex]; switch (mediaPlayer->state()) { case QMediaPlayer::PlayingState: mediaPlayer->pause(); break; default: mediaPlayer->play(); break; } }
I don't know how to determine the value of currentIndex, as I don't know much about your app.
-
@Kinesis You could use lambda (C++11: https://en.cppreference.com/w/cpp/language/lambda):
connect(m_playButton, &QAbstractButton::clicked, [mediaPlayer]() { switch (mediaPlayer->state()) { case QMediaPlayer::PlayingState: mediaPlayer->pause(); break; default: mediaPlayer->play(); break; } });
-
@jsulm
Thanks . now the buttons are not linked any more. But my first problem is back . I can't play all videos . I can just play 1 video(last video) when I load 2 videos , I can't play any videos when i load more than 2 . I don't know what to do now . I am really stuck at this stage for 4 days. I really appreciate your help for helping until now. -
Are your buttons supposed to control all video players at once ? If so, then do it as I suggested and go it iterate through the vector of players and control them all.
If you want to control each player separately then you have have to create as many buttons as players.
-
@Kinesis said in Media player not working for multiple videos:
I can just play 1 video(last video)
Sounds like you still use global mediaPlayer - do you?
Did you change the code as I suggested?for(const QFileInfo & finfo: directory.entryInfoList()){ QMediaPlayer *mediaPlayer = new QMediaPlayer(); // DO NOT USE GLOBAL mediaPlayer! mediaPlayer->setMedia(QUrl::fromLocalFile(finfo.absoluteFilePath())); ... connect(m_playButton, &QAbstractButton::clicked, [mediaPlayer]() { switch (mediaPlayer->state()) { case QMediaPlayer::PlayingState: mediaPlayer->pause(); break; default: mediaPlayer->play(); break; } }); ... mediaPlayer->setVideoOutput(m_videoItem); m_mediaPlayer.append(mediaPlayer);
-
@jsulm
I am not using mediaPlayer as global variable . Here is my updated codeMainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); ui->listWidget->setFlow(QListView::LeftToRight); ui->listWidget->setMinimumSize(760,350); ui->listWidget->setGridSize(QSize(360, 360)); ui->listWidget->setResizeMode(QListView::Adjust); ui->listWidget->setViewMode(QListView::ListMode); ui->listWidget->setWrapping(true); QDir directory = QFileDialog::getExistingDirectory(this, tr("Open Directory"),"/home", QFileDialog::ShowDirsOnly| QFileDialog::DontResolveSymlinks); directory.setNameFilters({"*.mp4" , "*.avi" , "*.flv" , "*.mwv"}); for(const QFileInfo & finfo: directory.entryInfoList()){ QMediaPlayer *mediaPlayer = new QMediaPlayer(); //player = new QMediaPlayer(this,QMediaPlayer::VideoSurface); //player = new QVector<QMediaPlayer*>(); //playlist = new QMediaPlaylist; // playlist->addMedia(QUrl::fromLocalFile(finfo.absoluteFilePath())); //mediaPlayer = new QMediaPlayer(); mediaPlayer->setMedia(QUrl::fromLocalFile(finfo.absoluteFilePath())); // mediaPlayer->setMedia(playlist); videoItem = new QGraphicsVideoItem; //videoItem->setSize(QSize(320,240)); QGraphicsScene *scene = new QGraphicsScene(this); QGraphicsView *graphicsView = new QGraphicsView(scene); scene->addItem(videoItem); mediaPlayer->setVideoOutput(videoItem); player.append(mediaPlayer); connect(mediaPlayer, &QMediaPlayer::stateChanged, this, &MainWindow::mediaStateChanged); connect(mediaPlayer, &QMediaPlayer::positionChanged, this, &MainWindow::positionChanged); connect(mediaPlayer, &QMediaPlayer::durationChanged, this, &MainWindow::durationChanged); m_playButton = new QPushButton; m_playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay)); m_positionSlider = new QSlider(Qt::Horizontal); m_positionSlider->setRange(0, 0); connect(m_playButton, &QAbstractButton::clicked, this, &MainWindow::play); connect(m_positionSlider, &QAbstractSlider::sliderMoved,this, &MainWindow::setPosition); auto item = new QListWidgetItem("", ui->listWidget); auto widget = new QWidget; auto label = new QLabel(finfo.fileName()); auto vb = new QVBoxLayout; QBoxLayout *controlLayout = new QHBoxLayout; controlLayout->setMargin(0); controlLayout->addWidget(m_playButton); controlLayout->addWidget(m_positionSlider); vb->addWidget(label,1); vb->addWidget(graphicsView,9); vb->addLayout(controlLayout); widget->setLayout(vb); widget->setMinimumSize(340, 340); ui->listWidget->setItemWidget(item,widget); } } MainWindow::~MainWindow() { delete ui; } QSize MainWindow::sizeHint() const { return (videoItem->size() * qreal(3) / qreal(2)).toSize(); } bool MainWindow::isPlayerAvailable() const { QMediaPlayer *mediaPlayer = player[1]; return mediaPlayer->isAvailable(); } void MainWindow::play() { QMediaPlayer *mediaPlayer = player[1]; connect(m_playButton, &QAbstractButton::clicked, [mediaPlayer]() { switch (mediaPlayer->state()) { case QMediaPlayer::PlayingState: mediaPlayer->pause(); break; default: mediaPlayer->play(); break; } }); } void MainWindow::mediaStateChanged(QMediaPlayer::State state) { switch(state) { case QMediaPlayer::PlayingState: m_playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPause)); break; default: m_playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay)); break; } } void MainWindow::positionChanged(qint64 position) { m_positionSlider->setValue(position); } void MainWindow::durationChanged(qint64 duration) { m_positionSlider->setRange(0, duration); } void MainWindow::setPosition(int position) { QMediaPlayer *mediaPlayer = player[1]; mediaPlayer->setPosition(position); }
-
@Kinesis
your still not doing what @jsulm suggested.this
void MainWindow::play() { QMediaPlayer *mediaPlayer = player[1]; connect(m_playButton, &QAbstractButton::clicked, [mediaPlayer]() { switch (mediaPlayer->state()) { case QMediaPlayer::PlayingState: mediaPlayer->pause(); break; default: mediaPlayer->play(); break; } }); }
is wrong and at the wrong place
delete that function all together
and in your loop replace
connect(m_playButton, &QAbstractButton::clicked, this, &MainWindow::play);
with
@jsulm said in Media player not working for multiple videos:
connect(m_playButton, &QAbstractButton::clicked, [mediaPlayer]() { switch (mediaPlayer->state()) { case QMediaPlayer::PlayingState: mediaPlayer->pause(); break; default: mediaPlayer->play(); break; } });