【问题标题】:Audio playlist in QMLQML 中的音频播放列表
【发布时间】:2015-12-07 11:17:11
【问题描述】:

我正在 qml 上制作一个简单的播放列表播放器。我的意思是有一个Audio 播放器可以播放文件夹中扩展名为.mp3 的文件。但是这个“播放列表播放器”将整个文件夹假定为一个播放列表。因此,我将播放列表文件夹的路径作为命令行参数提供给程序,例如。 ./playlist_player /home/user/playlist-folder 和程序在播放列表文件夹中播放整个 mp3。但是由于 qml 不理解像星号(*)这样的通配符,我使用QDir 来查找 mp3 的名称以查找 mp3 的名称,并使用此处描述的方法将这些字符串暴露给 qml http://doc.qt.io/qt-5/qtqml-cppintegration-exposecppattributes.html。所以我有一个 QObject 派生类名称FileNames,它有Q_PROPERTY(QStringList mp3List READ mp3List)。因此,在FileNames 的构造函数中,我查找命令行中给出的路径,并检测扩展名为.mp3s 的文件并将这些路径推回FileNames::mp3List。在main.cpp 上,我在实例化QQuickView 对象之后实例化一个FileNames 对象,然后使用QQmlContext::setContextProperty 成员函数将FileNames 对象传递给Qml 端。

一切正常,直到我还需要列表中的 mp3 数量来迭代所有 next 函数,该函数增加 qml 端列表的 index 值。我知道我可以公开另一个属性来传递mp3List 的计数,但我最终得到的这个解决方案可能不是最好的原生解决方案。

这是我写的代码;

/* filenames.h */

class FileNames : public QObject {
    Q_OBJECT
    Q_PROPERTY(QStringList mp3List READ mp3List)
    Q_PROPERTY(int mp3ListCount READ mp3ListCount)
public:
    explicit FileNames(QObject *parent = 0);

    QStringList mp3List() const;
    int mp3ListCount() const;
private:
    QStringList m_mp3List;
    int m_mp3ListCount;
};

/* filenames.cpp */

FileNames::FileNames(QObject *parent) :
    QObject(parent), m_mp3ListCount(0)
{
    QString path("/home/user/music/");
    QDir dirname(path);
    QStringList dir = dirname.entryList();

    for (const auto &file : dir)
        if (file.endsWith(".mp3")) {
            m_mp3List.push_back("file://" + path + file);
            ++m_mp3ListCount;
        }
}

QStringList FileNames::mp3List() const
{
    return m_mp3List;
}

int FileNames::mp3ListCount() const
{
    return m_mp3ListCount;
}

/* main.cpp */

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    FileNames names;

    QQuickView view;

    view.engine()->rootContext()->setContextProperty("names", &names);

    view.setSource(QUrl(QStringLiteral("qrc:///main.qml")));

    view.setResizeMode(QQuickView::SizeRootObjectToView);

    view.showFullScreen();

    return app.exec();
}

/* Playlist.qml */

Item {
    id: root

    property int index: 0
    property MediaPlayer mediaPlayer
    property variant list;
    property int listCount;

    function setIndex(i)
    {
        console.log("setting index to: " + i);
        index = i;
        if (index < 0 || index >= listCount) {
            index = 0;
            mediaPlayer.source = "";
        }
        mediaPlayer.source = list[index];
    }

    function next()
    {
        setIndex(index + 1);
    }

    function previous()
    {
        setIndex(index + 1);
    }

    Connections {
        target: root.mediaPlayer

        onStopped: {
            if (root.mediaPlayer.status == MediaPlayer.EndOfMedia)
            {
                root.next();
                root.mediaPlayer.play();
            }
        }
    }
}

/* main.qml */

Rectangle {
    id: root

    width: 1024
    height: 600

    color: "black"

    Playlist {

        id: playlist

        mediaPlayer: player

        list: names.mp3List
        listCount: names.mp3ListCount
    }

    MediaPlayer {
        id: player
    }

    VideoOutput {
        anchors.fill: parent

        source: player
    }
}

那么有没有人有更多的原生解决方案来使用 Qt 制作“playlist_player”应用程序?

更新->

所以现在我正在使用FolderListModel,但似乎这个类在没有视图的情况下无法正常工作。我猜是因为它是异步工​​作的。这是我的代码的样子;

/* Playlist.qml */
Item {
    id: root

    property int index: 0
    property MediaPlayer mediaPlayer
    property FolderListModel fm

    function setIndex(i)
    {
        index = i;
        console.log("setting index to: " + i);
        index %= fm.count;
        mediaPlayer.source = "file://" + fm.get(index, "filePath");
        console.log("setting source to: " + mediaPlayer.source);

    }

    function next()
    {
        setIndex(index + 1);
    }

    function previous()
    {
        setIndex(index + 1);
    }

    Connections {
        target: root.mediaPlayer

        onStopped: {
            if (root.mediaPlayer.status == MediaPlayer.EndOfMedia) {
                root.next();
                root.mediaPlayer.play();
            }
        }
    }
}

/* main.qml */
Rectangle {
    id: root
    width: 1024
    height: 600
    color: "black"

    property bool onStart: true

    Playlist {
        id: playlist
        mediaPlayer: player

        fm: FolderListModel {
            id: fm
            folder: "file:///home/user/music"
            showDirs: false
            showDotAndDotDot: false
            nameFilters: ["*.mp3"]
            property bool ready: count > 0
            // startup initialization;
            onReadyChanged: if (player.status == MediaPlayer.NoMedia) {
                                playlist.setIndex(0);
                                player.play();
                            }
        }
    }

    MediaPlayer { id: player }

    VideoOutput {
        anchors.fill: parent
        source: player
    }
}

谢谢你, 新浪网。

【问题讨论】:

    标签: qt audio qml qtquick2 playlist


    【解决方案1】:

    当需要与 C++ 代码集成时,在 QML 中使用 C++ 类型或定义上下文属性非常好。 C++ 自然地扩展了 QML 的可能性,何时需要 C++ 后端类或用 C++ 编写的新 QML 类型只是一个理解问题。有关此主题的进一步讨论,请查看this other answer

    鉴于上面链接的答案和播放列表组件的生命周期,使用 QML 类型而不是上下文属性将是正确的选择。但是,如前所述,QML 已经为您提供了正确的组件:FolderListModel。在你的情况下,它可以很容易地定义如下:

    FolderListModel {
        id: folderModel
        nameFilters: ["*.mp3"]
        showDirs: false
        folder: "file:" + /* CPP PROVIDED PATH */
    }
    

    您可以使用get 函数根据count 属性查询列表中的下一个mp3。

    一个很大的优势是FolderListModel确实监听文件夹中的文件更改,因此您不需要检查文件添加/删除。最后但同样重要的是,FolderListModel 可以轻松集成到 GUI 实现中,将其用作ListView 的模型。示例请参见here

    附录

    正如 OP 所述,FolderListModel 异步工作。这是一种常见的行为,因为在组件初始化期间进行所有检查可能会导致长时间启动(尤其是对于充满文件的目录)。当FolderListModel 完成对文件系统的跟踪时,没有要跟踪的属性,因为文件系统检查是连续的,所以拥有一个可能也没有意义。添加bool 属性可能会有所帮助,如下所示:

    FolderListModel {
        id: fm
        folder: "..."
        showDirs: false
        showDotAndDotDot: false
        nameFilters: ["*.mp3"]
        property bool ready: count > 0
    }
    

    ready 为真时(因为已添加mp3 或初始扫描已完成),可能会触发播放器。显然,可以添加其他属性来改进模型的行为。

    【讨论】:

      【解决方案2】:

      FolderListModel QML 类型将满足您的需求。支持名称过滤等。

      【讨论】:

        猜你喜欢
        • 2021-10-17
        • 1970-01-01
        • 1970-01-01
        • 2011-03-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多