diff --git a/src/DirectMpvPlayerBackend.cpp b/src/DirectMpvPlayerBackend.cpp index bc57a3c..31488ca 100644 --- a/src/DirectMpvPlayerBackend.cpp +++ b/src/DirectMpvPlayerBackend.cpp @@ -99,6 +99,7 @@ DirectMpvPlayerBackend::DirectMpvPlayerBackend(QQuickItem* parent) mpv_observe_property(mpv, 0, "playback-abort", MPV_FORMAT_NONE); mpv_observe_property(mpv, 0, "chapter-list", MPV_FORMAT_NODE); mpv_observe_property(mpv, 0, "track-list", MPV_FORMAT_NODE); + mpv_observe_property(mpv, 0, "chapter-list", MPV_FORMAT_NONE); mpv_observe_property(mpv, 0, "audio-device-list", MPV_FORMAT_NODE); mpv_observe_property(mpv, 0, "playlist-pos", MPV_FORMAT_DOUBLE); mpv_observe_property(mpv, 0, "volume", MPV_FORMAT_NONE); @@ -275,25 +276,7 @@ DirectMpvPlayerBackend::playerCommand(const Enums::Commands& cmd, setProperty("audio-device", args.toString()); break; } - case Enums::Commands::GetAudioDevices: { - QVariant drivers = getProperty("audio-device-list"); - QVariant currentDevice = getProperty("audio-device"); - QVariantMap newDrivers; - - QSequentialIterable iterable = drivers.value(); - foreach (const QVariant& v, iterable) { - QVariantMap item = v.toMap(); - item["selected"] = currentDevice == item["name"]; - newDrivers[item["description"].toString()] = item; - } - QMap pulseItem; - pulseItem["name"] = "pulse"; - pulseItem["description"] = "Default (pulseaudio)"; - pulseItem["selected"] = currentDevice == "pulse"; - newDrivers[pulseItem["description"].toString()] = pulseItem; - return QVariant(newDrivers); - } case Enums::Commands::SetVolume: { command(QVariantList() << "set" << "volume" << args); @@ -400,12 +383,6 @@ DirectMpvPlayerBackend::playerCommand(const Enums::Commands& cmd, break; } - case Enums::Commands::GetTracks: { - - return mpv::qt::get_property_variant(mpv, "track-list"); - - break; - } case Enums::Commands::ForwardFrame: { command(QVariantList() << "frame-step"); @@ -426,13 +403,6 @@ DirectMpvPlayerBackend::playerCommand(const Enums::Commands& cmd, break; } - case Enums::Commands::GetPlaylist: { - - return getProperty("playlist"); - - break; - } - case Enums::Commands::SetPlaylistPos: { command(QVariantList() << "set" @@ -507,6 +477,28 @@ DirectMpvPlayerBackend::updateAppImage() Utils::updateAppImage(); } +QVariantMap +DirectMpvPlayerBackend::getAudioDevices() const +{ + QVariant drivers = getProperty("audio-device-list"); + QVariant currentDevice = getProperty("audio-device"); + + QVariantMap newDrivers; + + QSequentialIterable iterable = drivers.value(); + foreach (const QVariant& v, iterable) { + QVariantMap item = v.toMap(); + item["selected"] = currentDevice == item["name"]; + newDrivers[item["description"].toString()] = item; + } + QMap pulseItem; + pulseItem["name"] = "pulse"; + pulseItem["description"] = "Default (pulseaudio)"; + pulseItem["selected"] = currentDevice == "pulse"; + newDrivers[pulseItem["description"].toString()] = pulseItem; + return newDrivers; +} + void DirectMpvPlayerBackend::handle_mpv_event(mpv_event* event) { @@ -566,11 +558,13 @@ DirectMpvPlayerBackend::handle_mpv_event(mpv_event* event) emit playStatusChanged(Enums::PlayStatus::Playing); } } else if (strcmp(prop->name, "tracks-menu") == 0) { - emit tracksChanged(); + emit tracksChanged(getProperty("tracks-menu").toList()); } else if (strcmp(prop->name, "audio-device-list") == 0) { - emit audioDevicesChanged(); + emit audioDevicesChanged(getAudioDevices()); } else if (strcmp(prop->name, "playlist") == 0) { - emit playlistChanged(); + emit playlistChanged(getProperty("playlist").toList()); + } else if (strcmp(prop->name, "chapter-list") == 0) { + emit chaptersChanged(getProperty("chapter-list").toList()); } #ifdef DISCORD updateDiscord(); diff --git a/src/DirectMpvPlayerBackend.h b/src/DirectMpvPlayerBackend.h index ff5a0ca..6c4020f 100644 --- a/src/DirectMpvPlayerBackend.h +++ b/src/DirectMpvPlayerBackend.h @@ -66,6 +66,9 @@ public slots: void swapped(); void cleanup(); + // Just used for adding missing audio devices to list. + QVariantMap getAudioDevices() const; + signals: void onUpdate(); void mpv_events(); @@ -80,9 +83,10 @@ signals: void titleChanged(const QString& title); void subtitlesChanged(const QString& subtitles); void durationStringChanged(const QString& string); - void tracksChanged(); - void audioDevicesChanged(); - void playlistChanged(); + void tracksChanged(const QVariantList& tracks); + void audioDevicesChanged(const QVariantMap& devices); + void playlistChanged(const QVariantList& devices); + void chaptersChanged(const QVariantList& devices); private slots: void doUpdate(); diff --git a/src/MpvPlayerBackend.cpp b/src/MpvPlayerBackend.cpp index 4d8905c..e4beff8 100644 --- a/src/MpvPlayerBackend.cpp +++ b/src/MpvPlayerBackend.cpp @@ -135,6 +135,7 @@ MpvPlayerBackend::MpvPlayerBackend(QQuickItem* parent) mpv_set_option_string(mpv, "config", "yes"); // mpv_set_option_string(mpv, "sub-visibility", "no"); mpv_observe_property(mpv, 0, "tracks-menu", MPV_FORMAT_NONE); + mpv_observe_property(mpv, 0, "chapter-list", MPV_FORMAT_NONE); mpv_observe_property(mpv, 0, "playback-abort", MPV_FORMAT_NONE); mpv_observe_property(mpv, 0, "chapter-list", MPV_FORMAT_NODE); mpv_observe_property(mpv, 0, "track-list", MPV_FORMAT_NODE); @@ -265,25 +266,6 @@ MpvPlayerBackend::playerCommand(const Enums::Commands& cmd, setProperty("audio-device", args.toString()); break; } - case Enums::Commands::GetAudioDevices: { - QVariant drivers = getProperty("audio-device-list"); - QVariant currentDevice = getProperty("audio-device"); - - QVariantMap newDrivers; - - QSequentialIterable iterable = drivers.value(); - foreach (const QVariant& v, iterable) { - QVariantMap item = v.toMap(); - item["selected"] = currentDevice == item["name"]; - newDrivers[item["description"].toString()] = item; - } - QMap pulseItem; - pulseItem["name"] = "pulse"; - pulseItem["description"] = "Default (pulseaudio)"; - pulseItem["selected"] = currentDevice == "pulse"; - newDrivers[pulseItem["description"].toString()] = pulseItem; - return QVariant(newDrivers); - } case Enums::Commands::SetVolume: { command(QVariantList() << "set" << "volume" << args); @@ -390,12 +372,6 @@ MpvPlayerBackend::playerCommand(const Enums::Commands& cmd, break; } - case Enums::Commands::GetTracks: { - - return mpv::qt::get_property_variant(mpv, "track-list"); - - break; - } case Enums::Commands::ForwardFrame: { command(QVariantList() << "frame-step"); @@ -416,13 +392,6 @@ MpvPlayerBackend::playerCommand(const Enums::Commands& cmd, break; } - case Enums::Commands::GetPlaylist: { - - return getProperty("playlist"); - - break; - } - case Enums::Commands::SetPlaylistPos: { command(QVariantList() << "set" @@ -474,6 +443,28 @@ MpvPlayerBackend::updateAppImage() Utils::updateAppImage(); } +QVariantMap +MpvPlayerBackend::getAudioDevices() const +{ + QVariant drivers = getProperty("audio-device-list"); + QVariant currentDevice = getProperty("audio-device"); + + QVariantMap newDrivers; + + QSequentialIterable iterable = drivers.value(); + foreach (const QVariant& v, iterable) { + QVariantMap item = v.toMap(); + item["selected"] = currentDevice == item["name"]; + newDrivers[item["description"].toString()] = item; + } + QMap pulseItem; + pulseItem["name"] = "pulse"; + pulseItem["description"] = "Default (pulseaudio)"; + pulseItem["selected"] = currentDevice == "pulse"; + newDrivers[pulseItem["description"].toString()] = pulseItem; + return newDrivers; +} + void MpvPlayerBackend::handle_mpv_event(mpv_event* event) { @@ -533,11 +524,13 @@ MpvPlayerBackend::handle_mpv_event(mpv_event* event) emit playStatusChanged(Enums::PlayStatus::Playing); } } else if (strcmp(prop->name, "tracks-menu") == 0) { - emit tracksChanged(); + emit tracksChanged(getProperty("track-list").toList()); } else if (strcmp(prop->name, "audio-device-list") == 0) { - emit audioDevicesChanged(); + emit audioDevicesChanged(getAudioDevices()); } else if (strcmp(prop->name, "playlist") == 0) { - emit playlistChanged(); + emit playlistChanged(getProperty("playlist").toList()); + } else if (strcmp(prop->name, "chapter-list") == 0) { + emit chaptersChanged(getProperty("chapter-list").toList()); } #ifdef DISCORD updateDiscord(); diff --git a/src/MpvPlayerBackend.h b/src/MpvPlayerBackend.h index 5806f28..71e209c 100644 --- a/src/MpvPlayerBackend.h +++ b/src/MpvPlayerBackend.h @@ -47,6 +47,8 @@ public slots: void setProperty(const QString& name, const QVariant& value); void setOption(const QString& name, const QVariant& value); QVariant getProperty(const QString& name) const; + // Just used for adding missing audio devices to list. + QVariantMap getAudioDevices() const; signals: void onUpdate(); @@ -62,9 +64,10 @@ signals: void titleChanged(const QString& title); void subtitlesChanged(const QString& subtitles); void durationStringChanged(const QString& string); - void tracksChanged(); - void audioDevicesChanged(); - void playlistChanged(); + void tracksChanged(const QVariantList& tracks); + void audioDevicesChanged(const QVariantMap& devices); + void playlistChanged(const QVariantList& devices); + void chaptersChanged(const QVariantList& devices); private slots: void doUpdate(); diff --git a/src/backendinterface.hpp b/src/backendinterface.hpp index 23eb53d..96fb014 100644 --- a/src/backendinterface.hpp +++ b/src/backendinterface.hpp @@ -38,8 +38,10 @@ signals: virtual void titleChanged(const QString& title) = 0; virtual void subtitlesChanged(const QString& subtitles) = 0; virtual void durationStringChanged(const QString& string) = 0; - virtual void tracksChanged() = 0; - virtual void audioDevicesChanged() = 0; + virtual void tracksChanged(const QVariantList& tracks) = 0; + virtual void audioDevicesChanged(const QVariantMap& devices) = 0; + virtual void playlistChanged(const QVariantList& devices) = 0; + virtual void chaptersChanged(const QVariantList& devices) = 0; }; Q_DECLARE_INTERFACE(BackendInterface, "NamedKitten.BackendInterface"); diff --git a/src/enums.hpp b/src/enums.hpp index 4d3b153..71a1f74 100644 --- a/src/enums.hpp +++ b/src/enums.hpp @@ -24,29 +24,26 @@ enum class Commands : int TogglePlayPause = 0, ToggleMute = 1, SetAudioDevice = 2, - GetAudioDevices = 3, - AddVolume = 4, - SetVolume = 5, - AddSpeed = 6, - SubtractSpeed = 7, - ChangeSpeed = 8, - SetSpeed = 9, - ToggleStats = 10, - NextAudioTrack = 11, - NextVideoTrack = 12, - NextSubtitleTrack = 13, - PreviousPlaylistItem = 14, - NextPlaylistItem = 15, - LoadFile = 16, - AppendFile = 17, - Seek = 18, - SeekAbsolute = 19, - GetTracks = 20, - ForwardFrame = 21, - BackwardFrame = 22, - SetTrack = 23, - GetPlaylist = 24, - SetPlaylistPos = 25 + AddVolume = 3, + SetVolume = 4, + AddSpeed = 5, + SubtractSpeed = 6, + ChangeSpeed = 7, + SetSpeed = 8, + ToggleStats = 9, + NextAudioTrack = 10, + NextVideoTrack = 11, + NextSubtitleTrack = 12, + PreviousPlaylistItem = 13, + NextPlaylistItem = 14, + LoadFile = 15, + AppendFile = 16, + Seek = 17, + SeekAbsolute = 18, + ForwardFrame = 19, + BackwardFrame = 20, + SetTrack = 21, + SetPlaylistPos = 22, }; Q_ENUM_NS(Commands) enum class Backends : int diff --git a/src/qml/ChapterMarker.qml b/src/qml/ChapterMarker.qml new file mode 100644 index 0000000..7963bd3 --- /dev/null +++ b/src/qml/ChapterMarker.qml @@ -0,0 +1,20 @@ +import QtQuick 2.11 +import QtQuick.Controls 2.4 +import Qt.labs.settings 1.0 +import player 1.0 + +Rectangle { + id: chapterMarker + property int time: 0 + color: appearance.chapterMarkerColor + Component.onCompleted: { + player.chaptersChanged.connect(chapterMarker.destroy) + } + + width: 4 + height: parent.height + anchors.top: parent.top + anchors.bottom: parent.bottom + x: progressBar.background.width / progressBar.to * time + z: 9000 +} diff --git a/src/qml/ControlsBar.qml b/src/qml/ControlsBar.qml index 74b9223..039a2a8 100644 --- a/src/qml/ControlsBar.qml +++ b/src/qml/ControlsBar.qml @@ -122,7 +122,7 @@ Item { progressBar.to = duration }) player.cachedDurationChanged.connect(function (duration) { - cachedLength.value = progressBar.value + duration + cachedLength.duration = duration }) } onMoved: { @@ -149,11 +149,9 @@ Item { id: progressBackground x: progressBar.leftPadding y: progressBar.topPadding + progressBar.availableHeight / 2 - height / 2 - implicitHeight: progressBar.getProgressBarHeight( - fun.nyanCat, - mouseAreaProgressBar.containsMouse) width: progressBar.availableWidth - height: implicitHeight + height: progressBar.getProgressBarHeight( + fun.nyanCat, mouseAreaProgressBar.containsMouse) color: appearance.progressBackgroundColor ProgressBar { id: cachedLength @@ -168,37 +166,50 @@ Item { } z: 40 to: progressBar.to + property int duration + value: progressBar.value + duration anchors.fill: parent } - ProgressBar { - z: 50 - id: progressLength - width: parent.width - height: parent.height - to: progressBar.to - value: progressBar.value - opacity: 1 - anchors.leftMargin: 0 - background: Item { + + Item { + anchors.fill: parent + id: chapterMarkers + Component.onCompleted: { + player.chaptersChanged.connect(chaptersChanged) } - contentItem: Item { - Rectangle { - width: progressLength.visualPosition * parent.width - + progressBar.handle.width / 2 - height: parent.height - color: appearance.progressSliderColor - Image { - visible: fun.nyanCat - id: rainbow - anchors.fill: parent - height: parent.height - width: parent.width - source: "qrc:/player/icons/rainbow.png" - fillMode: Image.TileHorizontally - } + function chaptersChanged(chapters) { + console.log(JSON.stringify(chapters)) + for (var i = 0, len = chapters.length; i < len; i++) { + var chapter = chapters[i] + var component = Qt.createComponent( + "ChapterMarker.qml") + + var marker = component.createObject(chapterMarkers, + { + time: chapter["time"] + }) } } } + + Rectangle { + id: progressLength + z: 50 + anchors.left: progressBackground.left + width: progressBar.visualPosition * parent.width + + (progressBar.handle.width / 2) + height: parent.height + color: appearance.progressSliderColor + Image { + visible: fun.nyanCat + id: rainbow + anchors.fill: parent + height: parent.height + width: parent.width + source: "qrc:/player/icons/rainbow.png" + fillMode: Image.TileHorizontally + } + } } handle: Rectangle { diff --git a/src/qml/MainMenu.qml b/src/qml/MainMenu.qml index 1054067..5000964 100644 --- a/src/qml/MainMenu.qml +++ b/src/qml/MainMenu.qml @@ -24,9 +24,10 @@ MenuBar { player.tracksChanged.connect(updateTracks) } - function updateTracks() { + function updateTracks(tracks) { + var newTracks = tracks var trackMenus = [audioMenu, videoMenu, subMenu] - for (var a = 0; i < trackMenus.length; a++) { + for (var a = 0; a < trackMenus.length; a++) { var menu = trackMenus[a] for (var i = 0, len = menu.count; i < len; i++) { var action = menu.actionAt(i) @@ -36,8 +37,6 @@ MenuBar { } } - var newTracks = player.playerCommand(Enums.Commands.GetTracks) - for (var i = 0, len = newTracks.length; i < len; i++) { var track = newTracks[i] var trackID = track["id"] @@ -45,8 +44,8 @@ MenuBar { var trackLang = LanguageCodes.localeCodeToEnglish( String(track["lang"])) var trackTitle = track["title"] + var component = Qt.createComponent("TrackItem.qml") if (trackType == "sub") { - var component = Qt.createComponent("TrackItem.qml") var action = component.createObject(subMenu, { text: trackLang, trackID: String( @@ -57,7 +56,6 @@ MenuBar { action.ActionGroup.group = subMenuGroup subMenu.addAction(action) } else if (trackType == "audio") { - var component = Qt.createComponent("TrackItem.qml") var action = component.createObject(audioMenu, { text: (trackTitle == undefined ? "" : trackTitle + " ") + (trackLang == "undefined" ? "" : trackLang), trackID: String( @@ -68,7 +66,6 @@ MenuBar { action.ActionGroup.group = audioMenuGroup audioMenu.addAction(action) } else if (trackType == "video") { - var component = Qt.createComponent("TrackItem.qml") var action = component.createObject(videoMenu, { text: "Video " + trackID, trackID: String( @@ -346,10 +343,7 @@ MenuBar { Component.onCompleted: { player.audioDevicesChanged.connect(updateAudioDevices) } - function updateAudioDevices() { - var audioDevices = player.playerCommand( - Enums.Commands.GetAudioDevices) - + function updateAudioDevices(audioDevices) { for (var i = 0, len = audioDeviceMenu.count; i < len; i++) { audioDeviceMenu.takeAction(0) } diff --git a/src/qml/main.qml b/src/qml/main.qml index 16dd351..d93fc47 100644 --- a/src/qml/main.qml +++ b/src/qml/main.qml @@ -31,6 +31,7 @@ ApplicationWindow { property string progressCachedColor: "white" property string buttonColor: "white" property string progressSliderColor: "red" + property string chapterMarkerColor: "#fc0" } Settings { id: i18n diff --git a/src/qml/qml.qrc b/src/qml/qml.qrc index f4dabaa..46212fa 100644 --- a/src/qml/qml.qrc +++ b/src/qml/qml.qrc @@ -1,6 +1,7 @@ main.qml + ChapterMarker.qml PlaylistDialog.qml CustomComboBox.qml CustomMenuItem.qml