├── .gitignore ├── .travis.yml ├── .tx └── config ├── DOCS ├── codebase.svg ├── codebase2.svg ├── coding standards.md └── ipc.md ├── LICENSE ├── README.md ├── binaries └── .gitignore ├── bintray.json ├── favoriteswindow.cpp ├── favoriteswindow.h ├── favoriteswindow.ui ├── helpers.cpp ├── helpers.h ├── http └── index.html ├── images ├── icon │ ├── mpc-qt.svg │ └── tinyicon.svg ├── logo │ ├── film-color.svg │ ├── film-gray.svg │ ├── mpv-vlc.svg │ └── triangle-circle.svg └── theme │ ├── black │ ├── document-export.svg │ ├── document-import.svg │ ├── go-next.svg │ ├── go-previous.svg │ ├── media-playback-pause.svg │ ├── media-playback-start.svg │ ├── media-playback-stop.svg │ ├── media-queue-visible.svg │ ├── media-seek-backward.svg │ ├── media-seek-forward.svg │ ├── media-skip-backward.svg │ ├── media-skip-forward.svg │ ├── player-volume-muted.svg │ ├── player-volume.svg │ ├── tab-close.svg │ ├── tab-duplicate.svg │ ├── tab-new.svg │ ├── video-x-generic-16.svg │ ├── video-x-generic-32.svg │ ├── view-media-queue.svg │ ├── view-media-subtitles-hidden.svg │ ├── view-media-subtitles.svg │ ├── zone-in.svg │ └── zone-out.svg │ └── white │ ├── document-export.svg │ ├── document-import.svg │ ├── go-next.svg │ ├── go-previous.svg │ ├── media-playback-pause.svg │ ├── media-playback-start.svg │ ├── media-playback-stop.svg │ ├── media-queue-visible.svg │ ├── media-seek-backward.svg │ ├── media-seek-forward.svg │ ├── media-skip-backward.svg │ ├── media-skip-forward.svg │ ├── player-volume-muted.svg │ ├── player-volume.svg │ ├── tab-close.svg │ ├── tab-duplicate.svg │ ├── tab-new.svg │ ├── video-x-generic-16.svg │ ├── video-x-generic-32.svg │ ├── view-media-queue.svg │ ├── view-media-subtitles-hidden.svg │ ├── view-media-subtitles.svg │ ├── zone-in.svg │ └── zone-out.svg ├── ipc ├── http.cpp ├── http.h ├── json.cpp ├── json.h ├── mpris.cpp └── mpris.h ├── librarywindow.cpp ├── librarywindow.h ├── librarywindow.ui ├── logger.cpp ├── logger.h ├── logwindow.cpp ├── logwindow.h ├── logwindow.ui ├── main.cpp ├── main.h ├── mainwindow.cpp ├── mainwindow.h ├── mainwindow.ui ├── make-mac-icon.sh ├── make-release-mac.py ├── make-release-win.sh ├── make-win-icon.sh ├── manager.cpp ├── manager.h ├── mpc-qt.desktop ├── mpc-qt.pro ├── mpv-dev ├── include │ └── mpv │ │ └── .gitignore └── lib │ └── .gitignore ├── mpvwidget.cpp ├── mpvwidget.h ├── openfiledialog.cpp ├── openfiledialog.h ├── openfiledialog.ui ├── platform ├── devicemanager.cpp ├── devicemanager.h ├── devicemanager_mac.cpp ├── devicemanager_mac.h ├── devicemanager_unix.cpp ├── devicemanager_unix.h ├── devicemanager_win.cpp ├── devicemanager_win.h ├── screensaver.cpp ├── screensaver.h ├── screensaver_mac.cpp ├── screensaver_mac.h ├── screensaver_unix.cpp ├── screensaver_unix.h ├── screensaver_win.cpp ├── screensaver_win.h ├── unify.cpp └── unify.h ├── playlist.cpp ├── playlist.h ├── playlistwindow.cpp ├── playlistwindow.h ├── playlistwindow.ui ├── propertieswindow.cpp ├── propertieswindow.h ├── propertieswindow.ui ├── qthelper.hpp ├── res.qrc ├── settingswindow.cpp ├── settingswindow.h ├── settingswindow.ui ├── storage.cpp ├── storage.h ├── text ├── encodeFormat.html └── playlistFormat.html ├── thumbnailerwindow.cpp ├── thumbnailerwindow.h ├── thumbnailerwindow.ui ├── translations ├── mpc-qt_en.ts ├── mpc-qt_es.ts ├── mpc-qt_fi.ts ├── mpc-qt_it.ts ├── mpc-qt_ru.ts └── mpc-qt_zh_CN.ts └── widgets ├── actioneditor.cpp ├── actioneditor.h ├── drawncollection.cpp ├── drawncollection.h ├── drawnplaylist.cpp ├── drawnplaylist.h ├── drawnslider.cpp ├── drawnslider.h ├── drawnstatus.cpp ├── drawnstatus.h ├── logowidget.cpp ├── logowidget.h ├── paletteeditor.cpp └── paletteeditor.h /.gitignore: -------------------------------------------------------------------------------- 1 | # C++ objects and libs 2 | 3 | *.slo 4 | *.lo 5 | *.o 6 | *.a 7 | *.la 8 | *.lai 9 | *.so 10 | *.dll 11 | *.dylib 12 | 13 | # Windows resources 14 | *.rc 15 | *.ico 16 | 17 | # Qt-es 18 | ======= 19 | 20 | /.qmake.cache 21 | /.qmake.stash 22 | *.pro.user 23 | *.pro.user.* 24 | *.qbs.user 25 | *.qbs.user.* 26 | *.moc 27 | moc_*.cpp 28 | moc_*.h 29 | qrc_*.cpp 30 | ui_*.h 31 | Makefile* 32 | *-build-* 33 | mpc-qt 34 | 35 | # QtCreator 36 | 37 | *.autosave 38 | 39 | #QtCtreator Qml 40 | *.qmlproject.user 41 | *.qmlproject.user.* 42 | 43 | #Python 44 | *.pyc 45 | 46 | # qmake 47 | /release/ 48 | /debug/ 49 | /object_script.*.Debug 50 | /object_script.*.Release 51 | /resources/translations/ 52 | 53 | # make release scripts 54 | /mpc-qt-*/ 55 | *.zip 56 | *.sha512 57 | 58 | # transifex 59 | .transifexrc 60 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | osx_image: xcode9.2 3 | 4 | branches: 5 | only: 6 | - master 7 | 8 | script: 9 | - qmake mpc-qt.pro 10 | - make -j2 11 | - make install 12 | - macdeployqt mpc-qt.app -libpath=/usr/local/lib/ 13 | - python macdeployqtfix/macdeployqtfix.py mpc-qt.app/Contents/MacOS/mpc-qt $(pkg-config --variable=prefix Qt5Gui) -v 14 | 15 | before_install: 16 | - brew update 17 | - brew install pkgconfig 18 | - brew install mpv 19 | - brew install qt 20 | - brew link qt --force 21 | - brew install librsvg 22 | 23 | install: 24 | - git clone --branch v0.29.1 https://github.com/mpv-player/mpv.git 25 | - cp mpv/libmpv/* $(pkg-config --variable=includedir mpv)/mpv/ 26 | - rm -rf mpv 27 | - git clone https://github.com/arl/macdeployqtfix.git 28 | - git fetch --unshallow 29 | - ln -s /usr/local/opt/python/Frameworks/Python.framework /usr/local/opt/python/lib/ 30 | 31 | before_deploy: 32 | - ls -al 33 | - pip3 install dmgbuild 34 | - dmgbuild -s make-release-mac.py "mpc-qt" mpc-qt.dmg 35 | 36 | deploy: 37 | skip_cleanup: true 38 | on: master 39 | provider: bintray 40 | file: "bintray.json" 41 | user: alby128 42 | key: 43 | secure: "h1ZKUCkLilR6NDlrF73g1GHFFVCN2F8dDBnJNwiYaUPZT4znToZwZE8Qh2ukLaz2jjIr2d6fxN+jV1TLJPjq5v7HRsXEJZjy64Fp0OniO3SGpzEvnQZL+58RUwmQU0Y+VeBbDLmyu5wNrLbmXZnjeK1OcJYM1CV6qxHP+uQA5QCxkCqa4/MP5/rmpTRNu/iz0zQD1qSrqf0q61xCG+aJCnX6JhQvs4w1UXdU4Qy53OfAeI1kDq7Fwpoa+AxOMfXvnIy9Yo0igdi64s8e8klv+uaqJ/TvslFDslqbivNOZuXv1+wZCq+ac4npPtDMQZyWoBvMZ0U24LJ3e24en2OsRcQBXdaiTS1r4PAstVn7VjFWgbgzgGTBSKlqucGgxg0O3RsX+GiG1yHjsIJ9JF9AtBn9Awcy5NMJsOi9meLN+AgEOVtMIEVWDH8m5jMK+aCHYsm7tEBYcjFpTaYl3/t9EaPeqjKpOvUNSJDTfSnsuIXKp233GIiIDWbMXzLWCR8F1Ijk9FNTJqtJECpBpZOUiHkPN95NPxz98w0CW6rDYjJmZImNYpgflSQ4gzH2w3bfqgvJJqbrsa1imZqMzH+JrmlUFfmZAwNfPJOrKJbSUsZisH8CNvL4x4wHt7iOhZSsT6nO8idkDP0ukKpXJ0qbKluU2Fqfvl1nNIxRYFFkyQs=" 44 | -------------------------------------------------------------------------------- /.tx/config: -------------------------------------------------------------------------------- 1 | [main] 2 | host = https://www.transifex.com 3 | 4 | [mpc-qt.mpc-qt-translations] 5 | file_filter = translations/mpc-qt_.ts 6 | minimum_perc = 0 7 | source_file = translations/mpc-qt_en.ts 8 | source_lang = en_US 9 | type = QT 10 | 11 | -------------------------------------------------------------------------------- /binaries/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /bintray.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": { 3 | "name": "mpc-qt", 4 | "repo": "mpc-qt", 5 | "subject": "alby128" 6 | }, 7 | "version": { 8 | "name": "v18.08" 9 | }, 10 | "files": [ 11 | { 12 | "includePattern": "./(.*\\.dmg)", 13 | "uploadPattern": "$1", 14 | "matrixParams": { 15 | "override": 1 16 | } 17 | } 18 | ], 19 | "publish": true 20 | } 21 | -------------------------------------------------------------------------------- /favoriteswindow.h: -------------------------------------------------------------------------------- 1 | #ifndef FAVORITESWINDOW_H 2 | #define FAVORITESWINDOW_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "helpers.h" 8 | 9 | namespace Ui { 10 | class FavoritesWindow; 11 | } 12 | 13 | class FavoritesList; 14 | class FavoritesModel; 15 | class FavoritesDelegate; 16 | 17 | class FavoritesWindow : public QWidget 18 | { 19 | Q_OBJECT 20 | 21 | public: 22 | explicit FavoritesWindow(QWidget *parent = nullptr); 23 | ~FavoritesWindow(); 24 | 25 | signals: 26 | void favoriteTracks(QList files, QList streams); 27 | 28 | public slots: 29 | void setFiles(const QList &tracks); 30 | void setStreams(const QList &tracks); 31 | void addTrack(const TrackInfo &track); 32 | void updateFavoriteTracks(); 33 | 34 | private slots: 35 | void on_remove_clicked(); 36 | 37 | private: 38 | Ui::FavoritesWindow *ui; 39 | FavoritesList *fileList; 40 | FavoritesList *streamList; 41 | }; 42 | 43 | class FavoritesList : public QListWidget 44 | { 45 | Q_OBJECT 46 | 47 | public: 48 | explicit FavoritesList(QWidget *parent = nullptr); 49 | ~FavoritesList(); 50 | TrackInfo getTrack(int index); 51 | void setTracks(const QList &tracks); 52 | void addTrack(const TrackInfo &track); 53 | QList tracks(); 54 | }; 55 | 56 | class FavoritesItem : public QListWidgetItem 57 | { 58 | public: 59 | explicit FavoritesItem(QListWidget *owner, const TrackInfo &t); 60 | ~FavoritesItem(); 61 | TrackInfo &track() { return track_; } 62 | private: 63 | TrackInfo track_; 64 | }; 65 | 66 | 67 | class FavoritesDelegate : public QAbstractItemDelegate 68 | { 69 | Q_OBJECT 70 | 71 | public: 72 | explicit FavoritesDelegate(QWidget *parent = nullptr); 73 | ~FavoritesDelegate(); 74 | QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const; 75 | virtual void setEditorData(QWidget *editor, const QModelIndex &index) const; 76 | virtual void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const; 77 | virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const; 78 | virtual void paint(QPainter *painter, 79 | const QStyleOptionViewItem &option, 80 | const QModelIndex &index) const; 81 | virtual void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const; 82 | 83 | private: 84 | FavoritesList *owner; 85 | }; 86 | 87 | #endif // FAVORITESWINDOW_H 88 | -------------------------------------------------------------------------------- /favoriteswindow.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | FavoritesWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 555 10 | 298 11 | 12 | 13 | 14 | Organize Favorites 15 | 16 | 17 | 18 | 19 | 20 | &Update 21 | 22 | 23 | 24 | 25 | 26 | 27 | 0 28 | 29 | 30 | 31 | &Files 32 | 33 | 34 | 35 | 36 | 37 | &Streams 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | &Remove 47 | 48 | 49 | 50 | 51 | 52 | 53 | Qt::Horizontal 54 | 55 | 56 | 57 | 40 58 | 20 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /http/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | MPC-HC WebServer 6 | 7 | 8 |

Welcome to the MPC-HC WebServer (mpc-qt compat). 9 |

Send the player a command: 10 |

11 | 13 | 14 |
15 |

File browser 16 |

Media player interface 17 |

Info page 18 |

Variables page 19 | 20 | 21 | -------------------------------------------------------------------------------- /images/icon/mpc-qt.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | 24 | 47 | 52 | 53 | 55 | 56 | 58 | image/svg+xml 59 | 61 | 62 | 63 | 64 | 65 | 70 | 78 | 79 | 84 | 90 | 102 | 109 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /images/theme/black/document-export.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 45 | 51 | 52 | 54 | 55 | 57 | image/svg+xml 58 | 60 | 61 | 62 | 63 | 64 | 69 | 75 | 81 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /images/theme/black/document-import.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 45 | 51 | 52 | 54 | 55 | 57 | image/svg+xml 58 | 60 | 61 | 62 | 63 | 64 | 69 | 75 | 81 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /images/theme/black/go-next.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 42 | 46 | 47 | 49 | 50 | 52 | image/svg+xml 53 | 55 | 56 | 57 | 58 | 59 | 64 | 72 | 78 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /images/theme/black/go-previous.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 42 | 46 | 47 | 49 | 50 | 52 | image/svg+xml 53 | 55 | 56 | 57 | 58 | 59 | 64 | 71 | 77 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /images/theme/black/media-playback-pause.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 42 | 46 | 47 | 49 | 50 | 52 | image/svg+xml 53 | 55 | 56 | 57 | 58 | 59 | 64 | 71 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /images/theme/black/media-playback-start.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 42 | 46 | 47 | 49 | 50 | 52 | image/svg+xml 53 | 55 | 56 | 57 | 58 | 59 | 64 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /images/theme/black/media-playback-stop.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 42 | 46 | 47 | 49 | 50 | 52 | image/svg+xml 53 | 55 | 56 | 57 | 58 | 59 | 64 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /images/theme/black/media-seek-backward.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 42 | 46 | 47 | 49 | 50 | 52 | image/svg+xml 53 | 55 | 56 | 57 | 58 | 59 | 64 | 70 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /images/theme/black/media-seek-forward.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 42 | 46 | 47 | 49 | 50 | 52 | image/svg+xml 53 | 55 | 56 | 57 | 58 | 59 | 64 | 70 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /images/theme/black/media-skip-backward.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 42 | 46 | 47 | 49 | 50 | 52 | image/svg+xml 53 | 55 | 56 | 57 | 58 | 59 | 64 | 71 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /images/theme/black/media-skip-forward.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 42 | 46 | 47 | 49 | 50 | 52 | image/svg+xml 53 | 55 | 56 | 57 | 58 | 59 | 64 | 72 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /images/theme/black/player-volume-muted.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 42 | 48 | 49 | 51 | 52 | 54 | image/svg+xml 55 | 57 | 58 | 59 | 60 | 61 | 66 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /images/theme/black/player-volume.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 42 | 48 | 49 | 51 | 52 | 54 | image/svg+xml 55 | 57 | 58 | 59 | 60 | 61 | 66 | 72 | 77 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /images/theme/black/tab-close.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 45 | 51 | 52 | 54 | 55 | 57 | image/svg+xml 58 | 60 | 61 | 62 | 63 | 64 | 69 | 74 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /images/theme/black/tab-duplicate.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 45 | 51 | 52 | 54 | 55 | 57 | image/svg+xml 58 | 60 | 61 | 62 | 63 | 64 | 69 | 75 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /images/theme/black/tab-new.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 45 | 51 | 52 | 54 | 55 | 57 | image/svg+xml 58 | 60 | 61 | 62 | 63 | 64 | 69 | 75 | 80 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /images/theme/black/video-x-generic-16.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 29 | 31 | 52 | 58 | 59 | -------------------------------------------------------------------------------- /images/theme/black/video-x-generic-32.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 40 | 44 | 45 | 47 | 48 | 50 | image/svg+xml 51 | 53 | 54 | 55 | 56 | 57 | 62 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /images/theme/black/view-media-subtitles.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 45 | 51 | 52 | 54 | 55 | 57 | image/svg+xml 58 | 60 | 61 | 62 | 63 | 64 | 69 | 75 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /images/theme/black/zone-in.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 42 | 48 | 49 | 51 | 52 | 54 | image/svg+xml 55 | 57 | 58 | 59 | 60 | 61 | 66 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /images/theme/black/zone-out.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 42 | 48 | 49 | 51 | 52 | 54 | image/svg+xml 55 | 57 | 58 | 59 | 60 | 61 | 66 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /images/theme/white/document-export.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 45 | 51 | 52 | 54 | 55 | 57 | image/svg+xml 58 | 60 | 61 | 62 | 63 | 64 | 69 | 75 | 81 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /images/theme/white/document-import.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 45 | 51 | 52 | 54 | 55 | 57 | image/svg+xml 58 | 60 | 61 | 62 | 63 | 64 | 69 | 75 | 81 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /images/theme/white/go-next.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 42 | 46 | 47 | 49 | 50 | 52 | image/svg+xml 53 | 55 | 56 | 57 | 58 | 59 | 64 | 72 | 78 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /images/theme/white/go-previous.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 42 | 46 | 47 | 49 | 50 | 52 | image/svg+xml 53 | 55 | 56 | 57 | 58 | 59 | 64 | 71 | 77 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /images/theme/white/media-playback-pause.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 42 | 46 | 47 | 49 | 50 | 52 | image/svg+xml 53 | 55 | 56 | 57 | 58 | 59 | 64 | 71 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /images/theme/white/media-playback-start.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 42 | 46 | 47 | 49 | 50 | 52 | image/svg+xml 53 | 55 | 56 | 57 | 58 | 59 | 64 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /images/theme/white/media-playback-stop.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 42 | 46 | 47 | 49 | 50 | 52 | image/svg+xml 53 | 55 | 56 | 57 | 58 | 59 | 64 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /images/theme/white/media-seek-backward.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 42 | 46 | 47 | 49 | 50 | 52 | image/svg+xml 53 | 55 | 56 | 57 | 58 | 59 | 64 | 70 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /images/theme/white/media-seek-forward.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 42 | 46 | 47 | 49 | 50 | 52 | image/svg+xml 53 | 55 | 56 | 57 | 58 | 59 | 64 | 70 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /images/theme/white/media-skip-backward.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 42 | 46 | 47 | 49 | 50 | 52 | image/svg+xml 53 | 55 | 56 | 57 | 58 | 59 | 64 | 71 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /images/theme/white/media-skip-forward.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 42 | 46 | 47 | 49 | 50 | 52 | image/svg+xml 53 | 55 | 56 | 57 | 58 | 59 | 64 | 72 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /images/theme/white/player-volume-muted.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 42 | 48 | 49 | 51 | 52 | 54 | image/svg+xml 55 | 57 | 58 | 59 | 60 | 61 | 66 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /images/theme/white/player-volume.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 42 | 48 | 49 | 51 | 52 | 54 | image/svg+xml 55 | 57 | 58 | 59 | 60 | 61 | 66 | 72 | 77 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /images/theme/white/tab-close.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 45 | 51 | 52 | 54 | 55 | 57 | image/svg+xml 58 | 60 | 61 | 62 | 63 | 64 | 69 | 74 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /images/theme/white/tab-duplicate.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 45 | 51 | 52 | 54 | 55 | 57 | image/svg+xml 58 | 60 | 61 | 62 | 63 | 64 | 69 | 75 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /images/theme/white/tab-new.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 45 | 51 | 52 | 54 | 55 | 57 | image/svg+xml 58 | 60 | 61 | 62 | 63 | 64 | 69 | 75 | 80 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /images/theme/white/video-x-generic-16.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 29 | 31 | 52 | 58 | 59 | -------------------------------------------------------------------------------- /images/theme/white/video-x-generic-32.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 40 | 44 | 45 | 47 | 48 | 50 | image/svg+xml 51 | 53 | 54 | 55 | 56 | 57 | 62 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /images/theme/white/view-media-subtitles.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 45 | 51 | 52 | 54 | 55 | 57 | image/svg+xml 58 | 60 | 61 | 62 | 63 | 64 | 69 | 75 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /images/theme/white/zone-in.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 42 | 48 | 49 | 51 | 52 | 54 | image/svg+xml 55 | 57 | 58 | 59 | 60 | 61 | 66 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /images/theme/white/zone-out.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 42 | 48 | 49 | 51 | 52 | 54 | image/svg+xml 55 | 57 | 58 | 59 | 60 | 61 | 66 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /ipc/http.h: -------------------------------------------------------------------------------- 1 | #ifndef IPCHTTP_H 2 | #define IPCHTTP_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class QAction; 10 | 11 | class HttpRequest { 12 | public: 13 | QString method; 14 | QString url; 15 | QMap headers; 16 | QMap getVars; 17 | QMap postVars; 18 | }; 19 | 20 | class HttpResponse { 21 | public: 22 | HttpResponse(); 23 | 24 | enum HttpStatus { 25 | Http200Ok = 200, 26 | Http204NoContent = 204, 27 | Http301MovedPermanently = 301, 28 | Http302Found = 302, 29 | Http303SeeOther = 303, 30 | Http400BadRequest = 400, 31 | Http401Unauthorized = 401, 32 | Http403Forbidden = 403, 33 | Http404NotFound = 404, 34 | Http500InternalServerError = 500, 35 | Http501NotImplemented = 501, 36 | }; 37 | 38 | HttpStatus statusCode; 39 | QDateTime dateResponse; 40 | QDateTime dateModified; 41 | QString contentType; 42 | QByteArray content; 43 | 44 | QString statusLine; 45 | QMap headers; 46 | 47 | bool fallthrough; 48 | 49 | void fillHeaders(); 50 | void redirect(QString where); 51 | void serveFile(QString filename); 52 | }; 53 | 54 | 55 | class HttpServer : public QTcpServer 56 | { 57 | Q_OBJECT 58 | public: 59 | HttpServer(QObject *owner = nullptr); 60 | void clearRoutes(); 61 | void route(QString path, std::function callback); 62 | static QString extensionToContentType(QString extension); 63 | static QString urlDecode(QString urlText, bool plusToSpace = false); 64 | static QString urlEncode(QString plainText); 65 | 66 | private: 67 | void sendSocket(QTcpSocket *sock, HttpResponse &res); 68 | 69 | private slots: 70 | void self_newConnection(); 71 | void socket_readyRead(QTcpSocket *sock); 72 | 73 | private: 74 | QList>> routeMap; 75 | }; 76 | 77 | 78 | class MpcHcServer : public QObject 79 | { 80 | Q_OBJECT 81 | 82 | class WmCommand { 83 | public: 84 | int id; 85 | const char *text; 86 | std::function func; 87 | }; 88 | 89 | public: 90 | explicit MpcHcServer(QObject *owner = nullptr); 91 | 92 | public slots: 93 | void setDefaultPage(QString file); 94 | void setEnabled(bool yes); 95 | void setLocalHostOnly(bool yes); 96 | void setTcpPort(uint16_t port); 97 | void setServeFiles(bool yes); 98 | void setWebRoot(QString path); 99 | 100 | private: 101 | void relisten(); 102 | void setupWmCommands(); 103 | void setupHttp(); 104 | 105 | HttpServer http; 106 | QList wmCommands; 107 | QMap wmCommandsById; 108 | 109 | QString defaultPage = "index.html"; 110 | bool enabled = false; 111 | bool localHostOnly = true; 112 | uint16_t tcpPort = 13579; 113 | bool serveFiles = false; 114 | QString webRoot; 115 | }; 116 | 117 | 118 | #endif // IPCHTTP_H 119 | -------------------------------------------------------------------------------- /librarywindow.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "playlist.h" 3 | #include "widgets/drawncollection.h" 4 | #include "widgets/drawnplaylist.h" 5 | #include "librarywindow.h" 6 | #include "ui_librarywindow.h" 7 | 8 | LibraryWindow::LibraryWindow(QWidget *parent) : 9 | QWidget(parent), 10 | ui(new Ui::LibraryWindow) 11 | { 12 | ui->setupUi(this); 13 | 14 | collectionWidget = new DrawnCollection(PlaylistCollection::getBackup()); 15 | ui->collectionLayout->addWidget(collectionWidget); 16 | 17 | playlistWidget = new DrawnPlaylist(PlaylistCollection::getBackup()); 18 | ui->playlistLayout->addWidget(playlistWidget); 19 | 20 | connect(collectionWidget, &DrawnCollection::playlistSelected, 21 | playlistWidget, &DrawnPlaylist::setUuid); 22 | } 23 | 24 | LibraryWindow::~LibraryWindow() 25 | { 26 | delete ui; 27 | } 28 | 29 | void LibraryWindow::refreshLibrary() 30 | { 31 | collectionWidget->repopulatePlaylists(); 32 | } 33 | 34 | void LibraryWindow::closeEvent(QCloseEvent *event) 35 | { 36 | event->accept(); 37 | emit windowClosed(); 38 | } 39 | 40 | void LibraryWindow::on_restorePlaylist_clicked() 41 | { 42 | int currentRow = collectionWidget->currentRow(); 43 | if (currentRow == -1) 44 | return; 45 | auto collectionItem = reinterpret_cast(collectionWidget->currentItem()); 46 | auto playlistCollection = PlaylistCollection::getSingleton(); 47 | auto backupCollection = PlaylistCollection::getBackup(); 48 | 49 | auto playlistTaken = backupCollection->takePlaylist(collectionItem->uuid()); 50 | playlistCollection->addPlaylist(playlistTaken); 51 | 52 | emit playlistRestored(playlistTaken->uuid()); 53 | delete collectionWidget->takeItem(currentRow); 54 | } 55 | 56 | void LibraryWindow::on_removePlaylist_clicked() 57 | { 58 | int currentRow = collectionWidget->currentRow(); 59 | if (currentRow == -1) 60 | return; 61 | auto backupCollection = PlaylistCollection::getBackup(); 62 | auto collectionItem = reinterpret_cast(collectionWidget->currentItem()); 63 | backupCollection->removePlaylist(collectionItem->uuid()); 64 | delete collectionWidget->takeItem(currentRow); 65 | } 66 | -------------------------------------------------------------------------------- /librarywindow.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBRARYWINDOW_H 2 | #define LIBRARYWINDOW_H 3 | 4 | #include 5 | #include 6 | 7 | QT_BEGIN_NAMESPACE 8 | namespace Ui { 9 | class LibraryWindow; 10 | } 11 | QT_END_NAMESPACE 12 | 13 | class DrawnPlaylist; 14 | class DrawnCollection; 15 | 16 | class LibraryWindow : public QWidget 17 | { 18 | Q_OBJECT 19 | 20 | public: 21 | explicit LibraryWindow(QWidget *parent = nullptr); 22 | ~LibraryWindow(); 23 | 24 | public slots: 25 | void refreshLibrary(); 26 | 27 | signals: 28 | void windowClosed(); 29 | void playlistRestored(QUuid playlistUuid); 30 | 31 | protected: 32 | void closeEvent(QCloseEvent *event); 33 | 34 | private slots: 35 | void on_restorePlaylist_clicked(); 36 | 37 | void on_removePlaylist_clicked(); 38 | 39 | private: 40 | Ui::LibraryWindow *ui; 41 | DrawnPlaylist *playlistWidget; 42 | DrawnCollection *collectionWidget; 43 | }; 44 | 45 | #endif // LIBRARYWINDOW_H 46 | -------------------------------------------------------------------------------- /librarywindow.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | LibraryWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 400 10 | 300 11 | 12 | 13 | 14 | Library 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | Restore 29 | 30 | 31 | 32 | 33 | 34 | 35 | Remove 36 | 37 | 38 | 39 | 40 | 41 | 42 | Qt::Horizontal 43 | 44 | 45 | 46 | 40 47 | 20 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | Close 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | closeWindow 67 | clicked() 68 | LibraryWindow 69 | close() 70 | 71 | 72 | 349 73 | 276 74 | 75 | 76 | 199 77 | 149 78 | 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /logger.h: -------------------------------------------------------------------------------- 1 | #ifndef LOGGER_H 2 | #define LOGGER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | // Logger class, alternatively thought of as the LogBuffer class. 12 | // To begin with will stores all debug output until setFlushTime 13 | // or setLoggingEnabled is called, so you may construct early and 14 | // lazily connect to whatever ui you later make. 15 | class Logger : public QObject 16 | { 17 | Q_OBJECT 18 | 19 | public: 20 | explicit Logger(QObject *owner = nullptr); 21 | ~Logger(); 22 | static Logger *singleton(); 23 | 24 | // log: lossely based on the requirements for printing mpv messages 25 | static void log(QString line); 26 | static void log(QString prefix, QString message); 27 | static void log(QString prefix, QString level, QString message); 28 | // logs: like log, but with stringlists. Spaces are inserted between items. 29 | static void logs(const QStringList &strings); 30 | static void logs(QString prefix, const QStringList &strings); 31 | static void logs(QString prefix, QString level, const QStringList &strings); 32 | static void fatalMessage(); 33 | 34 | signals: 35 | void logMessage(QString message); 36 | void logMessageBuffer(QStringList messages); 37 | 38 | public slots: 39 | void setLogFile(QString fileName); 40 | void setLoggingEnabled(bool enabled); 41 | void setFlushTime(int msec); 42 | void flushMessages(); 43 | void makeLog(QString line); 44 | void makeLogPrefixed(QString prefix, QString message); 45 | void makeLogDescriptively(QString prefix, QString level, QString message); 46 | 47 | private: 48 | bool loggingEnabled = true; // by default, log everything until we get told not to 49 | bool immediateMode = false; // by default, debug messages are stored 50 | QElapsedTimer elapsed; 51 | QTimer *flushTimer = nullptr; 52 | QFile *logFile = nullptr; 53 | QTextStream *logFileStream = nullptr; 54 | QString logFileName; 55 | QStringList pendingMessages; 56 | 57 | }; 58 | 59 | 60 | 61 | // This log stream class is principally for serializing variants et al. 62 | // It is generally faster to use the Logger::log(s) functions because 63 | // LogStream has to jump through a few hoops. Use LogStream this way: 64 | // LogStream("module") << "some text " << value; 65 | // Unlike QDebug, this does not insert spaces between << invocations. 66 | class LogStream { 67 | public: 68 | LogStream(QString prefix = QString(), QString level = QString()); 69 | ~LogStream(); 70 | LogStream &always(); 71 | LogStream &operator<<(const char *a); 72 | LogStream &operator<<(const QString &a); 73 | LogStream &operator<<(const QVariant &a); 74 | 75 | private: 76 | QString buffer; 77 | QString prefix; 78 | QString level; 79 | QTextStream stream; 80 | bool directFlush = false; 81 | }; 82 | 83 | #endif // LOGGER_H 84 | -------------------------------------------------------------------------------- /logwindow.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "logger.h" 6 | #include "logwindow.h" 7 | #include "ui_logwindow.h" 8 | 9 | 10 | LogWindow::LogWindow(QWidget *parent) : 11 | QWidget(parent), 12 | ui(new Ui::LogWindow) 13 | { 14 | ui->setupUi(this); 15 | Logger *logger = Logger::singleton(); 16 | connect(logger, &Logger::logMessage, 17 | this, &LogWindow::appendMessage, 18 | Qt::QueuedConnection); 19 | connect(logger, &Logger::logMessageBuffer, 20 | this, &LogWindow::appendMessageBlock, 21 | Qt::QueuedConnection); 22 | } 23 | 24 | LogWindow::~LogWindow() 25 | { 26 | delete ui; 27 | } 28 | 29 | void LogWindow::appendMessage(QString message) 30 | { 31 | ui->messages->appendPlainText(message); 32 | } 33 | 34 | void LogWindow::appendMessageBlock(QStringList messages) 35 | { 36 | ui->messages->appendPlainText(messages.join('\n')); 37 | } 38 | 39 | void LogWindow::setLogLimit(int lines) 40 | { 41 | ui->messages->setMaximumBlockCount(lines); 42 | } 43 | 44 | void LogWindow::closeEvent(QCloseEvent *event) 45 | { 46 | event->accept(); 47 | emit windowClosed(); 48 | } 49 | 50 | void LogWindow::on_copy_clicked() 51 | { 52 | QTextDocument *doc = ui->messages->document(); 53 | qApp->clipboard()->setText(doc->toPlainText()); 54 | } 55 | 56 | void LogWindow::on_save_clicked() 57 | { 58 | QString textToSave = ui->messages->document()->toPlainText(); 59 | static QString lastLog; 60 | QString file = QFileDialog::getSaveFileName(this, tr("Save File"), lastLog, "Text files (*.txt)"); 61 | if (file.isEmpty()) 62 | return; 63 | 64 | QFile f(file); 65 | if (!f.open(QIODevice::WriteOnly)) 66 | return; 67 | QTextStream stream(&f); 68 | stream.setGenerateByteOrderMark(true); 69 | stream << textToSave; 70 | } 71 | 72 | void LogWindow::on_clear_clicked() 73 | { 74 | ui->messages->clear(); 75 | } 76 | -------------------------------------------------------------------------------- /logwindow.h: -------------------------------------------------------------------------------- 1 | #ifndef LOGWINDOW_H 2 | #define LOGWINDOW_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace Ui { 10 | class LogWindow; 11 | } 12 | 13 | class LogWindow : public QWidget 14 | { 15 | Q_OBJECT 16 | 17 | public: 18 | explicit LogWindow(QWidget *parent = nullptr); 19 | ~LogWindow(); 20 | 21 | signals: 22 | void windowClosed(); 23 | 24 | public slots: 25 | void appendMessage(QString message); 26 | void appendMessageBlock(QStringList messages); 27 | void setLogLimit(int lines); 28 | 29 | protected: 30 | void closeEvent(QCloseEvent *event); 31 | 32 | private slots: 33 | void on_copy_clicked(); 34 | void on_save_clicked(); 35 | void on_clear_clicked(); 36 | 37 | private: 38 | Ui::LogWindow *ui; 39 | }; 40 | 41 | 42 | 43 | #endif // LOGWINDOW_H 44 | -------------------------------------------------------------------------------- /logwindow.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | LogWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 566 10 | 455 11 | 12 | 13 | 14 | Log Messages 15 | 16 | 17 | 18 | 19 | 20 | Qt::ScrollBarAlwaysOn 21 | 22 | 23 | Qt::ScrollBarAlwaysOff 24 | 25 | 26 | QPlainTextEdit::NoWrap 27 | 28 | 29 | true 30 | 31 | 32 | 1000 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | Qt::Horizontal 42 | 43 | 44 | 45 | 40 46 | 20 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | Copy 55 | 56 | 57 | 58 | 59 | 60 | 61 | Save 62 | 63 | 64 | 65 | 66 | 67 | 68 | Clear 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /make-mac-icon.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [ ! -f images/icon/mpc-qt.icns ]; then 3 | cd images/icon 4 | mkdir mpc-qt.iconset 5 | rsvg-convert -h 16 mpc-qt.svg > mpc-qt.iconset/icon_16x16.png 6 | rsvg-convert -h 32 mpc-qt.svg > mpc-qt.iconset/icon_16x16@2x.png 7 | rsvg-convert -h 32 mpc-qt.svg > mpc-qt.iconset/icon_32x32.png 8 | rsvg-convert -h 64 mpc-qt.svg > mpc-qt.iconset/icon_32x32@2x.png 9 | rsvg-convert -h 128 mpc-qt.svg > mpc-qt.iconset/icon_128x128.png 10 | rsvg-convert -h 256 mpc-qt.svg > mpc-qt.iconset/icon_128x128@2x.png 11 | rsvg-convert -h 256 mpc-qt.svg > mpc-qt.iconset/icon_256x256.png 12 | rsvg-convert -h 512 mpc-qt.svg > mpc-qt.iconset/icon_256x256@2x.png 13 | rsvg-convert -h 512 mpc-qt.svg > mpc-qt.iconset/icon_512x512.png 14 | rsvg-convert -h 1024 mpc-qt.svg > mpc-qt.iconset/icon_512x512@2x.png 15 | iconutil -c icns mpc-qt.iconset 16 | rm -R mpc-qt.iconset 17 | cd ../.. 18 | fi 19 | -------------------------------------------------------------------------------- /make-release-win.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Make windows release script using 64bit libs 3 | 4 | VERSION=`date +'%y%m'` 5 | DOTTEDVERSION=`date +'%y.%m'` 6 | BUILD=release 7 | SUFFIX="win-x64-$VERSION" 8 | DEST="mpc-qt-$SUFFIX" 9 | 10 | qmake "MPCQT_VERSION=$DOTTEDVERSION" mpc-qt.pro 11 | mkdir -p release 12 | rm release/* 13 | make release-clean 14 | make -j4 release 15 | 16 | read -r -d '' dirs <<'EOF' 17 | . 18 | /doc 19 | /iconengines 20 | /imageformats 21 | /platforms 22 | /styles 23 | /translations 24 | EOF 25 | 26 | read -r -d '' dlls <<'EOF' 27 | libbrotlidec.dll 28 | libbrotlicommon.dll 29 | libbz2-1.dll 30 | libdouble-conversion.dll 31 | libfreetype-6.dll 32 | libgcc_s_seh-1.dll 33 | libglib-2.0-0.dll 34 | libgraphite2.dll 35 | libharfbuzz-0.dll 36 | libiconv-2.dll 37 | libicudt67.dll 38 | libicuin67.dll 39 | libicuuc67.dll 40 | libintl-8.dll 41 | libjpeg-8.dll 42 | libpcre-1.dll 43 | libpcre2-16-0.dll 44 | libpng16-16.dll 45 | libstdc++-6.dll 46 | libwinpthread-1.dll 47 | libzstd.dll 48 | Qt5Core.dll 49 | Qt5Gui.dll 50 | Qt5Network.dll 51 | Qt5Svg.dll 52 | Qt5Widgets.dll 53 | Qt5Xml.dll 54 | zlib1.dll 55 | EOF 56 | 57 | read -r -d '' plugins <<'EOF' 58 | iconengines/qsvgicon.dll 59 | imageformats/qjpeg.dll 60 | imageformats/qsvg.dll 61 | platforms/qdirect2d.dll 62 | platforms/qminimal.dll 63 | platforms/qoffscreen.dll 64 | platforms/qwebgl.dll 65 | platforms/qwindows.dll 66 | styles/qwindowsvistastyle.dll 67 | EOF 68 | 69 | read -r -d '' docs <<'EOF' 70 | ipc.md 71 | EOF 72 | 73 | read -r -d '' binaries <<'EOF' 74 | youtube-dl.exe 75 | msvcr100.dll 76 | EOF 77 | 78 | translations=`ls resources/translations` 79 | 80 | (while read -r dir; do 81 | mkdir -p "$DEST/$dir" 82 | done)<<<"$dirs" 83 | 84 | (while read -r dll; do 85 | cp `which "$dll"` "$DEST/$dll" 86 | done)<<<"$dlls" 87 | 88 | (while read -r plugin; do 89 | cp "/mingw64/share/qt5/plugins/$plugin" "$DEST/$plugin" 90 | done)<<<"$plugins" 91 | 92 | (while read -r translation; do 93 | cp "resources/translations/$translation" "$DEST/translations/$translation" 94 | done)<<<"$translations" 95 | 96 | (while read -r doc; do 97 | cp "DOCS/$doc" "$DEST/doc/$doc" 98 | done)<<<"$docs" 99 | 100 | (while read -r binary; do 101 | cp "binaries/$binary" "$DEST/$binary" 102 | done)<<<"$binaries" 103 | 104 | cp "$BUILD/mpc-qt.exe" "$DEST/mpc-qt.exe" 105 | cp mpv-dev/lib/mpv-1.dll "$DEST/mpv-1.dll" 106 | 7z a "$DEST.zip" "./$DEST/*" 107 | sha512sum "$DEST.zip" >"$DEST.zip.sha512" 108 | -------------------------------------------------------------------------------- /make-win-icon.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [ ! -f mpc-qt.ico ]; then 3 | (magick convert -quiet images/icon/mpc-qt.svg -define icon:auto-resize=16,48,256 -compress zip mpc-qt.ico)2>&1>&/dev/null 4 | fi 5 | echo mpc-qt.ico 6 | -------------------------------------------------------------------------------- /mpc-qt.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Type=Application 3 | Name=Media Player Classic Qute Theater 4 | GenericName=Multimedia Player 5 | GenericName[pt]=Reprodutor multimédia 6 | Comment=Qt media player based on libmpv 7 | Comment[pt]=Reprodutor multimédia baseado em Qt e libmppv 8 | Exec=mpc-qt %U 9 | TryExec=mpc-qt 10 | Icon=mpc-qt 11 | StartupNotify=true 12 | Terminal=false 13 | Categories=Qt;AudioVideo;Audio;Video;Player;TV; 14 | MimeType=inode/directory;application/ogg;application/x-ogg;application/sdp;application/smil;application/x-smil;application/streamingmedia;application/x-streamingmedia;application/vnd.rn-realmedia;application/vnd.rn-realmedia-vbr;audio/aac;audio/x-aac;audio/m4a;audio/x-m4a;audio/mp1;audio/x-mp1;audio/mp2;audio/x-mp2;audio/mp3;audio/x-mp3;audio/mpeg;audio/x-mpeg;audio/mpegurl;audio/x-mpegurl;audio/mpg;audio/x-mpg;audio/rn-mpeg;audio/ogg;audio/scpls;audio/x-scpls;audio/vnd.rn-realaudio;audio/wav;audio/x-pn-windows-pcm;audio/x-realaudio;audio/x-pn-realaudio;audio/x-ms-wma;audio/x-pls;audio/x-wav;video/mpeg;video/x-mpeg;video/x-mpeg2;video/mp4;video/msvideo;video/x-msvideo;video/ogg;video/quicktime;video/vnd.rn-realvideo;video/x-ms-afs;video/x-ms-asf;video/x-ms-wmv;video/x-ms-wmx;video/x-ms-wvxvideo;video/x-avi;video/x-fli;video/x-flv;video/x-theora;video/x-matroska;video/webm;audio/x-flac;audio/x-vorbis+ogg;video/x-ogm+ogg;audio/x-shorten;audio/x-ape;audio/x-wavpack;audio/x-tta;audio/AMR;audio/ac3;video/mp2t;audio/flac;audio/mp4; 15 | X-KDE-Protocols=ftp,http,https,mms,rtmp,rtsp,sftp,smb 16 | X-DBUS-ServiceName= 17 | X-DBUS-StartupType= 18 | X-KDE-SubstituteUID=false 19 | X-KDE-Username= 20 | Actions=newFreestandingWindow 21 | 22 | [Desktop Action newFreestandingWindow] 23 | Name=New Freestanding Window 24 | Exec=mpc-qt --freestanding %U 25 | -------------------------------------------------------------------------------- /mpv-dev/include/mpv/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /mpv-dev/lib/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /openfiledialog.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "helpers.h" 3 | #include "openfiledialog.h" 4 | #include "ui_openfiledialog.h" 5 | 6 | OpenFileDialog::OpenFileDialog(QWidget *parent) : 7 | QDialog(parent), 8 | ui(new Ui::OpenFileDialog) 9 | { 10 | ui->setupUi(this); 11 | } 12 | 13 | OpenFileDialog::~OpenFileDialog() 14 | { 15 | delete ui; 16 | } 17 | 18 | QString OpenFileDialog::file() 19 | { 20 | return ui->fileField->text(); 21 | } 22 | 23 | QString OpenFileDialog::subs() 24 | { 25 | return ui->subsField->text(); 26 | } 27 | 28 | void OpenFileDialog::on_fileBrowse_clicked() 29 | { 30 | static QString filter; 31 | if (filter.isEmpty()) 32 | filter = Helpers::fileOpenFilter(); 33 | 34 | QUrl url = QFileDialog::getOpenFileUrl(this, tr("Select File"), QUrl(), filter); 35 | if (url.isValid()) 36 | ui->fileField->setText(url.toDisplayString()); 37 | } 38 | 39 | void OpenFileDialog::on_subsBrowse_clicked() 40 | { 41 | static QString subsFilter; 42 | if (subsFilter.isEmpty()) 43 | subsFilter = Helpers::subsOpenFilter(); 44 | QUrl url = QFileDialog::getOpenFileUrl(this, tr("Select File"), QUrl(), subsFilter); 45 | if (url.isValid()) 46 | ui->subsField->setText(url.toDisplayString()); 47 | } 48 | -------------------------------------------------------------------------------- /openfiledialog.h: -------------------------------------------------------------------------------- 1 | #ifndef OPENFILEDIALOG_H 2 | #define OPENFILEDIALOG_H 3 | 4 | #include 5 | 6 | namespace Ui { 7 | class OpenFileDialog; 8 | } 9 | 10 | class OpenFileDialog : public QDialog 11 | { 12 | Q_OBJECT 13 | 14 | public: 15 | explicit OpenFileDialog(QWidget *parent = nullptr); 16 | ~OpenFileDialog(); 17 | 18 | QString file(); 19 | QString subs(); 20 | 21 | private slots: 22 | void on_fileBrowse_clicked(); 23 | 24 | void on_subsBrowse_clicked(); 25 | 26 | private: 27 | Ui::OpenFileDialog *ui = nullptr; 28 | }; 29 | 30 | #endif // OPENFILEDIALOG_H 31 | -------------------------------------------------------------------------------- /openfiledialog.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | OpenFileDialog 4 | 5 | 6 | 7 | 0 8 | 0 9 | 640 10 | 112 11 | 12 | 13 | 14 | Open File 15 | 16 | 17 | 18 | 19 | 20 | Fi&le 21 | 22 | 23 | fileField 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | ... 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | &Subtitles 45 | 46 | 47 | subsField 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | ... 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | Qt::TabFocus 69 | 70 | 71 | Qt::Horizontal 72 | 73 | 74 | QDialogButtonBox::Cancel|QDialogButtonBox::Ok 75 | 76 | 77 | 78 | 79 | 80 | 81 | fileField 82 | fileBrowse 83 | subsField 84 | subsBrowse 85 | buttonBox 86 | 87 | 88 | 89 | 90 | buttonBox 91 | accepted() 92 | OpenFileDialog 93 | accept() 94 | 95 | 96 | 248 97 | 254 98 | 99 | 100 | 157 101 | 274 102 | 103 | 104 | 105 | 106 | buttonBox 107 | rejected() 108 | OpenFileDialog 109 | reject() 110 | 111 | 112 | 316 113 | 260 114 | 115 | 116 | 286 117 | 274 118 | 119 | 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /platform/devicemanager.cpp: -------------------------------------------------------------------------------- 1 | #include "devicemanager.h" 2 | 3 | 4 | DeviceInfo::DeviceInfo(QObject *parent) 5 | : QObject(parent) 6 | { 7 | static int index = 0; 8 | uniqueId_ = index++; 9 | } 10 | 11 | int DeviceInfo::uniqueId() 12 | { 13 | return uniqueId_; 14 | } 15 | 16 | DeviceManager::DeviceManager(QObject *parent) : QObject(parent) 17 | { 18 | changedTimer.setSingleShot(true); 19 | changedTimer.setInterval(0); 20 | connect(&changedTimer, &QTimer::timeout, 21 | this, &DeviceManager::deviceListChanged); 22 | } 23 | 24 | DeviceManager::~DeviceManager() 25 | { 26 | clearDevices(); 27 | } 28 | 29 | int DeviceManager::count() 30 | { 31 | return devices.count(); 32 | } 33 | 34 | bool DeviceManager::isDeviceValid(DeviceInfo *info) 35 | { 36 | return info && devices.contains(info->uniqueId()); 37 | } 38 | 39 | void DeviceManager::clearDevices() 40 | { 41 | qDeleteAll(devices); 42 | devices.clear(); 43 | } 44 | 45 | void DeviceManager::addDevice(DeviceInfo *device) 46 | { 47 | devices.insert(device->uniqueId(), device); 48 | emit deviceAdded(device); 49 | changedTimer.start(); 50 | } 51 | 52 | void DeviceManager::removeDevice(DeviceInfo *device) 53 | { 54 | removeDeviceById(device->uniqueId()); 55 | } 56 | 57 | void DeviceManager::removeDeviceById(int id) 58 | { 59 | if (!devices.contains(id)) 60 | return; 61 | emit deviceRemoved(devices[id]); 62 | devices.remove(id); 63 | changedTimer.start(); 64 | } 65 | 66 | void DeviceManager::iterateDevices(std::function callback) 67 | { 68 | for (auto i : qAsConst(devices)) { 69 | callback(i); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /platform/devicemanager.h: -------------------------------------------------------------------------------- 1 | #ifndef DEVICEMANAGER_H 2 | #define DEVICEMANAGER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | class DeviceInfo : public QObject 11 | { 12 | Q_OBJECT 13 | 14 | public: 15 | enum DeviceType { UnknownDrive, NoDrive, RemovableDrive, FixedDrive, 16 | RemoteDrive, OpticalDrive, RamDrive, MemoryDevice, 17 | OtherDevice = -1 }; 18 | 19 | DeviceInfo(QObject *parent = nullptr); 20 | int uniqueId(); 21 | virtual QString toDisplayString() = 0; 22 | virtual void mount() = 0; 23 | 24 | DeviceType deviceType; 25 | QString deviceName; 26 | QString internal; 27 | QString volumeLabel; 28 | QString mountedPath; 29 | 30 | private: 31 | int uniqueId_; 32 | }; 33 | 34 | 35 | class DeviceManager : public QObject 36 | { 37 | Q_OBJECT 38 | public: 39 | explicit DeviceManager(QObject *parent = nullptr); 40 | ~DeviceManager(); 41 | virtual bool deviceAccessPossible() = 0; 42 | int count(); 43 | void iterateDevices(std::function callback); 44 | bool isDeviceValid(DeviceInfo *info); 45 | 46 | signals: 47 | void deviceAdded(DeviceInfo *info); 48 | void deviceRemoved(DeviceInfo *info); 49 | void deviceListChanged(); 50 | 51 | public slots: 52 | 53 | protected: 54 | virtual void populate() = 0; 55 | void clearDevices(); 56 | void addDevice(DeviceInfo *device); 57 | void removeDevice(DeviceInfo *device); 58 | void removeDeviceById(int id); 59 | 60 | private: 61 | QMap devices; 62 | QTimer changedTimer; 63 | }; 64 | 65 | #endif // DEVICEMANAGER_H 66 | -------------------------------------------------------------------------------- /platform/devicemanager_mac.cpp: -------------------------------------------------------------------------------- 1 | #include "devicemanager_mac.h" 2 | 3 | DeviceManagerMac::DeviceManagerMac(QObject *parent) 4 | : DeviceManager(parent) 5 | { 6 | 7 | } 8 | 9 | bool DeviceManagerMac::deviceAccessPossible() 10 | { 11 | return false; 12 | } 13 | 14 | void DeviceManagerMac::populate() 15 | { 16 | 17 | } 18 | -------------------------------------------------------------------------------- /platform/devicemanager_mac.h: -------------------------------------------------------------------------------- 1 | #ifndef DEVICEMANAGER_MAC_H 2 | #define DEVICEMANAGER_MAC_H 3 | 4 | #include "devicemanager.h" 5 | 6 | class DeviceManagerMac : public DeviceManager 7 | { 8 | Q_OBJECT 9 | public: 10 | DeviceManagerMac(QObject *parent); 11 | bool deviceAccessPossible(); 12 | 13 | protected: 14 | void populate(); 15 | }; 16 | 17 | #endif // DEVICEMANAGER_MAC_H 18 | -------------------------------------------------------------------------------- /platform/devicemanager_unix.h: -------------------------------------------------------------------------------- 1 | #ifndef DEVICEMANAGER_UNIX_H 2 | #define DEVICEMANAGER_UNIX_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "devicemanager.h" 8 | 9 | class UDisks2Block; 10 | class UDisks2Drive; 11 | class UDisks2Filesystem; 12 | 13 | class DeviceManagerUnix : public DeviceManager 14 | { 15 | Q_OBJECT 16 | public: 17 | explicit DeviceManagerUnix(QObject *parent = nullptr); 18 | ~DeviceManagerUnix(); 19 | bool deviceAccessPossible(); 20 | 21 | QStringList blockDevices(); 22 | UDisks2Block *blockDevice(const QString &node); 23 | 24 | QStringList drives(); 25 | UDisks2Drive *drive(const QString &node); 26 | 27 | signals: 28 | void deviceInformationChanged(QString node, QVariantMap info); 29 | void driveAdded(const QString& node); 30 | void driveRemoved(const QString& node); 31 | void driveChanged(const QString& node); 32 | void blockDeviceAdded(const QString& node); 33 | void blockDeviceRemoved(const QString &node); 34 | void blockDeviceChanged(const QString &node); 35 | void filesystemAdded(const QString& node); 36 | void filesystemRemoved(const QString &node); 37 | void filesystemChanged(const QString &node); 38 | 39 | protected: 40 | void populate(); 41 | 42 | private: 43 | void addDrive(const QString &node); 44 | void addBlock(const QString &node); 45 | void removeDrive(const QString &node); 46 | void removeBlock(const QString &node); 47 | 48 | private slots: 49 | void dbus_interfaceAdded(const QDBusObjectPath &path, const QMap &interfaces); 50 | void dbus_interfaceRemoved(const QDBusObjectPath &path, const QStringList &interfaces); 51 | 52 | private: 53 | QMap drives_; 54 | QMap blocks_; 55 | QHash deviceIdByBlockNode; 56 | bool serviceConnected; 57 | }; 58 | 59 | 60 | 61 | class UDisks2Block : public DeviceInfo { 62 | Q_OBJECT 63 | public: 64 | explicit UDisks2Block(const QString &node, QObject *parent = NULL); 65 | QString toDisplayString(); 66 | void mount(); 67 | 68 | public: 69 | //QString name; // deviceName 70 | QString dev; 71 | QString id; 72 | //QString drive; // internal 73 | qulonglong size; 74 | bool readonly; 75 | QString usage; 76 | QString type; 77 | //QString label; // volumeLabel 78 | QString toString(); 79 | 80 | void update(); 81 | void updateFilesystem(); 82 | void addFilesystem(); 83 | void removeFilesystem(); 84 | UDisks2Filesystem *fileSystem(); 85 | 86 | signals: 87 | void filesystemAdded(const QString& node); 88 | void filesystemRemoved(const QString &node); 89 | void filesystemChanged(const QString &node); 90 | void changed(const QString &node); 91 | 92 | private slots: 93 | void self_propertiesChanged(const QString &interface, const QVariantMap &changedProp, const QStringList &invalidatedProp); 94 | 95 | private: 96 | QDBusInterface *dbus; 97 | UDisks2Filesystem* fs; 98 | }; 99 | 100 | class UDisks2Filesystem : public QObject { 101 | Q_OBJECT 102 | public: 103 | UDisks2Filesystem(const QString &node, QObject *parent = nullptr); 104 | const QStringList &mountPoints() const; 105 | void mount(); 106 | void unmount(); 107 | void update(); 108 | bool isValid(); 109 | 110 | QString name; 111 | 112 | private: 113 | QDBusInterface *dbus; 114 | QDBusInterface *dbusProp; 115 | QStringList mountPoints_; 116 | }; 117 | 118 | class UDisks2Drive : public QObject { 119 | Q_OBJECT 120 | public: 121 | explicit UDisks2Drive(const QString &node, QObject *parent = NULL); 122 | 123 | QString name; 124 | qulonglong size; 125 | QString vendor; 126 | QString model; 127 | QString serial; 128 | QString id; 129 | QString media; 130 | bool optical; 131 | bool removable; 132 | bool available; 133 | QString toString(); 134 | 135 | void update(); 136 | 137 | signals: 138 | void changed(const QString &node); 139 | 140 | private slots: 141 | void self_propertiesChanged(const QString &interface, const QVariantMap &changed, const QStringList &invalidated); 142 | 143 | private: 144 | QDBusInterface *dbus; 145 | }; 146 | 147 | #endif // DEVICEMANAGER_UNIX_H 148 | -------------------------------------------------------------------------------- /platform/devicemanager_win.h: -------------------------------------------------------------------------------- 1 | #ifndef DEVICEMANAGERWIN_H 2 | #define DEVICEMANAGERWIN_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "devicemanager.h" 8 | 9 | class DeviceManagerWin; 10 | class DeviceInfoWin; 11 | class DeviceListener; 12 | 13 | class DeviceManagerWin : public DeviceManager 14 | { 15 | Q_OBJECT 16 | public: 17 | DeviceManagerWin(QObject *parent); 18 | ~DeviceManagerWin(); 19 | bool deviceAccessPossible(); 20 | 21 | public slots: 22 | void rescan(); 23 | 24 | protected: 25 | void populate(); 26 | 27 | private: 28 | DeviceListener *listener; 29 | QList volumePaths(WCHAR *volumeName, WCHAR *deviceName); 30 | }; 31 | 32 | 33 | class DeviceInfoWin : public DeviceInfo 34 | { 35 | Q_OBJECT 36 | public: 37 | DeviceInfoWin(QObject *parent = nullptr); 38 | QString toDisplayString(); 39 | void mount(); 40 | }; 41 | 42 | class DeviceListener : public QWidget 43 | { 44 | Q_OBJECT 45 | public: 46 | explicit DeviceListener(QWidget *parent = nullptr); 47 | 48 | signals: 49 | void rescanNeeded(); 50 | 51 | protected: 52 | bool nativeEvent(const QByteArray &eventType, void *message, long *result); 53 | 54 | private: 55 | QTimer rescanTimer; 56 | }; 57 | 58 | 59 | #endif // DEVICEMANAGERWIN_H 60 | -------------------------------------------------------------------------------- /platform/screensaver.cpp: -------------------------------------------------------------------------------- 1 | #include "screensaver.h" 2 | 3 | ScreenSaver::ScreenSaver(QObject *parent) 4 | : QObject(parent) 5 | { 6 | } 7 | 8 | bool ScreenSaver::inhibiting() 9 | { 10 | return isInhibiting; 11 | } 12 | -------------------------------------------------------------------------------- /platform/screensaver.h: -------------------------------------------------------------------------------- 1 | #ifndef QABSTRACTSCREENSAVER_H 2 | #define QABSTRACTSCREENSAVER_H 3 | 4 | #include 5 | #include 6 | 7 | // This is probably overkill 8 | class ScreenSaver : public QObject 9 | { 10 | Q_OBJECT 11 | public: 12 | enum Ability { Inhibit, Uninhibit, LaunchSaver, LockScreen, 13 | Hibernate, Suspend, Shutdown, LogOff }; 14 | 15 | explicit ScreenSaver(QObject *parent = nullptr); 16 | 17 | virtual QSet abilities() = 0; 18 | virtual bool inhibiting(); 19 | 20 | public slots: 21 | virtual void inhibitSaver(const QString &reason) = 0; 22 | virtual void uninhibitSaver() = 0; 23 | virtual void launchSaver() = 0; 24 | virtual void lockScreen() = 0; 25 | virtual void hibernateSystem() = 0; 26 | virtual void suspendSystem() = 0; 27 | virtual void shutdownSystem() = 0; 28 | virtual void logOff() = 0; 29 | 30 | signals: 31 | void inhibitedSaver(); 32 | void uninhibitedSaver(); 33 | void launchedSaver(); 34 | void screenLocked(); 35 | void systemHibernated(); 36 | void systemSuspended(); 37 | void systemShutdown(); 38 | void loggedOff(); 39 | void failed(ScreenSaver::Ability what); 40 | 41 | protected: 42 | bool isInhibiting = false; 43 | }; 44 | 45 | #endif // QABSTRACTSCREENSAVER_H 46 | -------------------------------------------------------------------------------- /platform/screensaver_mac.cpp: -------------------------------------------------------------------------------- 1 | #include "screensaver_mac.h" 2 | 3 | //FIXME: use IOPMAssertion??? 4 | 5 | ScreenSaverMac::ScreenSaverMac(QObject *parent) : ScreenSaver(parent) 6 | { 7 | 8 | } 9 | 10 | QSet ScreenSaverMac::abilities() 11 | { 12 | return QSet(); 13 | } 14 | 15 | void ScreenSaverMac::inhibitSaver(const QString &reason) 16 | { 17 | Q_UNUSED(reason) 18 | emit failed(Inhibit); 19 | } 20 | 21 | void ScreenSaverMac::uninhibitSaver() { 22 | emit failed(Uninhibit); 23 | } 24 | 25 | void ScreenSaverMac::launchSaver() { 26 | emit failed(LaunchSaver); 27 | } 28 | 29 | void ScreenSaverMac::lockScreen() { 30 | emit failed(LockScreen); 31 | } 32 | 33 | void ScreenSaverMac::hibernateSystem() 34 | { 35 | emit failed(Hibernate); 36 | } 37 | 38 | void ScreenSaverMac::suspendSystem() 39 | { 40 | emit failed(Suspend); 41 | } 42 | 43 | void ScreenSaverMac::shutdownSystem() 44 | { 45 | emit failed(Shutdown); 46 | } 47 | 48 | void ScreenSaverMac::logOff() 49 | { 50 | emit failed(LogOff); 51 | } 52 | -------------------------------------------------------------------------------- /platform/screensaver_mac.h: -------------------------------------------------------------------------------- 1 | #ifndef QSCREENSAVER_MAC_H 2 | #define QSCREENSAVER_MAC_H 3 | #include "screensaver.h" 4 | 5 | class ScreenSaverMac : public ScreenSaver 6 | { 7 | Q_OBJECT 8 | public: 9 | ScreenSaverMac(QObject *parent = nullptr); 10 | 11 | QSet abilities(); 12 | 13 | public slots: 14 | void inhibitSaver(const QString &reason); 15 | void uninhibitSaver(); 16 | void launchSaver(); 17 | void lockScreen(); 18 | void hibernateSystem(); 19 | void suspendSystem(); 20 | void shutdownSystem(); 21 | void logOff(); 22 | }; 23 | 24 | #endif // QSCREENSAVER_MAC_H 25 | -------------------------------------------------------------------------------- /platform/screensaver_unix.h: -------------------------------------------------------------------------------- 1 | #ifndef QSCREENSAVER_UNIX_H 2 | #define QSCREENSAVER_UNIX_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "screensaver.h" 9 | 10 | Q_DECLARE_METATYPE(unsigned) 11 | Q_DECLARE_METATYPE(uint64_t) 12 | 13 | class ScreenSaverUnix : public ScreenSaver 14 | { 15 | Q_OBJECT 16 | public: 17 | explicit ScreenSaverUnix(QObject *parent = nullptr); 18 | 19 | QSet abilities(); 20 | 21 | public slots: 22 | void inhibitSaver(const QString &reason); 23 | void uninhibitSaver(); 24 | void launchSaver(); 25 | void lockScreen(); 26 | void hibernateSystem(); 27 | void suspendSystem(); 28 | void shutdownSystem(); 29 | void logOff(); 30 | 31 | private slots: 32 | void dbusScreensaver_inhibit(QDBusPendingCallWatcher *call); 33 | void dbusScreensaver_uninhibit(QDBusPendingCallWatcher *call); 34 | void dbusScreensaver_launch(QDBusPendingCallWatcher *call); 35 | void dbusScreensaver_lock(QDBusPendingCallWatcher *call); 36 | void dbusLogin_hibernate(QDBusPendingCallWatcher *call); 37 | void dbusLogin_suspend(QDBusPendingCallWatcher *call); 38 | void dbusLogin_shutdown(QDBusPendingCallWatcher *call); 39 | void dbusLoginSelf_logoff(QDBusPendingCallWatcher *call); 40 | 41 | private: 42 | QDBusInterface dbusScreensaver; 43 | QDBusInterface dbusLogin; 44 | QDBusInterface dbusLoginSelf; 45 | uint32_t inhibitToken = 0; 46 | bool inhibitCalled = false; 47 | }; 48 | 49 | #endif // QSCREENSAVER_UNIX_H 50 | -------------------------------------------------------------------------------- /platform/screensaver_win.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "screensaver_win.h" 4 | 5 | ScreenSaverWin::ScreenSaverWin(QObject *parent) : ScreenSaver(parent) 6 | { 7 | 8 | } 9 | 10 | QSet ScreenSaverWin::abilities() 11 | { 12 | QSet capabilities; 13 | capabilities << Inhibit << Uninhibit << LockScreen; 14 | if (canShutdown()) 15 | capabilities << Shutdown << Hibernate << Suspend << LogOff; 16 | return capabilities; 17 | } 18 | 19 | void ScreenSaverWin::inhibitSaver(const QString &reason) 20 | { 21 | Q_UNUSED(reason); 22 | if (isInhibiting) 23 | return; 24 | 25 | SetThreadExecutionState(ES_CONTINUOUS | ES_DISPLAY_REQUIRED | 26 | ES_SYSTEM_REQUIRED | ES_AWAYMODE_REQUIRED); 27 | isInhibiting = true; 28 | emit inhibitedSaver(); 29 | } 30 | 31 | void ScreenSaverWin::uninhibitSaver() 32 | { 33 | if (!isInhibiting) 34 | return; 35 | 36 | SetThreadExecutionState(ES_CONTINUOUS); 37 | isInhibiting = false; 38 | emit uninhibitedSaver(); 39 | } 40 | 41 | void ScreenSaverWin::launchSaver() 42 | { 43 | emit failed(LaunchSaver); 44 | } 45 | 46 | void ScreenSaverWin::lockScreen() 47 | { 48 | if (LockWorkStation()) 49 | emit screenLocked(); 50 | else 51 | emit failed(LockScreen); 52 | } 53 | 54 | void ScreenSaverWin::hibernateSystem() 55 | { 56 | if (SetSuspendState(TRUE, FALSE, FALSE)) 57 | emit systemHibernated(); 58 | else 59 | emit failed(Hibernate); 60 | } 61 | 62 | void ScreenSaverWin::suspendSystem() 63 | { 64 | if(SetSuspendState(FALSE, FALSE, FALSE)) 65 | emit systemSuspended(); 66 | else 67 | emit failed(Suspend); 68 | } 69 | 70 | void ScreenSaverWin::shutdownSystem() 71 | { 72 | if (ExitWindowsEx(EWX_SHUTDOWN, 0)) 73 | emit systemShutdown(); 74 | else 75 | emit failed(Shutdown); 76 | } 77 | 78 | void ScreenSaverWin::logOff() 79 | { 80 | if (ExitWindowsEx(EWX_LOGOFF, 0)) 81 | emit loggedOff(); 82 | else 83 | emit failed(LogOff); 84 | } 85 | 86 | bool ScreenSaverWin::canShutdown() 87 | { 88 | HANDLE hToken; 89 | TOKEN_PRIVILEGES tkp; 90 | 91 | // Get a token for this process. 92 | if (!OpenProcessToken(GetCurrentProcess(), 93 | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) 94 | return false; 95 | 96 | // Get the LUID for the shutdown privilege. 97 | LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, 98 | &tkp.Privileges[0].Luid); 99 | 100 | tkp.PrivilegeCount = 1; // one privilege to set 101 | tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 102 | // Get the shutdown privilege for this process. 103 | 104 | AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, 105 | (PTOKEN_PRIVILEGES)NULL, 0); 106 | 107 | return GetLastError() == ERROR_SUCCESS; 108 | } 109 | 110 | -------------------------------------------------------------------------------- /platform/screensaver_win.h: -------------------------------------------------------------------------------- 1 | #ifndef QSCREENSAVER_WIN_H 2 | #define QSCREENSAVER_WIN_H 3 | #include "screensaver.h" 4 | 5 | class ScreenSaverWin : public ScreenSaver 6 | { 7 | Q_OBJECT 8 | public: 9 | explicit ScreenSaverWin(QObject *parent = nullptr); 10 | 11 | QSet abilities(); 12 | 13 | public slots: 14 | void inhibitSaver(const QString &reason); 15 | void uninhibitSaver(); 16 | void launchSaver(); 17 | void lockScreen(); 18 | void hibernateSystem(); 19 | void suspendSystem(); 20 | void shutdownSystem(); 21 | void logOff(); 22 | 23 | private: 24 | bool canShutdown(); 25 | }; 26 | 27 | #endif // QSCREENSAVER_WIN_H 28 | -------------------------------------------------------------------------------- /platform/unify.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "unify.h" 6 | 7 | // Platform includes 8 | #if defined(Q_OS_WIN) 9 | #include "devicemanager_win.h" 10 | #include "screensaver_win.h" 11 | #elif defined(Q_OS_MAC) 12 | #include "devicemanager_mac.h" 13 | #include "screensaver_mac.h" 14 | #else 15 | #include 16 | #include "devicemanager_unix.h" 17 | #include "screensaver_unix.h" 18 | #endif 19 | 20 | 21 | // Platform defines 22 | #if defined(Q_OS_WIN) 23 | #define ScreenSaverPlatform ScreenSaverWin 24 | #define DeviceManagerPlatform DeviceManagerWin 25 | #elif defined(Q_OS_MAC) 26 | #define ScreenSaverPlatform ScreenSaverMac 27 | #define DeviceManagerPlatform DeviceManagerMac 28 | #else 29 | #define ScreenSaverPlatform ScreenSaverUnix 30 | #define DeviceManagerPlatform DeviceManagerUnix 31 | #endif 32 | 33 | 34 | // Platform flags 35 | const bool Platform::isMac = 36 | #if defined(Q_OS_MAC) 37 | true 38 | #else 39 | false 40 | #endif 41 | ; 42 | 43 | const bool Platform::isWindows = 44 | #if defined(Q_OS_WIN) 45 | true 46 | #else 47 | false 48 | #endif 49 | ; 50 | 51 | const bool Platform::isUnix = 52 | #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) 53 | true 54 | #else 55 | false 56 | #endif 57 | ; 58 | 59 | 60 | DeviceManager *Platform::deviceManager() 61 | { 62 | static DeviceManagerPlatform *dm = nullptr; 63 | if (dm == nullptr) { 64 | Q_ASSERT(qApp); 65 | dm = new DeviceManagerPlatform(qApp); 66 | QObject::connect(dm, &DeviceManager::destroyed, [&] { 67 | dm = nullptr; 68 | }); 69 | } 70 | return dm; 71 | } 72 | 73 | ScreenSaver *Platform::screenSaver() 74 | { 75 | static ScreenSaverPlatform *ss = nullptr; 76 | if (ss == nullptr) { 77 | Q_ASSERT(qApp); 78 | ss = new ScreenSaverPlatform(qApp); 79 | QObject::connect(ss, &ScreenSaver::destroyed, [&] { 80 | ss = nullptr; 81 | }); 82 | } 83 | return ss; 84 | } 85 | 86 | QString Platform::resourcesPath() 87 | { 88 | if (Platform::isMac) 89 | return QApplication::applicationDirPath() + "/../Resources"; 90 | if (Platform::isWindows) 91 | return QApplication::applicationDirPath(); 92 | if (Platform::isUnix) { 93 | #ifdef MPCQT_PREFIX 94 | return MPCQT_PREFIX "/share/mpc-qt"; 95 | #endif 96 | } 97 | return "."; 98 | } 99 | 100 | QString Platform::fixedConfigPath(QString configPath) 101 | { 102 | if (isWindows) { 103 | // backward compatability sucks 104 | configPath.replace("AppData/Local","AppData/Roaming"); 105 | } 106 | return configPath; 107 | } 108 | 109 | QString Platform::sanitizedFilename(QString fileName) 110 | { 111 | if (isWindows) 112 | fileName.replace(':', '.'); 113 | return fileName; 114 | } 115 | 116 | bool Platform::tiledDesktopsExist() 117 | { 118 | return isUnix; 119 | } 120 | 121 | bool Platform::tilingDesktopActive() 122 | { 123 | if (!isUnix) 124 | return false; 125 | 126 | QProcessEnvironment env; 127 | QStringList tilers({ "awesome", "bspwm", "dwm", "i3", "larswm", "ion", 128 | "qtile", "ratpoison", "stumpwm", "wmii", "xmonad"}); 129 | QString desktop = env.value("XDG_SESSION_DESKTOP", "="); 130 | if (tilers.contains(desktop)) 131 | return true; 132 | desktop = env.value("XDG_DATA_DIRS", "="); 133 | for (QString &wm : tilers) 134 | if (desktop.contains(wm)) 135 | return true; 136 | for (QString &wm: tilers) { 137 | QProcess process; 138 | process.start("pgrep", QStringList({"-x", wm})); 139 | process.waitForFinished(); 140 | if (!process.readAllStandardOutput().isEmpty()) 141 | return true; 142 | } 143 | return false; 144 | } 145 | 146 | void Platform::disableAutomaticAccel(QWidget *what) 147 | { 148 | #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) 149 | static auto symbol = "_ZN19KAcceleratorManager10setNoAccelEP7QWidget"; 150 | 151 | void *d = dlopen("libKF5WidgetsAddons.so", RTLD_LAZY); 152 | if (!d) 153 | return; 154 | typedef void (*DisablerFunc)(QWidget *); 155 | DisablerFunc setNoAccel; 156 | setNoAccel = reinterpret_cast(dlsym(d, symbol)); 157 | if (setNoAccel) 158 | setNoAccel(what); 159 | dlclose(d); 160 | #else 161 | Q_UNUSED(what); 162 | #endif 163 | } 164 | -------------------------------------------------------------------------------- /platform/unify.h: -------------------------------------------------------------------------------- 1 | #ifndef PLATFORM_ALL_H 2 | #define PLATFORM_ALL_H 3 | 4 | #include 5 | #include 6 | 7 | class DeviceManager; 8 | class ScreenSaver; 9 | 10 | namespace Platform { 11 | extern const bool isMac; 12 | extern const bool isWindows; 13 | extern const bool isUnix; 14 | 15 | DeviceManager *deviceManager(); 16 | ScreenSaver *screenSaver(); 17 | 18 | QString resourcesPath(); 19 | QString fixedConfigPath(QString configPath); 20 | QString sanitizedFilename(QString fileName); 21 | bool tiledDesktopsExist(); 22 | bool tilingDesktopActive(); 23 | void disableAutomaticAccel(QWidget *what); 24 | } 25 | 26 | #endif // PLATFORM_ALL_H 27 | -------------------------------------------------------------------------------- /propertieswindow.h: -------------------------------------------------------------------------------- 1 | #ifndef PROPERTIESWINDOW_H 2 | #define PROPERTIESWINDOW_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace Ui { 10 | class PropertiesWindow; 11 | } 12 | 13 | class PropertiesWindow : public QDialog 14 | { 15 | Q_OBJECT 16 | 17 | public: 18 | explicit PropertiesWindow(QWidget *parent = nullptr); 19 | ~PropertiesWindow(); 20 | 21 | public slots: 22 | void setFileName(const QString &filename); 23 | void setFileFormat(const QString &format); 24 | void setFileSize(const int64_t &bytes); 25 | void setMediaLength(double time); 26 | void setVideoSize(const QSize &sz); 27 | void setFileCreationTime(const int64_t &secsSinceEpoch); 28 | void setTracks(const QVariantList &tracks); 29 | void setMediaTitle(const QString &title); 30 | void setFilePath(const QString &path); 31 | void setMetaData(QVariantMap data); 32 | void setChapters(const QVariantList &chapters); 33 | 34 | private slots: 35 | void on_save_clicked(); 36 | void updateSaveVisibility(); 37 | 38 | private: 39 | void updateLastTab(); 40 | QString sectionText(const QString &header, const QVariantMap &fields); 41 | 42 | Ui::PropertiesWindow *ui; 43 | 44 | QString filename; 45 | QString metadataText; 46 | QString trackText; 47 | QString chapterText; 48 | }; 49 | 50 | #endif // PROPERTIESWINDOW_H 51 | -------------------------------------------------------------------------------- /res.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | text/playlistFormat.html 4 | text/encodeFormat.html 5 | images/logo/triangle-circle.svg 6 | images/logo/mpv-vlc.svg 7 | images/logo/film-color.svg 8 | images/logo/film-gray.svg 9 | images/theme/black/media-playback-start.svg 10 | images/theme/black/media-playback-pause.svg 11 | images/theme/black/media-playback-stop.svg 12 | images/theme/black/media-seek-backward.svg 13 | images/theme/black/media-seek-forward.svg 14 | images/theme/black/go-previous.svg 15 | images/theme/black/go-next.svg 16 | images/theme/black/media-skip-backward.svg 17 | images/theme/black/media-skip-forward.svg 18 | images/theme/black/player-volume.svg 19 | images/theme/black/player-volume-muted.svg 20 | images/theme/black/zone-in.svg 21 | images/theme/black/zone-out.svg 22 | images/theme/black/tab-new.svg 23 | images/theme/black/tab-close.svg 24 | images/theme/black/tab-duplicate.svg 25 | images/theme/black/document-import.svg 26 | images/theme/black/document-export.svg 27 | images/theme/black/media-queue-visible.svg 28 | images/theme/black/view-media-queue.svg 29 | images/icon/mpc-qt.svg 30 | images/icon/tinyicon.svg 31 | images/theme/white/video-x-generic-16.svg 32 | images/theme/white/media-playback-start.svg 33 | images/theme/white/media-playback-stop.svg 34 | images/theme/white/media-playback-pause.svg 35 | images/theme/white/tab-close.svg 36 | images/theme/white/media-skip-backward.svg 37 | images/theme/white/video-x-generic-32.svg 38 | images/theme/white/media-skip-forward.svg 39 | images/theme/white/media-seek-backward.svg 40 | images/theme/white/media-seek-forward.svg 41 | images/theme/white/tab-duplicate.svg 42 | images/theme/white/zone-in.svg 43 | images/theme/white/zone-out.svg 44 | images/theme/white/player-volume-muted.svg 45 | images/theme/white/tab-new.svg 46 | images/theme/white/go-previous.svg 47 | images/theme/white/go-next.svg 48 | images/theme/white/document-import.svg 49 | images/theme/white/document-export.svg 50 | images/theme/white/player-volume.svg 51 | images/theme/white/media-queue-visible.svg 52 | images/theme/white/view-media-queue.svg 53 | images/theme/black/view-media-subtitles-hidden.svg 54 | images/theme/black/view-media-subtitles.svg 55 | images/theme/white/view-media-subtitles-hidden.svg 56 | images/theme/white/view-media-subtitles.svg 57 | http/index.html 58 | 59 | 60 | -------------------------------------------------------------------------------- /storage.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "storage.h" 11 | #include "platform/unify.h" 12 | 13 | QString Storage::configPath; 14 | 15 | Storage::Storage(QObject *parent) : 16 | QObject(parent) 17 | { 18 | QDir().mkpath(fetchConfigPath()); 19 | } 20 | 21 | QString Storage::fetchConfigPath() 22 | { 23 | if (configPath.isEmpty()) { 24 | configPath = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation); 25 | configPath = Platform::fixedConfigPath(configPath); 26 | } 27 | return configPath; 28 | } 29 | 30 | void Storage::writeVMap(QString name, const QVariantMap &qvm) 31 | { 32 | QJsonDocument doc; 33 | doc.setObject(QJsonObject::fromVariantMap(qvm)); 34 | writeJsonObject(name, doc); 35 | } 36 | 37 | QVariantMap Storage::readVMap(QString name) 38 | { 39 | QJsonDocument doc = readJsonObject(name); 40 | return doc.object().toVariantMap(); 41 | } 42 | 43 | void Storage::writeVList(QString name, const QVariantList &qvl) 44 | { 45 | QJsonDocument doc; 46 | doc.setArray(QJsonArray::fromVariantList(qvl)); 47 | writeJsonObject(name, doc); 48 | } 49 | 50 | QVariantList Storage::readVList(QString name) 51 | { 52 | QJsonDocument doc = readJsonObject(name); 53 | return doc.array().toVariantList(); 54 | } 55 | 56 | QStringList Storage::readM3U(const QString &where) 57 | { 58 | QStringList items; 59 | QFile file(where); 60 | if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) 61 | return QStringList(); 62 | items = QTextStream(&file).readAll().split("\n"); 63 | for (int i = 0; i < items.count(); ++i) { 64 | items[i] = items[i].trimmed(); 65 | if (items[i].isEmpty() || items[i].startsWith("#")) { 66 | items.removeAt(i); 67 | --i; 68 | } 69 | } 70 | return items; 71 | } 72 | 73 | void Storage::writeM3U(const QString &where, QStringList items) 74 | { 75 | QFile file(where); 76 | if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) 77 | return; 78 | QTextStream(&file) << "#EXTM3U\n\n" << items.join("\n"); 79 | } 80 | 81 | void Storage::writeJsonObject(QString fname, const QJsonDocument &doc) 82 | { 83 | QFile file(QDir(configPath).absoluteFilePath(fname + ".json")); 84 | if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) 85 | return; 86 | QTextStream(&file) << doc.toJson(); 87 | } 88 | 89 | QJsonDocument Storage::readJsonObject(QString fname) 90 | { 91 | QFile file(QDir(configPath).absoluteFilePath(fname + ".json")); 92 | if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) 93 | return QJsonDocument(); 94 | QJsonDocument doc = QJsonDocument::fromJson(QTextStream(&file).readAll().toUtf8()); 95 | return doc; 96 | } 97 | -------------------------------------------------------------------------------- /storage.h: -------------------------------------------------------------------------------- 1 | #ifndef STORAGE_H 2 | #define STORAGE_H 3 | 4 | #include 5 | 6 | class Storage : public QObject 7 | { 8 | Q_OBJECT 9 | public: 10 | explicit Storage(QObject *parent = nullptr); 11 | static QString fetchConfigPath(); 12 | 13 | void writeVMap(QString name, const QVariantMap &qvm); 14 | QVariantMap readVMap(QString name); 15 | 16 | void writeVList(QString name, const QVariantList &qvl); 17 | QVariantList readVList(QString name); 18 | 19 | QStringList readM3U(const QString &where); 20 | void writeM3U(const QString &where, QStringList items); 21 | 22 | private: 23 | void writeJsonObject(QString fname, const QJsonDocument &doc); 24 | QJsonDocument readJsonObject(QString fname); 25 | 26 | signals: 27 | 28 | public slots: 29 | 30 | private: 31 | static QString configPath; 32 | }; 33 | 34 | #endif // STORAGE_H 35 | -------------------------------------------------------------------------------- /text/playlistFormat.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 11 | 12 | 13 | 19 | 20 | 21 |

Format specifiers

22 |


23 |

If no format specifier is set, mpc will attempt to use a sensible default. A format string is composed of %prop tuples, where prop is a metadata property returned by mpv. When mpc has not received any metadata about a file, it will display the filename (minus the extension and the dot).

24 |


25 |

%prop{tag present}{audio file}{video file}

26 |

Expands to the text as decoded by format string X if the tag was present, and optionally if the tag was not present, whether the file was an audio or video file. Files without an audio or video track will be decoded to nothing. For example %author{# - }{Unknown - }{} will expand to "John Doe - " when a music file specifies who the author is, "Unknown - " when a music file does not specify who the author is, and nothing when a video file does not specify who the author is (as would be the expected case for most video files). If the second and/or third pair of {} are not specified, they will be parsed as if they were empty.

27 |


28 |

Format string X

29 |


30 |

#

31 |

A special character that expands to whatever the current property may be. Nothing if there is no current property or the current property is empty.

32 |


33 |

##

34 |

Expands to a hash sign.

35 |


36 |

$

37 |

A special character which expands to the filename (minus the extension and the dot). Useful for when no or insufficient metadata is present.

38 |


39 |

$$

40 |

Expands to a dollar sign

41 |


42 |

Useful metadata properties

43 |


44 |

album

45 |

author

46 |

date

47 |

genre

48 |

title

49 |

track

50 | 51 | 52 | -------------------------------------------------------------------------------- /thumbnailerwindow.h: -------------------------------------------------------------------------------- 1 | #ifndef THUMBNAILERWINDOW_H 2 | #define THUMBNAILERWINDOW_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "mpvwidget.h" 10 | 11 | namespace Ui { 12 | class ThumbnailerWindow; 13 | } 14 | class MpvThumbnailDrawer; 15 | class MpvThumbnailer; 16 | 17 | class ThumbnailerWindow : public QWidget 18 | { 19 | Q_OBJECT 20 | 21 | public: 22 | explicit ThumbnailerWindow(QWidget *parent = nullptr); 23 | ~ThumbnailerWindow(); 24 | 25 | public slots: 26 | void open(QUrl sourceUrl); 27 | void begin(); 28 | void setScreenshotDirectory(QString folder); 29 | void setScreenshotFormat(QString format); 30 | 31 | private slots: 32 | void on_saveImageBrowse_clicked(); 33 | void thumbnailer_setProgress(int percent); 34 | void thumbnailer_finished(); 35 | 36 | private: 37 | Ui::ThumbnailerWindow *ui = nullptr; 38 | MpvThumbnailer *thumbnailer = nullptr; 39 | QString screenshotDirectory; 40 | QString screenshotFormat = "png"; 41 | }; 42 | 43 | class MpvThumbnailer : public QObject { 44 | Q_OBJECT 45 | 46 | enum ThumbnailingState { 47 | AvailableState, // Available for use 48 | StartedState, // File opened 49 | StaleState, // File opened, but no video size yet 50 | SeekingState, // Seek command sent 51 | PlayingState, // Playing video until frozen 52 | WaitingForTimer, // Waiting for snapshot timer 53 | FinishedState // Playback finished 54 | }; 55 | 56 | struct ThumbPts { 57 | int x, y; 58 | double pts; 59 | int percent, index; 60 | QImage thumb; 61 | }; 62 | 63 | public: 64 | struct Params { 65 | QUrl sourceUrl; 66 | QString imageFile; 67 | int jpegQuality, imageWidth; 68 | int cols, rows; 69 | }; 70 | 71 | explicit MpvThumbnailer(QObject *parent); 72 | ~MpvThumbnailer(); 73 | void execute(const Params &p); 74 | 75 | signals: 76 | void progress(int percent); 77 | void finished(); 78 | 79 | private: 80 | void initPlayer(); 81 | void deinitPlayer(); 82 | 83 | void initThumbPts(); 84 | void processThumb(); 85 | bool seekNextFrame(); 86 | void renderImage(); 87 | void saveImage(); 88 | 89 | private slots: 90 | void mpv_fileSizeChanged(int64_t bytes); 91 | void mpv_videoSizeChanged(QSize size); 92 | void mpv_playLengthChanged(double length); 93 | void mpv_playTimeChanged(double time); 94 | void mpv_playbackFinished(); 95 | void mpv_playbackIdling(); 96 | void timer_navigateTick(); 97 | 98 | private: 99 | Params p; 100 | MpvObject *mpv = nullptr; 101 | MpvThumbnailDrawer *thumbnailer = nullptr; 102 | 103 | ThumbnailingState thumbState = AvailableState; 104 | double mpvTime = -1; 105 | double mpvDuration = -1; 106 | Helpers::TimeFormat osdTimeFormat = Helpers::ShortFormat; 107 | int64_t mpvFileSize = 0; 108 | QSize mpvVideoSize = {-1,-1}; 109 | QQueue pendingPts; 110 | QQueue processedPts; 111 | QImage render; 112 | QSize thumbSize; 113 | }; 114 | 115 | 116 | class MpvThumbnailDrawer : public QOpenGLWidget, public MpvWidgetInterface { 117 | Q_OBJECT 118 | Q_INTERFACES(MpvWidgetInterface) 119 | 120 | public: 121 | explicit MpvThumbnailDrawer(MpvObject *object); 122 | ~MpvThumbnailDrawer(); 123 | 124 | QWidget *self(); 125 | void initMpv(); 126 | void setLogoUrl(const QString &filename); 127 | void setLogoBackground(const QColor &color); 128 | void setDrawLogo(bool yes); 129 | 130 | signals: 131 | void renderedFrame(); 132 | 133 | protected: 134 | void initializeGL(); 135 | void paintGL(); 136 | void resizeGL(int w, int h); 137 | 138 | private slots: 139 | void alwaysUpdate(); 140 | 141 | private: 142 | static void render_update(void *ctx); 143 | mpv_render_context *render = nullptr; 144 | int glWidth, glHeight; 145 | }; 146 | 147 | #endif // THUMBNAILERWINDOW_H 148 | -------------------------------------------------------------------------------- /widgets/actioneditor.h: -------------------------------------------------------------------------------- 1 | #ifndef QACTIONEDITOR_H 2 | #define QACTIONEDITOR_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "helpers.h" 10 | 11 | 12 | 13 | class QKeySequenceEdit; 14 | class QToolButton; 15 | class QComboBox; 16 | 17 | 18 | 19 | class ActionEditor : public QTableView 20 | { 21 | Q_OBJECT 22 | public: 23 | ActionEditor(QWidget *parent = nullptr); 24 | 25 | void setCommands(const QList &commands); 26 | Command getCommand(int index) const; 27 | void setCommand(int index, const Command &c); 28 | void updateActions(); 29 | 30 | QVariantMap toVMap() const; 31 | void fromVMap(const QVariantMap &map); 32 | 33 | signals: 34 | void mouseFullscreenMap(MouseStateMap map); 35 | void mouseWindowedMap(MouseStateMap map); 36 | 37 | private: 38 | QStandardItemModel model; 39 | QList commands; 40 | }; 41 | 42 | 43 | 44 | class ShortcutWidget :public QWidget { 45 | Q_OBJECT 46 | public: 47 | ShortcutWidget(QWidget *parent = nullptr); 48 | void setKeySequence(const QKeySequence &keySequence); 49 | QKeySequence keySequence(); 50 | 51 | private slots: 52 | void keyClear_clicked(); 53 | 54 | private: 55 | QKeySequenceEdit *keyEditor = nullptr; 56 | QToolButton *keyClear = nullptr; 57 | }; 58 | 59 | 60 | 61 | class ShortcutDelegate : public QStyledItemDelegate { 62 | Q_OBJECT 63 | public: 64 | ShortcutDelegate(QObject *parent = nullptr); 65 | virtual QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const; 66 | virtual void setEditorData(QWidget *editor, const QModelIndex &index) const; 67 | virtual void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const; 68 | virtual void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const; 69 | 70 | private: 71 | ActionEditor *owner = nullptr; 72 | }; 73 | 74 | 75 | 76 | 77 | class ButtonWidget : public QWidget { 78 | Q_OBJECT 79 | public: 80 | ButtonWidget(QWidget * parent = nullptr); 81 | void setState(const MouseState &state); 82 | MouseState state() const; 83 | 84 | private slots: 85 | void buttonMenu_selected(int item); 86 | void keyModMenu_selected(int item, bool yes); 87 | void pressMenu_selected(int item); 88 | 89 | private: 90 | QList buttonActions; 91 | QList keyModActions; 92 | QList pressActions; 93 | QToolButton *button = nullptr; 94 | QToolButton *keyMod = nullptr; 95 | QToolButton *press = nullptr; 96 | MouseState state_; 97 | }; 98 | 99 | 100 | 101 | class ButtonDelegate : public QStyledItemDelegate { 102 | Q_OBJECT 103 | public: 104 | ButtonDelegate(QObject *parent = nullptr, bool fullscreen = false); 105 | virtual QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const; 106 | virtual void setEditorData(QWidget *editor, const QModelIndex &index) const; 107 | virtual void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const; 108 | virtual void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const; 109 | 110 | private: 111 | ActionEditor *owner = nullptr; 112 | bool fullscreen = false; 113 | }; 114 | 115 | #endif // QACTIONEDITOR_H 116 | -------------------------------------------------------------------------------- /widgets/drawncollection.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "drawncollection.h" 4 | 5 | CollectionPainter::CollectionPainter(QObject *parent) : QAbstractItemDelegate(parent) 6 | { 7 | 8 | } 9 | 10 | void CollectionPainter::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const 11 | { 12 | DrawnCollection *collectionWidget = qobject_cast(parent()); 13 | auto collection = collectionWidget->collection(); 14 | auto playlist = collection->playlistOf(QUuid(index.data(Qt::DisplayRole).toString())); 15 | 16 | 17 | QStyleOptionViewItem o2 = option; 18 | QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &o2, 19 | painter); 20 | QRect rc = option.rect.adjusted(3,0,-3,0); 21 | 22 | QString text = playlist->title(); 23 | QFont f = collectionWidget->font(); 24 | painter->setFont(f); 25 | painter->setPen(collectionWidget->palette().text().color()); 26 | painter->drawText(rc, Qt::AlignLeft|Qt::AlignVCenter, text); 27 | painter->setFont(collectionWidget->font()); 28 | } 29 | 30 | QSize CollectionPainter::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const 31 | { 32 | Q_UNUSED(index) 33 | return QApplication::style()->sizeFromContents(QStyle::CT_ItemViewItem, 34 | &option, 35 | option.rect.size()); 36 | } 37 | 38 | 39 | 40 | CollectionItem::CollectionItem(QUuid uuid, QListWidget *parent) 41 | : QListWidgetItem(uuid.toString(), parent) 42 | { 43 | uuid_ = uuid; 44 | } 45 | 46 | QUuid CollectionItem::uuid() 47 | { 48 | return uuid_; 49 | } 50 | 51 | 52 | 53 | DrawnCollection::DrawnCollection(QSharedPointer collection, QWidget *parent) : QListWidget(parent) 54 | { 55 | collection_ = collection; 56 | setItemDelegate(new CollectionPainter(this)); 57 | 58 | connect(this, &DrawnCollection::currentRowChanged, 59 | this, &DrawnCollection::self_currentRowChanged); 60 | } 61 | 62 | QSharedPointer DrawnCollection::collection() 63 | { 64 | return collection_; 65 | } 66 | 67 | void DrawnCollection::addPlaylist(QUuid playlistUuid) 68 | { 69 | CollectionItem *playItem = new CollectionItem(playlistUuid, this); 70 | addItem(playItem); 71 | } 72 | 73 | QUuid DrawnCollection::currentPlaylistUuid() 74 | { 75 | auto ci = reinterpret_cast(currentItem()); 76 | if (!ci) 77 | ci = reinterpret_cast(item(0)); 78 | return ci ? ci->uuid() : QUuid(); 79 | } 80 | 81 | 82 | void DrawnCollection::repopulatePlaylists() 83 | { 84 | clear(); 85 | auto itemAdder = [&](QSharedPointer playlist) { 86 | addPlaylist(playlist->uuid()); 87 | }; 88 | collection_->iteratePlaylists(itemAdder); 89 | } 90 | 91 | void DrawnCollection::self_currentRowChanged(int currentRow) 92 | { 93 | QUuid uuid; 94 | if (currentRow != -1) 95 | uuid = reinterpret_cast(this->item(currentRow))->uuid(); 96 | emit playlistSelected(uuid); 97 | } 98 | 99 | -------------------------------------------------------------------------------- /widgets/drawncollection.h: -------------------------------------------------------------------------------- 1 | #ifndef DRAWNCOLLECTION_H 2 | #define DRAWNCOLLECTION_H 3 | 4 | #include 5 | #include 6 | #include "playlist.h" 7 | 8 | class CollectionPainter : public QAbstractItemDelegate 9 | { 10 | Q_OBJECT 11 | public: 12 | CollectionPainter(QObject *parent = nullptr); 13 | void paint(QPainter *painter, const QStyleOptionViewItem &option, 14 | const QModelIndex &index) const; 15 | QSize sizeHint(const QStyleOptionViewItem &option, 16 | const QModelIndex &index) const; 17 | }; 18 | 19 | class CollectionItem : public QListWidgetItem 20 | { 21 | public: 22 | CollectionItem(QUuid uuid, QListWidget *parent = nullptr); 23 | QUuid uuid(); 24 | private: 25 | QUuid uuid_; 26 | }; 27 | 28 | 29 | class DrawnCollection : public QListWidget 30 | { 31 | Q_OBJECT 32 | public: 33 | DrawnCollection(QSharedPointer collection, QWidget *parent = nullptr); 34 | QSharedPointer collection(); 35 | 36 | void addPlaylist(QUuid playlistUuid); 37 | QUuid currentPlaylistUuid(); 38 | 39 | signals: 40 | void playlistSelected(QUuid); 41 | 42 | public slots: 43 | void repopulatePlaylists(); 44 | 45 | private slots: 46 | void self_currentRowChanged(int currentRow); 47 | 48 | private: 49 | QSharedPointer collection_; 50 | }; 51 | 52 | #endif // DRAWNCOLLECTION_H 53 | -------------------------------------------------------------------------------- /widgets/drawnslider.h: -------------------------------------------------------------------------------- 1 | #ifndef QDRAWNSLIDER_H 2 | #define QDRAWNSLIDER_H 3 | // A set of simplistic (okay, not really) multimedia widgets that mimics stock 4 | // QSliders, but completely disregards their storage semantics. 5 | // 6 | // These widgets use doubles rather than integers to store their positional- 7 | // related attributes. This is important because timestamps are usually more 8 | // accurate than a single second. 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | class DrawnSlider : public QWidget { 15 | Q_OBJECT 16 | 17 | public: 18 | explicit DrawnSlider(QWidget *parent, QSize handle, QSize margin); 19 | void setValue(double v); 20 | void setMaximum(double v); 21 | void setMinimum(double v); 22 | double value(); 23 | double maximum(); 24 | double minimum(); 25 | 26 | signals: 27 | void sliderMoved(double v); 28 | 29 | protected: 30 | void setSliderGeometry(int handleWidth, int handleHeight, 31 | int marginX, int marginY); 32 | virtual void makeBackground() = 0; 33 | virtual void makeHandle() = 0; 34 | virtual void handleHover(double x); 35 | 36 | double valueToX(double value); 37 | double xToValue(double x); 38 | 39 | void paintEvent(QPaintEvent *event); 40 | void resizeEvent(QResizeEvent *event); 41 | 42 | bool redrawPics = true; 43 | QImage backgroundPic; 44 | QImage handlePics[16]; 45 | 46 | QRectF drawnArea; 47 | QRectF grooveArea; 48 | QRectF sliderArea; 49 | QColor grooveBorder, grooveFill; 50 | QColor handleBorder, handleFill; 51 | QColor bgColor, loopColor, markColor; 52 | int handleWidth, handleHeight, marginX, marginY; 53 | 54 | private: 55 | void mousePressEvent(QMouseEvent *ev); 56 | void mouseReleaseEvent(QMouseEvent *ev); 57 | void mouseMoveEvent(QMouseEvent *ev); 58 | 59 | bool isDragging = false; 60 | double xPosition = 0.0; 61 | 62 | double vValue = 0.0; 63 | double vMaximum = 0.0; 64 | double vMinimum = 0.0; 65 | }; 66 | 67 | class MediaSlider : public DrawnSlider { 68 | Q_OBJECT 69 | public: 70 | explicit MediaSlider(QWidget *parent = nullptr); 71 | 72 | void clearTicks(); 73 | void setTick(double value, QString text); 74 | void setLoopA(double a); 75 | void setLoopB(double b); 76 | double loopA(); 77 | double loopB(); 78 | bool isLoopEmpty(); 79 | 80 | signals: 81 | void hoverBegin(); 82 | void hoverEnd(); 83 | void hoverValue(double value, QString text, double x); 84 | 85 | protected: 86 | void resizeEvent(QResizeEvent *event); 87 | void makeBackground(); 88 | void makeHandle(); 89 | void enterEvent(QEvent *event); 90 | void leaveEvent(QEvent *event); 91 | void handleHover(double x); 92 | 93 | void updateLoopArea(); 94 | 95 | QString valueToTickText(double value); 96 | QMap ticks; 97 | double vLoopA = -1; 98 | double vLoopB = -1; 99 | QRectF loopArea = { -1, -1, 0, 0}; 100 | }; 101 | 102 | class VolumeSlider : public DrawnSlider { 103 | Q_OBJECT 104 | 105 | public: 106 | explicit VolumeSlider(QWidget *parent = nullptr); 107 | 108 | protected: 109 | void makeBackground(); 110 | void makeHandle(); 111 | }; 112 | #endif // QDRAWNSLIDER_H 113 | -------------------------------------------------------------------------------- /widgets/drawnstatus.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "helpers.h" 4 | #include "drawnstatus.h" 5 | 6 | StatusTime::StatusTime(QWidget *parent) : QWidget(parent) 7 | { 8 | setTime(0, 0); 9 | setMinimumSize(minimumSizeHint()); 10 | } 11 | 12 | QSize StatusTime::minimumSizeHint() const 13 | { 14 | QSize sz = QFontMetrics(font()).size(0, drawnText); 15 | return sz; 16 | } 17 | 18 | void StatusTime::setTime(double time, double duration) 19 | { 20 | if (currentDuration != duration) { 21 | currentDuration = duration; 22 | updateTimeFormat(); 23 | } else if (currentTime == time) 24 | return; 25 | currentTime = time; 26 | updateText(); 27 | } 28 | 29 | void StatusTime::setShortMode(bool shortened) 30 | { 31 | if (shortMode == shortened) 32 | return; 33 | shortMode = shortened; 34 | lastTextLength = 0; 35 | updateTimeFormat(); 36 | updateText(); 37 | } 38 | 39 | void StatusTime::updateTimeFormat() 40 | { 41 | Helpers::TimeFormat format; 42 | if (int(currentDuration*1000 + 0.5) >= 3600000) 43 | format = shortMode ? Helpers::ShortFormat : Helpers::LongFormat; 44 | else 45 | format = shortMode ? Helpers::ShortHourFormat : Helpers::LongHourFormat; 46 | if (timeFormat == format) 47 | return; 48 | timeFormat = format; 49 | } 50 | 51 | void StatusTime::updateText() 52 | { 53 | drawnText = Helpers::toDateFormatFixed(currentTime, timeFormat); 54 | int drawnTextLength = drawnText.length(); 55 | if (drawnTextLength != lastTextLength) { 56 | setMinimumSize(minimumSizeHint()); 57 | lastTextLength = drawnTextLength; 58 | } 59 | update(); 60 | } 61 | 62 | void StatusTime::paintEvent(QPaintEvent *event) 63 | { 64 | Q_UNUSED(event) 65 | QPainter p(this); 66 | QColor bgColor = parentWidget()->palette().color(QPalette::Active, QPalette::Window); 67 | QColor txColor = parentWidget()->palette().color(QPalette::Active, QPalette::WindowText); 68 | QRectF rc = QRectF(QPointF(0,0), QSizeF(size())).adjusted(-0.5,-0.5,0.5,0.5); 69 | p.fillRect(rc, bgColor); 70 | p.setPen(txColor); 71 | p.drawText(rc, drawnText, QTextOption(Qt::AlignRight | Qt::AlignVCenter)); 72 | } 73 | 74 | -------------------------------------------------------------------------------- /widgets/drawnstatus.h: -------------------------------------------------------------------------------- 1 | #ifndef QDRAWNSTATUS_H 2 | #define QDRAWNSTATUS_H 3 | 4 | #include 5 | #include "helpers.h" 6 | 7 | class StatusTime : public QWidget 8 | { 9 | Q_OBJECT 10 | public: 11 | explicit StatusTime(QWidget *parent = nullptr); 12 | virtual QSize minimumSizeHint() const; 13 | 14 | void setTime(double time, double duration); 15 | void setShortMode(bool shortened); 16 | 17 | protected: 18 | void updateTimeFormat(); 19 | void updateText(); 20 | void paintEvent(QPaintEvent *event); 21 | 22 | private: 23 | bool shortMode = false; 24 | Helpers::TimeFormat timeFormat = Helpers::LongFormat; 25 | double currentTime = 0; 26 | double currentDuration = 0; 27 | QString drawnText; 28 | int lastTextLength = 0; 29 | }; 30 | 31 | #endif // QDRAWNSTATUS_H 32 | -------------------------------------------------------------------------------- /widgets/logowidget.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "logowidget.h" 3 | 4 | LogoDrawer::LogoDrawer(QObject *parent) 5 | : QObject(parent) 6 | { 7 | setLogoUrl(""); 8 | setLogoBackground(QColor(0,0,0)); 9 | } 10 | 11 | LogoDrawer::~LogoDrawer() 12 | { 13 | 14 | } 15 | 16 | void LogoDrawer::setLogoUrl(const QString &filename) 17 | { 18 | logoUrl = filename.isEmpty() ? ":/images/bitmaps/blank-screen.png" 19 | : filename; 20 | regenerateTexture(); 21 | } 22 | 23 | void LogoDrawer::setLogoBackground(const QColor &color) 24 | { 25 | logoBackground = color.isValid() ? color : QColor(0,0,0); 26 | } 27 | 28 | void LogoDrawer::resizeGL(int w, int h) 29 | { 30 | QTransform t; 31 | t.scale(2.0/w, 2.0/h); 32 | t.translate(((w + logo.width())&1)/2.0, 33 | ((h + logo.height())&1)/2.0); 34 | logoLocation = t.mapRect(QRectF(-logo.width()/2.0, -logo.height()/2.0, 35 | logo.width(), logo.height())); 36 | 37 | if (logoLocation.height() > 2) { 38 | t.reset(); 39 | t.scale(2/logoLocation.height(), 2/logoLocation.height()); 40 | logoLocation = t.mapRect(logoLocation); 41 | } 42 | if (logoLocation.width() > 2) { 43 | t.reset(); 44 | t.scale(2/logoLocation.width(), 2/logoLocation.width()); 45 | logoLocation = t.mapRect(logoLocation); 46 | } 47 | } 48 | 49 | void LogoDrawer::paintGL(QOpenGLWidget *widget) 50 | { 51 | QPainter painter(widget); 52 | int ratio = widget->devicePixelRatio(); 53 | QRect window(-1, -1, 2*ratio, 2*ratio); 54 | painter.setWindow(window); 55 | painter.setRenderHint(QPainter::SmoothPixmapTransform); 56 | painter.fillRect(window, QBrush(logoBackground)); 57 | if (!logo.isNull()) 58 | painter.drawImage(logoLocation, logo); 59 | } 60 | 61 | void LogoDrawer::regenerateTexture() 62 | { 63 | logo.load(logoUrl); 64 | emit logoSize(logo.size()); 65 | } 66 | 67 | 68 | 69 | LogoWidget::LogoWidget(QWidget *parent) 70 | : QOpenGLWidget(parent) 71 | { 72 | } 73 | 74 | LogoWidget::~LogoWidget() 75 | { 76 | if (logoDrawer) { 77 | makeCurrent(); 78 | delete logoDrawer; 79 | logoDrawer = nullptr; 80 | } 81 | } 82 | 83 | void LogoWidget::setLogo(const QString &filename) { 84 | logoUrl = filename; 85 | if (logoDrawer) { 86 | makeCurrent(); 87 | logoDrawer->setLogoUrl(filename); 88 | logoDrawer->resizeGL(width(), height()); 89 | doneCurrent(); 90 | update(); 91 | } 92 | } 93 | 94 | void LogoWidget::setLogoBackground(const QColor &color) 95 | { 96 | logoBackground = color; 97 | if (logoDrawer) 98 | logoDrawer->setLogoBackground(color); 99 | } 100 | 101 | void LogoWidget::initializeGL() 102 | { 103 | if (!logoDrawer) { 104 | logoDrawer = new LogoDrawer(this); 105 | logoDrawer->setLogoUrl(logoUrl); 106 | logoDrawer->setLogoBackground(logoBackground); 107 | } 108 | } 109 | 110 | void LogoWidget::paintGL() 111 | { 112 | logoDrawer->paintGL(this); 113 | } 114 | 115 | void LogoWidget::resizeGL(int w, int h) 116 | { 117 | logoDrawer->resizeGL(w,h); 118 | } 119 | -------------------------------------------------------------------------------- /widgets/logowidget.h: -------------------------------------------------------------------------------- 1 | #ifndef LOGOWIDGET_H 2 | #define LOGOWIDGET_H 3 | 4 | #include 5 | #include 6 | 7 | class LogoDrawer : public QObject { 8 | Q_OBJECT 9 | public: 10 | explicit LogoDrawer(QObject *parent = nullptr); 11 | ~LogoDrawer(); 12 | void setLogoUrl(const QString &filename); 13 | void setLogoBackground(const QColor &color); 14 | void resizeGL(int w, int h); 15 | void paintGL(QOpenGLWidget *widget); 16 | 17 | signals: 18 | void logoSize(QSize size); 19 | 20 | private: 21 | void regenerateTexture(); 22 | 23 | private: 24 | QRectF logoLocation; 25 | QImage logo; 26 | QString logoUrl; 27 | QColor logoBackground; 28 | }; 29 | 30 | class LogoWidget : public QOpenGLWidget { 31 | Q_OBJECT 32 | public: 33 | explicit LogoWidget(QWidget *parent = nullptr); 34 | ~LogoWidget(); 35 | void setLogo(const QString &filename); 36 | void setLogoBackground(const QColor &color); 37 | 38 | protected: 39 | void initializeGL(); 40 | void paintGL(); 41 | void resizeGL(int w, int h); 42 | 43 | private: 44 | LogoDrawer *logoDrawer = nullptr; 45 | QString logoUrl; 46 | QColor logoBackground; 47 | }; 48 | 49 | #endif // LOGOWIDGET_H 50 | -------------------------------------------------------------------------------- /widgets/paletteeditor.h: -------------------------------------------------------------------------------- 1 | #ifndef PALETTEEDITOR_H 2 | #define PALETTEEDITOR_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class PaletteBox : public QWidget 9 | { 10 | Q_OBJECT 11 | Q_PROPERTY(QColor value READ value WRITE setValue NOTIFY valueChanged) 12 | public: 13 | explicit PaletteBox(QWidget *parent = nullptr); 14 | QColor value(); 15 | 16 | signals: 17 | void valueChanged(QColor c); 18 | void valueSelected(QColor c); 19 | 20 | public slots: 21 | void setValue(const QColor &c); 22 | 23 | protected: 24 | void paintEvent(QPaintEvent *event); 25 | void mousePressEvent(QMouseEvent *event); 26 | 27 | private: 28 | QColor color; 29 | }; 30 | 31 | 32 | class PaletteEditor : public QWidget 33 | { 34 | Q_OBJECT 35 | Q_PROPERTY(QPalette palette READ palette WRITE setPalette NOTIFY paletteChanged RESET resetPalette) 36 | Q_PROPERTY(QVariant value READ variant WRITE setVariant NOTIFY valueChanged) 37 | 38 | public: 39 | typedef QPair ColorPair; 40 | typedef QMap BoxMap; 41 | typedef QMap PaletteEntries; 42 | 43 | explicit PaletteEditor(QWidget *parent = nullptr); 44 | QPalette palette(); 45 | QPalette systemPalette(); 46 | 47 | // custom variant et al routines are needed for json serialisation 48 | QVariant variant(); 49 | QPalette variantToPalette(const QVariant &v); 50 | QVariant paletteToVariant(const QPalette &p); 51 | 52 | signals: 53 | void paletteChanged(QPalette pal); 54 | void valueChanged(); 55 | 56 | public slots: 57 | void setPalette(const QPalette &pal); 58 | void setVariant(const QVariant &value); 59 | void resetPalette(); 60 | 61 | private slots: 62 | void colorField_valueSelected(PaletteEditor::ColorPair entry, QColor color); 63 | void generateButton_clicked(); 64 | void generateButtonWindow_clicked(); 65 | 66 | private: 67 | QPalette system; 68 | QPalette selected; 69 | BoxMap boxes; 70 | }; 71 | 72 | #endif // PALETTEEDITOR_H 73 | --------------------------------------------------------------------------------