1
0
Fork 0

[UI+Backend] Optimizations and Chapter Markers.

This commit is contained in:
NamedKitten 2018-11-24 14:35:34 +00:00
parent 37158fbcad
commit e7c0e1af92
11 changed files with 161 additions and 141 deletions

View file

@ -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();

View file

@ -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();

View file

@ -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();

View file

@ -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();

View file

@ -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");

View file

@ -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
View 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
}

View file

@ -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 {

View file

@ -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)
}

View file

@ -31,6 +31,7 @@ ApplicationWindow {
property string progressCachedColor: "white"
property string buttonColor: "white"
property string progressSliderColor: "red"
property string chapterMarkerColor: "#fc0"
}
Settings {
id: i18n

View file

@ -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>