[UI+Backend] Optimizations and Chapter Markers.
This commit is contained in:
parent
37158fbcad
commit
e7c0e1af92
|
@ -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<QSequentialIterable>();
|
||||
foreach (const QVariant& v, iterable) {
|
||||
QVariantMap item = v.toMap();
|
||||
item["selected"] = currentDevice == item["name"];
|
||||
newDrivers[item["description"].toString()] = item;
|
||||
}
|
||||
QMap<QString, QVariant> 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<QSequentialIterable>();
|
||||
foreach (const QVariant& v, iterable) {
|
||||
QVariantMap item = v.toMap();
|
||||
item["selected"] = currentDevice == item["name"];
|
||||
newDrivers[item["description"].toString()] = item;
|
||||
}
|
||||
QMap<QString, QVariant> 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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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<QSequentialIterable>();
|
||||
foreach (const QVariant& v, iterable) {
|
||||
QVariantMap item = v.toMap();
|
||||
item["selected"] = currentDevice == item["name"];
|
||||
newDrivers[item["description"].toString()] = item;
|
||||
}
|
||||
QMap<QString, QVariant> 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<QSequentialIterable>();
|
||||
foreach (const QVariant& v, iterable) {
|
||||
QVariantMap item = v.toMap();
|
||||
item["selected"] = currentDevice == item["name"];
|
||||
newDrivers[item["description"].toString()] = item;
|
||||
}
|
||||
QMap<QString, QVariant> 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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
20
src/qml/ChapterMarker.qml
Normal file
20
src/qml/ChapterMarker.qml
Normal file
|
@ -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
|
||||
}
|
|
@ -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,23 +166,38 @@ 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 {
|
||||
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 {
|
||||
width: progressLength.visualPosition * parent.width
|
||||
+ progressBar.handle.width / 2
|
||||
id: progressLength
|
||||
z: 50
|
||||
anchors.left: progressBackground.left
|
||||
width: progressBar.visualPosition * parent.width
|
||||
+ (progressBar.handle.width / 2)
|
||||
height: parent.height
|
||||
color: appearance.progressSliderColor
|
||||
Image {
|
||||
|
@ -198,8 +211,6 @@ Item {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handle: Rectangle {
|
||||
z: 70
|
||||
|
|
|
@ -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"]
|
||||
if (trackType == "sub") {
|
||||
var component = Qt.createComponent("TrackItem.qml")
|
||||
if (trackType == "sub") {
|
||||
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)
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ ApplicationWindow {
|
|||
property string progressCachedColor: "white"
|
||||
property string buttonColor: "white"
|
||||
property string progressSliderColor: "red"
|
||||
property string chapterMarkerColor: "#fc0"
|
||||
}
|
||||
Settings {
|
||||
id: i18n
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<RCC>
|
||||
<qresource prefix="/player">
|
||||
<file>main.qml</file>
|
||||
<file>ChapterMarker.qml</file>
|
||||
<file>PlaylistDialog.qml</file>
|
||||
<file>CustomComboBox.qml</file>
|
||||
<file>CustomMenuItem.qml</file>
|
||||
|
|
Loading…
Reference in a new issue