Evgenii Legotckoi
29 червня 2016 р. 19:06

Qt/C++ - Урок 051. QMediaPlayer – простий аудіоплеєр

Пропоную написати простенький аудіо плеєр для mp3 файлів з використанням Qt/C++, який матиме плейлист, можливість запуску/паузи/зупинки треків, а також перегортання треків.

Для реалізації цього задуму в Qt є класи QMediaPlayer та QMediaPlaylist, які відносяться до модуля multimedia. А для відображення плейлиста скористаємося QStandardItemModel та QTableView.

Статті цього циклу:

Структура проекта

  • SimplePlayer.pro - профайл проекту;
  • main.cpp - файл із функцією main;
  • widget.ui - файл форми вікна програми;
  • widget.h - заголовний файл вікна програми;
  • widget.cpp - файл вихідних кодів вікна програми;
  • buttons.qrc - ресурсний файл іконок кнопок програми.

widget.ui

Інтерфейс програми зробимо з використанням графічного дизайнера, і виглядатиме він повинен буде таким чином.

До складу інтерфейсу програми входять такі елементи:

  • btn_add (QToolButton*) - відповідає за додавання треків у плейлист;
  • btn_next (QToolButton*) - відповідає за прогортання плейлиста вперед;
  • btn_previous (QToolButton*) - відповідає за прогортання плейлиста назад;
  • btn_play (QToolButton*) - відповідає за відтворення треку;
  • btn_pause (QToolButton*) - відповідає за постановку треку на паузу;
  • btn_stop (QToolButton*) - відповідає за зупинку треку;
  • currentTrack (QLabel*) - лейбл, в якому відображатиметься поточний трек;
  • playlistView (QTableView*) - таблиця, що відповідає за відображення плейлиста.

SimplePlayer.pro

У профайлі проекту не забудьте підключити модуль *multimedia, інакше класи QMediaPlayer та QMediaPlaylist будуть недоступні.

#-------------------------------------------------
#
# Project created by QtCreator 2016-06-29T11:25:56
#
#-------------------------------------------------

QT       += core gui multimedia

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = SimplePlayer
TEMPLATE = app


SOURCES += main.cpp\
        widget.cpp

HEADERS  += widget.h

FORMS    += widget.ui

RESOURCES += \
    buttons.qrc

віджет.h

Для реалізації відображення плейлиста доведеться використовувати QStandardItemModel. У ній будуть розміщуватися шляхи до аудіо файлів, а також імена аудіо файлів. У першій колонці буде ім'я аудіо файлу, а в другій буде повний шлях, але ця колонка буде прихована в об'єкті QTableView, який відповідатиме за відображення плейлиста.

Також шляхи до файлів як медіа джерел необхідно буде помістити в об'єкт QMediaPlaylist, який буде розміщено в QMediaPlayer.

Вказівники на ці об'єкти розміщуються у заголовному файлі вікна програми. Також тут є автогенерований через дизайнер інтерфейсів слот для обробки натискання по кнопці додавання треків у плейлист.

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QStandardItemModel>
#include <QMediaPlayer>
#include <QMediaPlaylist>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

private slots:
    void on_btn_add_clicked();              // Слот для обработки добавления треков через диалоговое окно

private:
    Ui::Widget *ui;
    QStandardItemModel  *m_playListModel;   // Модель данных плейлиста для отображения
    QMediaPlayer        *m_player;          // Проигрыватель треков
    QMediaPlaylist      *m_playlist;        // Плейлиста проигрывателя
};

#endif // WIDGET_H

widget.cpp

Для реалізації плеєра необхідно ініціалізувати об'єкти QMediaPlayer, QMediaPlaylist та QStandardItemModel, які були оголошені у заголовному файлі вікна програми. У першій половині конструктора проводиться налаштування зовнішнього вигляду таблиці для відображення плейлиста, тоді як у другій настройка плеєра. Керування плеєром здійснюється через кнопки, які підключені до керуючих слотів m_playlist (для навігації) та m_player (для запуску/паузи/зупинки).

При зміні поточного треку, плеєр автоматично завершує відтворення того, який трек був до зміни, і запускає на відтворення новий трек.

Через те, що QMediaPlaylist не має моделі для відображення в таблиці, ми скористаємося класом QStandardItemModel, тому доведеться додавати дані про шляхи до файлів і туди, і туди.

#include "widget.h"
#include "ui_widget.h"
#include <QFileDialog>
#include <QDir>

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    // Настройка таблицы плейлиста
    m_playListModel = new QStandardItemModel(this);
    ui->playlistView->setModel(m_playListModel);    // Устанавливаем модель данных в TableView
    // Устанавливаем заголовки таблицы
    m_playListModel->setHorizontalHeaderLabels(QStringList()  << tr("Audio Track")
                                                            << tr("File Path"));
    ui->playlistView->hideColumn(1);    // Скрываем колонку, в которой хранится путь к файлу
    ui->playlistView->verticalHeader()->setVisible(false);                  // Скрываем нумерацию строк
    ui->playlistView->setSelectionBehavior(QAbstractItemView::SelectRows);  // Включаем выделение строк
    ui->playlistView->setSelectionMode(QAbstractItemView::SingleSelection); // Разрешаем выделять только одну строку
    ui->playlistView->setEditTriggers(QAbstractItemView::NoEditTriggers);   // Отключаем редактирование
    // Включаем подгонку размера последней видимой колонки к ширине TableView
    ui->playlistView->horizontalHeader()->setStretchLastSection(true);

    m_player = new QMediaPlayer(this);          // Инициализируем плеер
    m_playlist = new QMediaPlaylist(m_player);  // Инициализируем плейлист
    m_player->setPlaylist(m_playlist);          // Устанавливаем плейлист в плеер
    m_player->setVolume(70);                    // Устанавливаем громкость воспроизведения треков
    m_playlist->setPlaybackMode(QMediaPlaylist::Loop);  // Устанавливаем циклический режим проигрывания плейлиста

    // подключаем кнопки управления к слотам управления
    // Здесь отметим, что навигация по плейлисту осуществляется именно через плейлист
    // а запуск/пауза/остановка через сам плеер
    connect(ui->btn_previous, &QToolButton::clicked, m_playlist, &QMediaPlaylist::previous);
    connect(ui->btn_next, &QToolButton::clicked, m_playlist, &QMediaPlaylist::next);
    connect(ui->btn_play, &QToolButton::clicked, m_player, &QMediaPlayer::play);
    connect(ui->btn_pause, &QToolButton::clicked, m_player, &QMediaPlayer::pause);
    connect(ui->btn_stop, &QToolButton::clicked, m_player, &QMediaPlayer::stop);

    // При даблклике по треку в таблице устанавливаем трек в плейлисте
    connect(ui->playlistView, &QTableView::doubleClicked, [this](const QModelIndex &index){
        m_playlist->setCurrentIndex(index.row());
    });

    // при изменении индекса текущего трека в плейлисте, устанавливаем название файла в специальном лейбле
    connect(m_playlist, &QMediaPlaylist::currentIndexChanged, [this](int index){
        ui->currentTrack->setText(m_playListModel->data(m_playListModel->index(index, 0)).toString());
    });
}

Widget::~Widget()
{
    delete ui;
    delete m_playListModel;
    delete m_playlist;
    delete m_player;
}

void Widget::on_btn_add_clicked()
{
    // С помощью диалога выбора файлов делаем множественный выбор mp3 файлов
    QStringList files = QFileDialog::getOpenFileNames(this,
                                                      tr("Open files"),
                                                      QString(),
                                                      tr("Audio Files (*.mp3)"));

    // Далее устанавливаем данные по именам и пути к файлам
    // в плейлист и таблицу отображающую плейлист
    foreach (QString filePath, files) {
        QList<QStandardItem *> items;
        items.append(new QStandardItem(QDir(filePath).dirName()));
        items.append(new QStandardItem(filePath));
        m_playListModel->appendRow(items);
        m_playlist->addMedia(QUrl(filePath));
    }
}

Підсумок

Після того, як програма запуститься, Ви зможете відкрити mp3 треки та прослухати їх.

Скачать Qt Audio Player

Відеоурок

Рекомендовані статті на цю тему

По статті запитували1питання

7

Вам це подобається? Поділіться в соціальних мережах!

S
  • 10 червня 2017 р. 13:26

Скажите, пожалуйста, как на линуксе исправить ошибку , связанную с непраильной схемой пути к файлу - "Error: "Invalid URI ...."" и далее соответственно GSteamer; unable to pause...

На официальном форуме указано на то, что "when passing local file to the media player, you need to use the "file://" scheme so it knows it has to look in to the file system." Но что конкретно из этого стоит вынести, не ясно.
Благодарен за внимание.
Evgenii Legotckoi
  • 10 червня 2017 р. 20:35

Ответил на форуме

DV
  • 28 квітня 2021 р. 01:40

Добрый вечер. Хотел бы получить консультацию по работе с проектом на Mac OS. Открыл проект в QT и собрал его. Проблема в том, что он не воспроизводит треки и их названия зацикленно мелькают в поле текущего трека. По системе:
- Mac OS 10.14
- QT 5.15.2
- XCode 10.2
С чем это может быть связано. Заранее благодарен.

Evgenii Legotckoi
  • 02 липня 2021 р. 15:09

С Mac OS опыта работы не имею на данный момент

АГ
  • 21 червня 2022 р. 15:48

можно ли из этого плеера сделать многоканалов воспроизведения ?

Evgenii Legotckoi
  • 21 червня 2022 р. 15:54

нет

АГ
  • 21 червня 2022 р. 16:07

есть такая вообще возможность ?

Evgenii Legotckoi
  • 21 червня 2022 р. 16:26
  • (відредаговано)

Не думаю, QMediaPlayer в один поток проигрывает. Если вам нужно одновременное воспроизведение нескольких аудиоисточников, то вам нужна Bass audio library , насколько знаю, её обычно используют для подобных вещей.

Р5
  • 13 вересня 2022 р. 18:54

Здравствуйте. Подскажите пожалуйста, как решить проблему
multimedia модуль не распознается

juvf
  • 25 листопада 2022 р. 12:14

Добрый день.
Подскажите, как можно перехватить в Qt или Qml уровень воспроизводимого звука? Т.е. требуется сделать виртуальный винтажный индикатор (стрелочный или светодиодный), который бы показывал уровень звука. И желательно без усилиения. Т.е. в файле mp3 допустим записана синусоида 1000 кГц, амплитудой 0.5 (минимальный уровень 0.0, макс 1.0), то на индикаторе должно быть 0.5, в независимости от того, как выкручена громкость на регуляторе звука плеера, винды/линукса, калонок или внешнего УМ. Как такое возможно реализовать (желательно кроссплатформено с помощью qt/qml)? Куда копать? Как-то перехватывать декодирование mp3 и допустим раз в 100 мс обновлять виджет "Индикатор"?

Evgenii Legotckoi
  • 12 грудня 2022 р. 15:05

Qt не располагает средствами для визуализации формы звукового сигнала в файле. То есть из модуля Qt multimedia вы не сможете забрать график звука а потом его обработать так, чтобы вы получали нужный вам результат. Это нужно реализовывать с помощью сторонних библиотек, а потом отрисовывать уже в Qt/Qml. Возможно Bass Dll может в этом помочь.

juvf
  • 12 грудня 2022 р. 15:06

Спасибо.

juvf
  • 17 січня 2023 р. 09:18

PS. Почти дописал плеер на QML. Уперся в ограничения QML. Переписываю плеер на с++/qt, а графика останится в qml. Нашел то, что мне надо, а именно индикатор звука. Qt может перехватывать аудиопоток и анализировать уровень звука. Кому интересно - подробно в примерах в QtCreator "Media Player Example".

Evgenii Legotckoi
  • 07 лютого 2023 р. 16:32

А он анализирует уровень звука по частотам, как эквайлайзер? Я просто подумал, что вам как в аналоговом эквалайзере нужно...

Коментарі

Only authorized users can post comments.
Please, Log in or Sign up