Smart Pointer

导航

QT创建一个媒体播放器

编码:mainwindow.h

我们已经为我们的应用程序创建了框架,现在只要添加功能即可。点击“mainwindow.h”,并在顶部添加如下代码行:

#include <QList>

#include <QFileDialog>

#include <QDesktopServices>

#include <Phonon>

以上代码的作用是,通过头文件导入我们要在代码中使用的Qt函数。现在我们需要添加我们的槽,它们在我们前面编辑过的ui文件中已经定义好了。在“public:”部分中的“~MainWindow();”行正下方,添加如下代码:

private slots:

    void playPause();

    void addFiles();

    void nextFile();

    void aboutToFinish();

    void finished();

可以看到,这些槽对应于我们在用户界面中创建的名称,而且我们还添加了更多的槽来处理内部通信。最后,在“private”部分中添加如下变量,我们将在应用程序的主要逻辑中用到这些变量:

    QList<Phonon::MediaSource> sources;

    Phonon::MediaObject *mediaObject;

    Phonon::AudioOutput *audioOutput;

    Phonon::MediaObject *metaInformationResolver;

编码:mainwindow.cpp

现在,我们需要做的第一件事情是初始化Phonon,并建立内部的信号和槽。这可以通过标准的初始化方法MainWindow::MainWindow来完成。如果你看一看这个方法的内容,就会发现应用程序的GUI是由“ui->setupUi(this);”行来运行的。这意味着,我们需要在这之前加入我们的预运行代码。我们将从设置Phonon开始:

     audioOutput = new Phonon::AudioOutput(Phonon::MusicCategory, this);

     mediaObject = new Phonon::MediaObject(this);

     metaInformationResolver = new Phonon::MediaObject(this);

     Phonon::createPath(mediaObject, audioOutput);

Phonon术语中,我们要创建的audioOutput对象叫做音频接收槽。它是直接与音频驱动器通信的层的组成部分,并充当MediaObject的虚拟音频设备。MediaObject位于这一层的上层,增加了诸如暂停、播放和倒带之类的功能。顺便提一句,MusicCategory不一定是必需的,但它可以对未来发展起到作用,比如可以根据正在收听的内容自动变化的KDE均衡器。

我们将使用“metaInformationResolver”来指向当前音频文件,而最后一行在接收槽和媒体对象之间建立了连接。Phonon使用了一种叫做“graph”的框架,这意味着对象就像是一幅图上的节点,需要连接起来才能创建流向。这正是以上代码的最后一行的作用。

现在添加如下用于处理playPause()槽的新函数:

void MainWindow::playPause()

{

    switch (mediaObject->state()){

        case Phonon::PlayingState:

            mediaObject->pause();

            ui->pushButtonPlay->setChecked(false);

            break;

        case Phonon::PausedState:

            mediaObject->play();

            break;

        case Phonon::StoppedState:

            mediaObject->play();

            break;

        case Phonon::LoadingState:

            ui->pushButtonPlay->setChecked(false);

            break;

    }

}

以上代码应该不难理解。我们使用一条Case语句检查播放的当前状态。Phonon通过MediaObject为我们提供了这种功能。它实际上就是一个整数,但是每个值代表着特定的状态。例如,如果应用程序是首次启动,播放列表中尚未加入任何文件,就会返回LoadingState值。播放和暂停由媒体对象进行处理,在“mediaObject->pause();”命令之后将自动从当前位置继续。

* Creator中输入代码时,可使用自动完成功能找到所需函数。

我们还尝试给用户提供一些关于当前播放状态的反馈。如果音乐正在播放,我们会让“Play”按钮凹下去,使其看起来好像是被按下一样。如果音乐处于任意其他状态,我们会让“Play”按钮恢复原样,使其看起来处于停止状态。为了实现这一点,需要将播放按钮取名为“pushButtonPlay”。可以在Designer视图中修改它的名称,方法是选择该按钮并修改“objectName”值。

void MainWindow::addFiles()

{

    QStringList files = QFileDialog::getOpenFileNames(this, tr("Select Music Files"),

        QDesktopServices::storageLocation(QDesktopServices::MusicLocation));

 

    ui->pushButtonPlay->setChecked(false);

    if (files.isEmpty())

        return;

    int index = sources.size();

    foreach (QString string, files) {

            Phonon::MediaSource source(string);

            sources.append(source);

    }

    if (!sources.isEmpty()){

        metaInformationResolver->setCurrentSource(sources.at(index));

        mediaObject->setCurrentSource(metaInformationResolver->currentSource()); 

    }

}

现在,让我们开始实现添加文件的部分。创建文件请求器几乎是自动的,我们可以把结果放到一个字符串列表中。“QdesktopServices::MusicLocation”返回一个通常用于保存音乐文件的特定操作系统位置,而我们使用它作为请求器的起始位置。接下来,我们将把已经选择的每个音乐文件添加到我们早先创建的“metaInformationResolver”中,并使用它告诉mediaObject接下来播放哪个文件。

在所有这些工作间隙,我们进行一点清理工作,以确保队列中有文件,而且当处于播放状态时出现播放按钮。添加文件将自动停止播放。

void MainWindow::nextFile()

{ 

    int index = sources.indexOf(mediaObject->currentSource()) + 1; 

    if (sources.size() > index) {

         mediaObject->stop();

         mediaObject->setCurrentSource(sources.at(index));

         mediaObject->play();

     }

}

 

void MainWindow::aboutToFinish()

{

     int index = sources.indexOf(mediaObject->currentSource()) + 1;

     if (sources.size() > index) {

         mediaObject->enqueue(sources.at(index));

     }

   else {

         ui->pushButtonPlay->setChecked(false);

     }

}

void MainWindow::finished()

{

        ui->pushButtonPlay->setChecked(false);

}

 

posted on 2011-07-28 21:56  Smart Pointer  阅读(636)  评论(0编辑  收藏  举报