13 Commits

Author SHA1 Message Date
Martin Wagner
b0a083b9f4 preparations for 1.5.1 2021-12-30 19:59:56 +01:00
Martin Wagner
710fdb44fe fixed translations of .ui files with flatpak 2021-12-30 19:56:14 +01:00
Martin Wagner
69e1ee1749 preparations for 1.5.0 2021-12-30 17:32:47 +01:00
Martin Wagner
20b8f5eb4c nl translation fix 2021-12-30 17:16:26 +01:00
Martin Wagner
d5f643eab8 fixed translation build 2021-12-30 01:23:29 +01:00
Martin Wagner
e746812c7d simplified locale settings 2021-12-29 17:20:52 +01:00
Martin Wagner
efabfca7d8 use gresource 2021-12-29 16:48:42 +01:00
Martin Wagner
fac7a3f6e3 switched to meson 2021-12-29 14:03:25 +01:00
Martin Wagner
39922e7c05 fixed mini player mode 2021-12-29 12:56:24 +01:00
Martin Wagner
4f9a8a3f35 reduced UI blocking with large collections 2021-12-22 21:17:08 +01:00
Martin Wagner
90c9628616 fixed overwrite 2021-12-21 20:14:56 +01:00
Martin Wagner
4bba0fca98 removed "use-album-artist" 2021-12-21 19:06:01 +01:00
Martin Wagner
432957e291 reworked browser to support "*sort" tags 2021-12-21 19:04:03 +01:00
33 changed files with 1316 additions and 1048 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/builddir

View File

@@ -54,7 +54,7 @@ Building
--------
Build dependencies:
- DistUtilsExtra
- meson
Dependencies:
- Gtk3
@@ -70,8 +70,9 @@ Run:
```bash
git clone https://github.com/SoongNoonien/mpdevil.git
cd mpdevil
sudo python3 setup.py install
sudo glib-compile-schemas /usr/share/glib-2.0/schemas
meson builddir --prefix=/usr/local
sudo ninja -C builddir install
sudo glib-compile-schemas /usr/local/share/glib-2.0/schemas
sudo gtk-update-icon-cache
sudo update-desktop-database
```

16
data/AboutDialog.ui Normal file
View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkAboutDialog" id="about_dialog">
<property name="modal">True</property>
<property name="program_name">mpdevil</property>
<property name="version">1.5.1</property>
<property name="comments" translatable="yes">A simple music browser for MPD</property>
<property name="authors">Martin Wagner</property>
<property name="translator_credits">Martin de Reuver
Martin Wagner</property>
<property name="website">https://github.com/SoongNoonien/mpdevil</property>
<property name="copyright">Copyright © 2020-2021 Martin Wagner</property>
<property name="license_type">gpl-3-0</property>
<property name="logo_icon_name">org.mpdevil.mpdevil</property>
</object>
</interface>

257
data/ShortcutsWindow.ui Normal file
View File

@@ -0,0 +1,257 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkShortcutsWindow" id="shortcuts_window">
<property name="modal">False</property>
<child>
<object class="GtkShortcutsSection">
<property name="visible">True</property>
<property name="section-name">shortcuts</property>
<child>
<object class="GtkShortcutsGroup">
<property name="visible">True</property>
<property name="title" translatable="yes">General</property>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">True</property>
<property name="title" translatable="yes">Open online help</property>
<property name="accelerator">F1</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">True</property>
<property name="title" translatable="yes">Open shortcuts window</property>
<property name="accelerator">&lt;Control&gt;question</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">True</property>
<property name="title" translatable="yes">Open menu</property>
<property name="accelerator">F10</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">True</property>
<property name="title" translatable="yes">Update database</property>
<property name="accelerator">F5</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">True</property>
<property name="title" translatable="yes">Quit</property>
<property name="accelerator">&lt;Control&gt;q</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkShortcutsGroup">
<property name="visible">True</property>
<property name="title" translatable="yes">Window</property>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">True</property>
<property name="title" translatable="yes">Cycle through profiles</property>
<property name="accelerator">&lt;Control&gt;p</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">True</property>
<property name="title" translatable="yes">Cycle through profiles in reversed order</property>
<property name="accelerator">&lt;Shift&gt;&lt;Control&gt;p</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">True</property>
<property name="title" translatable="yes">Toggle mini player</property>
<property name="accelerator">&lt;Control&gt;m</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">True</property>
<property name="title" translatable="yes">Toggle genre filter</property>
<property name="accelerator">&lt;Control&gt;g</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">True</property>
<property name="title" translatable="yes">Toggle lyrics</property>
<property name="accelerator">&lt;Control&gt;l</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">True</property>
<property name="title" translatable="yes">Toggle search</property>
<property name="accelerator">&lt;Control&gt;f</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">True</property>
<property name="title" translatable="yes">Back to current album</property>
<property name="accelerator">Escape</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkShortcutsGroup">
<property name="visible">True</property>
<property name="title" translatable="yes">Playback</property>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">True</property>
<property name="title" translatable="yes">Play/Pause</property>
<property name="accelerator">space</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">True</property>
<property name="title" translatable="yes">Stop</property>
<property name="accelerator">&lt;Shift&gt;space</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">True</property>
<property name="title" translatable="yes">Stop after current title</property>
<property name="accelerator">&lt;Control&gt;space</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">True</property>
<property name="title" translatable="yes">Next title</property>
<property name="accelerator">KP_Add</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">True</property>
<property name="title" translatable="yes">Previous title</property>
<property name="accelerator">KP_Subtract</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">True</property>
<property name="title" translatable="yes">Seek forward</property>
<property name="accelerator">KP_Multiply</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">True</property>
<property name="title" translatable="yes">Seek backward</property>
<property name="accelerator">KP_Divide</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">True</property>
<property name="title" translatable="yes">Toggle repeat mode</property>
<property name="accelerator">&lt;Control&gt;r</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">True</property>
<property name="title" translatable="yes">Toggle random mode</property>
<property name="accelerator">&lt;Control&gt;s</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">True</property>
<property name="title" translatable="yes">Toggle single mode</property>
<property name="accelerator">&lt;Control&gt;1</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">True</property>
<property name="title" translatable="yes">Toggle consume mode</property>
<property name="accelerator">&lt;Control&gt;o</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkShortcutsGroup">
<property name="visible">True</property>
<property name="title" translatable="yes">Search, Album Dialog, Album List and Artist List</property>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">True</property>
<property name="title" translatable="yes">Enqueue selected item</property>
<property name="accelerator">&lt;Control&gt;e</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">True</property>
<property name="title" translatable="yes">Append selected item</property>
<property name="subtitle" translatable="yes">Middle-click</property>
<property name="accelerator">&lt;Control&gt;plus</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">True</property>
<property name="title" translatable="yes">Play selected item immediately</property>
<property name="subtitle" translatable="yes">Double-click</property>
<property name="accelerator">&lt;Control&gt;Return</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">True</property>
<property name="title" translatable="yes">Show additional information</property>
<property name="subtitle" translatable="yes">Right-click</property>
<property name="accelerator">&lt;Control&gt;i Menu</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkShortcutsGroup">
<property name="visible">True</property>
<property name="title" translatable="yes">Playlist</property>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">True</property>
<property name="title" translatable="yes">Remove selected song</property>
<property name="subtitle" translatable="yes">Middle-click</property>
<property name="accelerator">Delete</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">True</property>
<property name="title" translatable="yes">Clear playlist</property>
<property name="accelerator">&lt;Shift&gt;Delete</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">True</property>
<property name="title" translatable="yes">Show additional information</property>
<property name="subtitle" translatable="yes">Right-click</property>
<property name="accelerator">&lt;Control&gt;i Menu</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</interface>

View File

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 8.6 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

Before

Width:  |  Height:  |  Size: 456 B

After

Width:  |  Height:  |  Size: 456 B

View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 8.7 KiB

View File

Before

Width:  |  Height:  |  Size: 657 B

After

Width:  |  Height:  |  Size: 657 B

21
data/meson.build Normal file
View File

@@ -0,0 +1,21 @@
i18n.merge_file(
input: 'org.mpdevil.mpdevil.desktop.in',
output: 'org.mpdevil.mpdevil.desktop',
type: 'desktop',
po_dir: '../po',
install: true,
install_dir: join_paths(get_option('datadir'), 'applications')
)
gnome.compile_resources(
'mpdevil', 'mpdevil.gresource.xml',
gresource_bundle: true,
source_dir: '.',
install_dir: resources_dir,
install: true
)
install_data('org.mpdevil.mpdevil.appdata.xml', install_dir: join_paths(get_option('datadir'), 'metainfo'))
install_data('org.mpdevil.mpdevil.gschema.xml', install_dir: join_paths(get_option('datadir'), 'glib-2.0/schemas'))
install_subdir('icons', install_dir: get_option('datadir'))

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/mpdevil/mpdevil">
<file>AboutDialog.ui</file>
<file>ShortcutsWindow.ui</file>
</gresource>
</gresources>

View File

@@ -23,7 +23,7 @@
</ul>
</description>
<releases>
<release version="1.4.1" date="2021-11-13"/>
<release version="1.5.1" date="2021-12-30"/>
</releases>
<launchable type="desktop-id">org.mpdevil.mpdevil.desktop</launchable>
<screenshots>

View File

@@ -1,11 +1,10 @@
[Desktop Entry]
Name=mpdevil
GenericName=MPD Client
_Comment=A simple music browser for MPD
Comment=A simple music browser for MPD
Exec=mpdevil
Icon=org.mpdevil.mpdevil
Terminal=false
Type=Application
StartupNotify=true
Categories=Audio;AudioVideo;Player;GTK

View File

@@ -84,10 +84,6 @@
<default>false</default>
<summary>Play selected albums directly</summary>
</key>
<key type="b" name="use-album-artist">
<default>true</default>
<summary>Use 'Album Artist' tag to group albums</summary>
</key>
<key type="b" name="mpris">
<default>true</default>
<summary>Provide MPRIS</summary>

10
meson.build Normal file
View File

@@ -0,0 +1,10 @@
project('mpdevil', version: '1.5.1')
i18n = import('i18n')
gnome = import('gnome')
resources_dir = join_paths(get_option('prefix'), get_option('datadir'), meson.project_name())
subdir('data')
subdir('src')
subdir('po')

1
po/LINGUAS Normal file
View File

@@ -0,0 +1 @@
de nl

4
po/POTFILES Normal file
View File

@@ -0,0 +1,4 @@
src/mpdevil.py
data/org.mpdevil.mpdevil.desktop.in
data/AboutDialog.ui
data/ShortcutsWindow.ui

View File

@@ -1,4 +0,0 @@
[encoding: UTF-8]
bin/mpdevil
data/org.mpdevil.mpdevil.desktop.in

511
po/de.po
View File

@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-10-23 12:59+0200\n"
"PO-Revision-Date: 2021-10-23 13:04+0200\n"
"POT-Creation-Date: 2021-12-30 01:19+0100\n"
"PO-Revision-Date: 2021-12-30 01:19+0100\n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: de\n"
@@ -18,93 +18,89 @@ msgstr ""
"X-Generator: Poedit 2.3.1\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: mpdevil:492
#: src/mpdevil.py:490
#, python-brace-format
msgid "{days} day"
msgid_plural "{days} days"
msgstr[0] "{days} Tag"
msgstr[1] "{days} Tage"
#: mpdevil:529
#: src/mpdevil.py:527
#, python-brace-format
msgid "{channels} channel"
msgid_plural "{channels} channels"
msgstr[0] "{channels} Kanal"
msgstr[1] "{channels} Kanäle"
#: mpdevil:994
#: src/mpdevil.py:1005
msgid "(restart required)"
msgstr "(Neustart erforderlich)"
#: mpdevil:1040
#: src/mpdevil.py:1051
msgid "Use Client-side decoration"
msgstr "„Client-side decoration“ benutzen"
#: mpdevil:1041
#: src/mpdevil.py:1052
msgid "Show stop button"
msgstr "Stopp-Knopf anzeigen"
#: mpdevil:1042
#: src/mpdevil.py:1053
msgid "Show audio format"
msgstr "Audioformat anzeigen"
#: mpdevil:1043
#: src/mpdevil.py:1054
msgid "Show lyrics button"
msgstr "Liedtext-Knopf anzeigen"
#: mpdevil:1044
#: src/mpdevil.py:1055
msgid "Place playlist at the side"
msgstr "Wiedergabeliste seitlich anzeigen"
#: mpdevil:1050
#: src/mpdevil.py:1061
msgid "Main cover size"
msgstr "Größe des Hauptcovers"
#: mpdevil:1051
#: src/mpdevil.py:1062
msgid "Album view cover size"
msgstr "Covergröße in Albumliste"
#: mpdevil:1052
#: src/mpdevil.py:1063
msgid "Action bar icon size"
msgstr "Symbolgröße Aktionsleiste"
#: mpdevil:1062
#: src/mpdevil.py:1073
msgid "Support “MPRIS”"
msgstr "„MPRIS“ unterstützen"
#: mpdevil:1063
msgid "Use “Album Artist” tag"
msgstr "„Album Artist“ Tag benutzen"
#: mpdevil:1064
#: src/mpdevil.py:1074
msgid "Sort albums by year"
msgstr "Alben nach Jahr sortieren"
#: mpdevil:1065
#: src/mpdevil.py:1075
msgid "Send notification on title change"
msgstr "Über Titelwechsel benachrichtigen"
#: mpdevil:1066
#: src/mpdevil.py:1076
msgid "Play selected albums and titles immediately"
msgstr "Ausgewählte Alben und Titel sofort abspielen"
#: mpdevil:1067
#: src/mpdevil.py:1077
msgid "Rewind via previous button"
msgstr "Klassischer Rück­spul­knopf"
#: mpdevil:1068
#: src/mpdevil.py:1078
msgid "Stop playback on quit"
msgstr "Wiedergabe beim Beenden stoppen"
#: mpdevil:1095
#: src/mpdevil.py:1105
msgid "Choose directory"
msgstr "Verzeichnis wählen"
#: mpdevil:1108
#: src/mpdevil.py:1118
msgid "Connect via Unix domain socket"
msgstr "Über „Unix domain socket“ verbinden"
#: mpdevil:1127
#: src/mpdevil.py:1137
msgid ""
"The first image in the same directory as the song file matching this regex "
"will be displayed. %AlbumArtist% and %Album% will be replaced by the "
@@ -114,186 +110,190 @@ msgstr ""
"regulären Ausdruck entspricht, wird angezeigt. %AlbumArtist% und %Album% "
"werden durch die entsprechenden Tags des Liedes ersetzt."
#: mpdevil:1132
#: src/mpdevil.py:1142
msgid "Socket:"
msgstr "Socket:"
#: mpdevil:1134
#: src/mpdevil.py:1144
msgid "Host:"
msgstr "Host:"
#: mpdevil:1136
#: src/mpdevil.py:1146
msgid "Password:"
msgstr "Passwort:"
#: mpdevil:1137
#: src/mpdevil.py:1147
msgid "Music lib:"
msgstr "Musikverzeichnis:"
#: mpdevil:1139
#: src/mpdevil.py:1149
msgid "Cover regex:"
msgstr "Cover-Regex:"
#: mpdevil:1163 mpdevil:3655
#: src/mpdevil.py:1173 src/mpdevil.py:3569
msgid "Profile 1"
msgstr "Profil 1"
#: mpdevil:1164 mpdevil:3655
#: src/mpdevil.py:1174 src/mpdevil.py:3569
msgid "Profile 2"
msgstr "Profil 2"
#: mpdevil:1165 mpdevil:3655
#: src/mpdevil.py:1175 src/mpdevil.py:3569
msgid "Profile 3"
msgstr "Profil 3"
#: mpdevil:1169 mpdevil:3542
#. connect button
#: src/mpdevil.py:1179 src/mpdevil.py:3451
msgid "Connect"
msgstr "Verbinden"
#: mpdevil:1194
#. label
#: src/mpdevil.py:1204
msgid "Choose the order of information to appear in the playlist:"
msgstr ""
"Lege die Reihenfolge fest, in der Informationen in der Wiedergabeliste "
"angezeigt werden sollen:"
#: mpdevil:1211 mpdevil:1643 mpdevil:1846 mpdevil:2505
#. fill store
#: src/mpdevil.py:1221 src/mpdevil.py:1641 src/mpdevil.py:1840
#: src/mpdevil.py:2461
msgid "No"
msgstr "Nr."
#: mpdevil:1211 mpdevil:2506
#: src/mpdevil.py:1221 src/mpdevil.py:2462
msgid "Disc"
msgstr "CD"
#: mpdevil:1211 mpdevil:1646 mpdevil:1677 mpdevil:1847 mpdevil:2507
#: mpdevil:2613 mpdevil:2615
#: src/mpdevil.py:1221 src/mpdevil.py:1644 src/mpdevil.py:1671
#: src/mpdevil.py:1841 src/mpdevil.py:2463 src/mpdevil.py:2556
#: src/mpdevil.py:2558
msgid "Title"
msgstr "Titel"
#: mpdevil:1211 mpdevil:1848 mpdevil:2508
#: src/mpdevil.py:1221 src/mpdevil.py:1842 src/mpdevil.py:2464
msgid "Artist"
msgstr "Interpret"
#: mpdevil:1211 mpdevil:1849 mpdevil:2509
#: src/mpdevil.py:1221 src/mpdevil.py:1843 src/mpdevil.py:2465
msgid "Album"
msgstr "Album"
#: mpdevil:1211 mpdevil:1650 mpdevil:1850 mpdevil:2510
#: src/mpdevil.py:1221 src/mpdevil.py:1648 src/mpdevil.py:1844
#: src/mpdevil.py:2466
msgid "Length"
msgstr "Länge"
#: mpdevil:1211 mpdevil:2511
#: src/mpdevil.py:1221 src/mpdevil.py:2467
msgid "Year"
msgstr "Jahr"
#: mpdevil:1211 mpdevil:2512
#: src/mpdevil.py:1221 src/mpdevil.py:2468
msgid "Genre"
msgstr "Genre"
#: mpdevil:1295 mpdevil:1297 mpdevil:3543 mpdevil:3647
#: src/mpdevil.py:1305 src/mpdevil.py:1307 src/mpdevil.py:3452
#: src/mpdevil.py:3561
msgid "Preferences"
msgstr "Einstellungen"
#: mpdevil:1311 mpdevil:1322
#: src/mpdevil.py:1321 src/mpdevil.py:1332
msgid "View"
msgstr "Ansicht"
#: mpdevil:1312 mpdevil:1323
#: src/mpdevil.py:1322 src/mpdevil.py:1333
msgid "Behavior"
msgstr "Verhalten"
#: mpdevil:1313 mpdevil:1324 mpdevil:3455
#: src/mpdevil.py:1323 src/mpdevil.py:1334 data/ShortcutsWindow.ui:228
msgid "Playlist"
msgstr "Wiedergabeliste"
#: mpdevil:1314 mpdevil:1325
#: src/mpdevil.py:1324 src/mpdevil.py:1335
msgid "Profiles"
msgstr "Profile"
#: mpdevil:1342
#: src/mpdevil.py:1352
msgid "Stats"
msgstr "Statistik"
#: mpdevil:1351
#: src/mpdevil.py:1361
msgid "<b>Protocol:</b>"
msgstr "<b>Protokoll:</b>"
#: mpdevil:1352
#: src/mpdevil.py:1362
msgid "<b>Uptime:</b>"
msgstr "<b>Uptime:</b>"
#: mpdevil:1353
#: src/mpdevil.py:1363
msgid "<b>Playtime:</b>"
msgstr "<b>Wiedergabezeit:</b>"
#: mpdevil:1354
#: src/mpdevil.py:1364
msgid "<b>Artists:</b>"
msgstr "<b>Künstler:</b>"
#: mpdevil:1355
#: src/mpdevil.py:1365
msgid "<b>Albums:</b>"
msgstr "<b>Alben:</b>"
#: mpdevil:1356
#: src/mpdevil.py:1366
msgid "<b>Songs:</b>"
msgstr "<b>Titel:</b>"
#: mpdevil:1357
#: src/mpdevil.py:1367
msgid "<b>Total Playtime:</b>"
msgstr "<b>Gesamtwiedergabezeit:</b>"
#: mpdevil:1358
#: src/mpdevil.py:1368
msgid "<b>Database Update:</b>"
msgstr "<b>Datenbankaktualisierung:</b>"
#: mpdevil:1382
msgid "A simple music browser for MPD"
msgstr "Ein einfacher Musikbrowser für MPD"
#: mpdevil:1408
#. open-with button
#: src/mpdevil.py:1416
msgid "Open with…"
msgstr "Öffnen mit…"
#: mpdevil:1418 mpdevil:1709
#: src/mpdevil.py:1426 src/mpdevil.py:1703
msgid "Append"
msgstr "Anhängen"
#: mpdevil:1419 mpdevil:1710
#: src/mpdevil.py:1427 src/mpdevil.py:1704
msgid "Play"
msgstr "Abspielen"
#: mpdevil:1420 mpdevil:1711
#: src/mpdevil.py:1428 src/mpdevil.py:1705
msgid "Enqueue"
msgstr "Einreihen"
#: mpdevil:1437
#: src/mpdevil.py:1445
msgid "MPD-Tag"
msgstr "MPD-Tag"
#: mpdevil:1440
#: src/mpdevil.py:1448
msgid "Value"
msgstr "Wert"
#: mpdevil:1581
#: src/mpdevil.py:1579
msgid "_Append"
msgstr "_Anhängen"
#: mpdevil:1581
#: src/mpdevil.py:1579
msgid "Add all titles to playlist"
msgstr "Alle Titel der Wiedergabeliste anhängen"
#: mpdevil:1582
#: src/mpdevil.py:1580
msgid "_Play"
msgstr "Ab_spielen"
#: mpdevil:1582
#: src/mpdevil.py:1580
msgid "Directly play all titles"
msgstr "Alle Titel sofort abspielen"
#: mpdevil:1583
#: src/mpdevil.py:1581
msgid "_Enqueue"
msgstr "_Einreihen"
#: mpdevil:1583
#: src/mpdevil.py:1581
msgid ""
"Append all titles after the currently playing track and clear the playlist "
"from all other songs"
@@ -301,277 +301,292 @@ msgstr ""
"Alle Titel hinter dem aktuellen Stück einreihen und die weitere "
"Wiedergabeliste leeren"
#: mpdevil:1676 mpdevil:2716
#: src/mpdevil.py:1670 src/mpdevil.py:2652
#, python-brace-format
msgid "{number} song ({duration})"
msgid_plural "{number} songs ({duration})"
msgstr[0] "{number} Stück ({duration})"
msgstr[1] "{number} Stücke ({duration})"
#: mpdevil:1779
#: src/mpdevil.py:1773
#, python-brace-format
msgid "{hits} hit"
msgid_plural "{hits} hits"
msgstr[0] "{hits} Treffer"
msgstr[1] "{hits} Treffer"
#: mpdevil:1898
#: src/mpdevil.py:1892
msgid "all tags"
msgstr "Alle Tags"
#: mpdevil:2028
#: src/mpdevil.py:2024
msgid "all genres"
msgstr "Alle Genres"
#: mpdevil:2053
#: src/mpdevil.py:2050
msgid "all artists"
msgstr "Alle Interpreten"
#: mpdevil:2486
#: src/mpdevil.py:2683
msgid "Scroll to current song"
msgstr "Gehe zu aktuellem Lied"
#: mpdevil:2819
#: src/mpdevil.py:2785
msgid "searching…"
msgstr "suche…"
#: mpdevil:2824
#: src/mpdevil.py:2790
msgid "connection error"
msgstr "Verbindungsfehler"
#: mpdevil:2826
#: src/mpdevil.py:2792
msgid "lyrics not found"
msgstr "Liedtext nicht gefunden"
#: mpdevil:2934
#: src/mpdevil.py:2899
msgid "Lyrics"
msgstr "Liedtext"
#: mpdevil:3025 mpdevil:3026
#: src/mpdevil.py:2990 src/mpdevil.py:2991
#, python-brace-format
msgid "{number} song"
msgid_plural "{number} songs"
msgstr[0] "{number} Stück"
msgstr[1] "{number} Stücke"
#: mpdevil:3231
#: src/mpdevil.py:3196
msgid "Repeat mode"
msgstr "Dauerschleife"
#: mpdevil:3232
#: src/mpdevil.py:3197
msgid "Random mode"
msgstr "Zufallsmodus"
#: mpdevil:3233
#: src/mpdevil.py:3198
msgid "Single mode"
msgstr "Einzelstückmodus"
#: mpdevil:3234
#: src/mpdevil.py:3199
msgid "Consume mode"
msgstr "Wiedergabeliste verbrauchen"
#: mpdevil:3451
msgid "General"
msgstr "Allgemein"
#: mpdevil:3452
msgid "Window"
msgstr "Fenster"
#: mpdevil:3453
msgid "Playback"
msgstr "Wiedergabe"
#: mpdevil:3454
msgid "Search, Album Dialog, Album List and Artist List"
msgstr "Suche, Albumdialog, Albumliste und Interpretenliste"
#: mpdevil:3464
msgid "Open online help"
msgstr "Onlinehilfe öffnen"
#: mpdevil:3465
msgid "Open shortcuts window"
msgstr "Tastenkürzelfenster öffnen"
#: mpdevil:3466
msgid "Open menu"
msgstr "Menü öffnen"
#: mpdevil:3467
msgid "Update database"
msgstr "Datenbank aktualisieren"
#: mpdevil:3468
msgid "Quit"
msgstr "Beenden"
#: mpdevil:3469
msgid "Cycle through profiles"
msgstr "Profile durchschalten"
#: mpdevil:3470
msgid "Cycle through profiles in reversed order"
msgstr "Profile rückwärts durchschalten"
#: mpdevil:3471
msgid "Toggle mini player"
msgstr "Miniplayer ein-/ausschalten"
#: mpdevil:3472
msgid "Toggle genre filter"
msgstr "Genrefilter ein-/ausschalten"
#: mpdevil:3473
msgid "Toggle lyrics"
msgstr "Liedtext ein-/ausblenden"
#: mpdevil:3474
msgid "Toggle search"
msgstr "Suche ein-/ausblenden"
#: mpdevil:3475 mpdevil:3635
msgid "Back to current album"
msgstr "Zurück zu aktuellem Album"
#: mpdevil:3476
msgid "Play/Pause"
msgstr "Wiedergabe/Pause"
#: mpdevil:3477
msgid "Stop"
msgstr "Stopp"
#: mpdevil:3478
msgid "Stop after current title"
msgstr "Nach aktuellem Titel stoppen"
#: mpdevil:3479
msgid "Next title"
msgstr "Nächster Titel"
#: mpdevil:3480
msgid "Previous title"
msgstr "Vorheriger Titel"
#: mpdevil:3481
msgid "Seek forward"
msgstr "Vorspulen"
#: mpdevil:3482
msgid "Seek backward"
msgstr "Zurückspulen"
#: mpdevil:3483
msgid "Toggle repeat mode"
msgstr "Dauerschleife ein-/ausschalten"
#: mpdevil:3484
msgid "Toggle random mode"
msgstr "Zufallsmodus ein-/ausschalten"
#: mpdevil:3485
msgid "Toggle single mode"
msgstr "Einzelstückmodus ein-/ausschalten"
#: mpdevil:3486
msgid "Toggle consume mode"
msgstr "Wiedergabeliste verbrauchen ein-/ausschalten"
#: mpdevil:3487
msgid "Enqueue selected item"
msgstr "Ausgewähltes Element einreihen"
#: mpdevil:3488
msgid "Append selected item"
msgstr "Ausgewähltes Element anhängen"
#: mpdevil:3488 mpdevil:3491
msgid "Middle-click"
msgstr "Mittelklick"
#: mpdevil:3489
msgid "Play selected item immediately"
msgstr "Ausgewähltes Element sofort abspielen"
#: mpdevil:3489
msgid "Double-click"
msgstr "Doppelklick"
#: mpdevil:3490 mpdevil:3493
msgid "Show additional information"
msgstr "Zeige weitere Informationen"
#: mpdevil:3490 mpdevil:3493
msgid "Right-click"
msgstr "Rechtsklick"
#: mpdevil:3491
msgid "Remove selected song"
msgstr "Ausgewählten Titel entfernen"
#: mpdevil:3492
msgid "Clear playlist"
msgstr "Wiedergabeliste leeren"
#: mpdevil:3512
#: src/mpdevil.py:3421
msgid "Updating Database…"
msgstr "Datenbank aktualisieren…"
#: mpdevil:3564
#: src/mpdevil.py:3473
#, python-brace-format
msgid "Connection to “{socket}” failed"
msgstr "Verbindung zu „{socket}“ fehlgeschlagen"
#: mpdevil:3566
#: src/mpdevil.py:3475
#, python-brace-format
msgid "Connection to “{host}:{port}” failed"
msgstr "Verbindung zu „{host}:{port}“ fehlgeschlagen"
#: mpdevil:3632
#: src/mpdevil.py:3546
msgid "Search"
msgstr "Suche"
#: mpdevil:3648
#: src/mpdevil.py:3549 data/ShortcutsWindow.ui:99
msgid "Back to current album"
msgstr "Zurück zu aktuellem Album"
#: src/mpdevil.py:3562
msgid "Keyboard Shortcuts"
msgstr "Tastenkürzel"
#: mpdevil:3649
#: src/mpdevil.py:3563
msgid "Help"
msgstr "Hilfe"
#: mpdevil:3650
#: src/mpdevil.py:3564
msgid "About mpdevil"
msgstr "Info zu mpdevil"
#: mpdevil:3652
#: src/mpdevil.py:3566
msgid "Update Database"
msgstr "Datenbank aktualisieren"
#: mpdevil:3653
#: src/mpdevil.py:3567
msgid "Server Stats"
msgstr "Serverstatistik"
#: mpdevil:3660
#: src/mpdevil.py:3574
msgid "Mini Player"
msgstr "Miniplayer"
#: mpdevil:3661
#: src/mpdevil.py:3575
msgid "Genre Filter"
msgstr "Genrefilter"
#: mpdevil:3671
#: src/mpdevil.py:3585
msgid "Menu"
msgstr "Menü"
#: mpdevil:3724 mpdevil:3726
#: src/mpdevil.py:3638 src/mpdevil.py:3640
msgid "connecting…"
msgstr "verbinden…"
#: mpdevil:3885
#: src/mpdevil.py:3797
msgid "Debug mode"
msgstr "Debugmodus"
#: data/org.mpdevil.mpdevil.desktop.in:3
msgid "mpdevil"
msgstr "mpdevil"
#: data/org.mpdevil.mpdevil.desktop.in:4
msgid "MPD Client"
msgstr "MPD Client"
#: data/org.mpdevil.mpdevil.desktop.in:5 data/AboutDialog.ui:7
msgid "A simple music browser for MPD"
msgstr "Ein einfacher Musikbrowser für MPD"
#: data/ShortcutsWindow.ui:12
msgid "General"
msgstr "Allgemein"
#: data/ShortcutsWindow.ui:16
msgid "Open online help"
msgstr "Onlinehilfe öffnen"
#: data/ShortcutsWindow.ui:23
msgid "Open shortcuts window"
msgstr "Tastenkürzelfenster öffnen"
#: data/ShortcutsWindow.ui:30
msgid "Open menu"
msgstr "Menü öffnen"
#: data/ShortcutsWindow.ui:37
msgid "Update database"
msgstr "Datenbank aktualisieren"
#: data/ShortcutsWindow.ui:44
msgid "Quit"
msgstr "Beenden"
#: data/ShortcutsWindow.ui:53
msgid "Window"
msgstr "Fenster"
#: data/ShortcutsWindow.ui:57
msgid "Cycle through profiles"
msgstr "Profile durchschalten"
#: data/ShortcutsWindow.ui:64
msgid "Cycle through profiles in reversed order"
msgstr "Profile rückwärts durchschalten"
#: data/ShortcutsWindow.ui:71
msgid "Toggle mini player"
msgstr "Miniplayer ein-/ausschalten"
#: data/ShortcutsWindow.ui:78
msgid "Toggle genre filter"
msgstr "Genrefilter ein-/ausschalten"
#: data/ShortcutsWindow.ui:85
msgid "Toggle lyrics"
msgstr "Liedtext ein-/ausblenden"
#: data/ShortcutsWindow.ui:92
msgid "Toggle search"
msgstr "Suche ein-/ausblenden"
#: data/ShortcutsWindow.ui:108
msgid "Playback"
msgstr "Wiedergabe"
#: data/ShortcutsWindow.ui:112
msgid "Play/Pause"
msgstr "Wiedergabe/Pause"
#: data/ShortcutsWindow.ui:119
msgid "Stop"
msgstr "Stopp"
#: data/ShortcutsWindow.ui:126
msgid "Stop after current title"
msgstr "Nach aktuellem Titel stoppen"
#: data/ShortcutsWindow.ui:133
msgid "Next title"
msgstr "Nächster Titel"
#: data/ShortcutsWindow.ui:140
msgid "Previous title"
msgstr "Vorheriger Titel"
#: data/ShortcutsWindow.ui:147
msgid "Seek forward"
msgstr "Vorspulen"
#: data/ShortcutsWindow.ui:154
msgid "Seek backward"
msgstr "Zurückspulen"
#: data/ShortcutsWindow.ui:161
msgid "Toggle repeat mode"
msgstr "Dauerschleife ein-/ausschalten"
#: data/ShortcutsWindow.ui:168
msgid "Toggle random mode"
msgstr "Zufallsmodus ein-/ausschalten"
#: data/ShortcutsWindow.ui:175
msgid "Toggle single mode"
msgstr "Einzelstückmodus ein-/ausschalten"
#: data/ShortcutsWindow.ui:182
msgid "Toggle consume mode"
msgstr "Wiedergabeliste verbrauchen ein-/ausschalten"
#: data/ShortcutsWindow.ui:191
msgid "Search, Album Dialog, Album List and Artist List"
msgstr "Suche, Albumdialog, Albumliste und Interpretenliste"
#: data/ShortcutsWindow.ui:195
msgid "Enqueue selected item"
msgstr "Ausgewähltes Element einreihen"
#: data/ShortcutsWindow.ui:202
msgid "Append selected item"
msgstr "Ausgewähltes Element anhängen"
#: data/ShortcutsWindow.ui:203 data/ShortcutsWindow.ui:233
msgid "Middle-click"
msgstr "Mittelklick"
#: data/ShortcutsWindow.ui:210
msgid "Play selected item immediately"
msgstr "Ausgewähltes Element sofort abspielen"
#: data/ShortcutsWindow.ui:211
msgid "Double-click"
msgstr "Doppelklick"
#: data/ShortcutsWindow.ui:218 data/ShortcutsWindow.ui:247
msgid "Show additional information"
msgstr "Zeige weitere Informationen"
#: data/ShortcutsWindow.ui:219 data/ShortcutsWindow.ui:248
msgid "Right-click"
msgstr "Rechtsklick"
#: data/ShortcutsWindow.ui:232
msgid "Remove selected song"
msgstr "Ausgewählten Titel entfernen"
#: data/ShortcutsWindow.ui:240
msgid "Clear playlist"
msgstr "Wiedergabeliste leeren"
#~ msgid "Use “Album Artist” tag"
#~ msgstr "„Album Artist“ Tag benutzen"
#~ msgid "Show lyrics"
#~ msgstr "Zeige Liedtext"

1
po/meson.build Normal file
View File

@@ -0,0 +1 @@
i18n.gettext('mpdevil', preset: 'glib')

View File

@@ -1,14 +1,14 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# This file is distributed under the same license as the mpdevil package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Project-Id-Version: mpdevil\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-10-23 12:59+0200\n"
"POT-Creation-Date: 2021-12-30 01:19+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -18,549 +18,561 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
#: mpdevil:492
#: src/mpdevil.py:490
#, python-brace-format
msgid "{days} day"
msgid_plural "{days} days"
msgstr[0] ""
msgstr[1] ""
#: mpdevil:529
#: src/mpdevil.py:527
#, python-brace-format
msgid "{channels} channel"
msgid_plural "{channels} channels"
msgstr[0] ""
msgstr[1] ""
#: mpdevil:994
#: src/mpdevil.py:1005
msgid "(restart required)"
msgstr ""
#: mpdevil:1040
#: src/mpdevil.py:1051
msgid "Use Client-side decoration"
msgstr ""
#: mpdevil:1041
#: src/mpdevil.py:1052
msgid "Show stop button"
msgstr ""
#: mpdevil:1042
#: src/mpdevil.py:1053
msgid "Show audio format"
msgstr ""
#: mpdevil:1043
#: src/mpdevil.py:1054
msgid "Show lyrics button"
msgstr ""
#: mpdevil:1044
#: src/mpdevil.py:1055
msgid "Place playlist at the side"
msgstr ""
#: mpdevil:1050
#: src/mpdevil.py:1061
msgid "Main cover size"
msgstr ""
#: mpdevil:1051
#: src/mpdevil.py:1062
msgid "Album view cover size"
msgstr ""
#: mpdevil:1052
#: src/mpdevil.py:1063
msgid "Action bar icon size"
msgstr ""
#: mpdevil:1062
#: src/mpdevil.py:1073
msgid "Support “MPRIS”"
msgstr ""
#: mpdevil:1063
msgid "Use “Album Artist” tag"
msgstr ""
#: mpdevil:1064
#: src/mpdevil.py:1074
msgid "Sort albums by year"
msgstr ""
#: mpdevil:1065
#: src/mpdevil.py:1075
msgid "Send notification on title change"
msgstr ""
#: mpdevil:1066
#: src/mpdevil.py:1076
msgid "Play selected albums and titles immediately"
msgstr ""
#: mpdevil:1067
#: src/mpdevil.py:1077
msgid "Rewind via previous button"
msgstr ""
#: mpdevil:1068
#: src/mpdevil.py:1078
msgid "Stop playback on quit"
msgstr ""
#: mpdevil:1095
#: src/mpdevil.py:1105
msgid "Choose directory"
msgstr ""
#: mpdevil:1108
#: src/mpdevil.py:1118
msgid "Connect via Unix domain socket"
msgstr ""
#: mpdevil:1127
#: src/mpdevil.py:1137
msgid ""
"The first image in the same directory as the song file matching this regex "
"will be displayed. %AlbumArtist% and %Album% will be replaced by the "
"corresponding tags of the song."
msgstr ""
#: mpdevil:1132
#: src/mpdevil.py:1142
msgid "Socket:"
msgstr ""
#: mpdevil:1134
#: src/mpdevil.py:1144
msgid "Host:"
msgstr ""
#: mpdevil:1136
#: src/mpdevil.py:1146
msgid "Password:"
msgstr ""
#: mpdevil:1137
#: src/mpdevil.py:1147
msgid "Music lib:"
msgstr ""
#: mpdevil:1139
#: src/mpdevil.py:1149
msgid "Cover regex:"
msgstr ""
#: mpdevil:1163 mpdevil:3655
#: src/mpdevil.py:1173 src/mpdevil.py:3569
msgid "Profile 1"
msgstr ""
#: mpdevil:1164 mpdevil:3655
#: src/mpdevil.py:1174 src/mpdevil.py:3569
msgid "Profile 2"
msgstr ""
#: mpdevil:1165 mpdevil:3655
#: src/mpdevil.py:1175 src/mpdevil.py:3569
msgid "Profile 3"
msgstr ""
#: mpdevil:1169 mpdevil:3542
#. connect button
#: src/mpdevil.py:1179 src/mpdevil.py:3451
msgid "Connect"
msgstr ""
#: mpdevil:1194
#. label
#: src/mpdevil.py:1204
msgid "Choose the order of information to appear in the playlist:"
msgstr ""
#: mpdevil:1211 mpdevil:1643 mpdevil:1846 mpdevil:2505
#. fill store
#: src/mpdevil.py:1221 src/mpdevil.py:1641 src/mpdevil.py:1840
#: src/mpdevil.py:2461
msgid "No"
msgstr ""
#: mpdevil:1211 mpdevil:2506
#: src/mpdevil.py:1221 src/mpdevil.py:2462
msgid "Disc"
msgstr ""
#: mpdevil:1211 mpdevil:1646 mpdevil:1677 mpdevil:1847 mpdevil:2507
#: mpdevil:2613 mpdevil:2615
#: src/mpdevil.py:1221 src/mpdevil.py:1644 src/mpdevil.py:1671
#: src/mpdevil.py:1841 src/mpdevil.py:2463 src/mpdevil.py:2556
#: src/mpdevil.py:2558
msgid "Title"
msgstr ""
#: mpdevil:1211 mpdevil:1848 mpdevil:2508
#: src/mpdevil.py:1221 src/mpdevil.py:1842 src/mpdevil.py:2464
msgid "Artist"
msgstr ""
#: mpdevil:1211 mpdevil:1849 mpdevil:2509
#: src/mpdevil.py:1221 src/mpdevil.py:1843 src/mpdevil.py:2465
msgid "Album"
msgstr ""
#: mpdevil:1211 mpdevil:1650 mpdevil:1850 mpdevil:2510
#: src/mpdevil.py:1221 src/mpdevil.py:1648 src/mpdevil.py:1844
#: src/mpdevil.py:2466
msgid "Length"
msgstr ""
#: mpdevil:1211 mpdevil:2511
#: src/mpdevil.py:1221 src/mpdevil.py:2467
msgid "Year"
msgstr ""
#: mpdevil:1211 mpdevil:2512
#: src/mpdevil.py:1221 src/mpdevil.py:2468
msgid "Genre"
msgstr ""
#: mpdevil:1295 mpdevil:1297 mpdevil:3543 mpdevil:3647
#: src/mpdevil.py:1305 src/mpdevil.py:1307 src/mpdevil.py:3452
#: src/mpdevil.py:3561
msgid "Preferences"
msgstr ""
#: mpdevil:1311 mpdevil:1322
#: src/mpdevil.py:1321 src/mpdevil.py:1332
msgid "View"
msgstr ""
#: mpdevil:1312 mpdevil:1323
#: src/mpdevil.py:1322 src/mpdevil.py:1333
msgid "Behavior"
msgstr ""
#: mpdevil:1313 mpdevil:1324 mpdevil:3455
#: src/mpdevil.py:1323 src/mpdevil.py:1334 data/ShortcutsWindow.ui:228
msgid "Playlist"
msgstr ""
#: mpdevil:1314 mpdevil:1325
#: src/mpdevil.py:1324 src/mpdevil.py:1335
msgid "Profiles"
msgstr ""
#: mpdevil:1342
#: src/mpdevil.py:1352
msgid "Stats"
msgstr ""
#: mpdevil:1351
#: src/mpdevil.py:1361
msgid "<b>Protocol:</b>"
msgstr ""
#: mpdevil:1352
#: src/mpdevil.py:1362
msgid "<b>Uptime:</b>"
msgstr ""
#: mpdevil:1353
#: src/mpdevil.py:1363
msgid "<b>Playtime:</b>"
msgstr ""
#: mpdevil:1354
#: src/mpdevil.py:1364
msgid "<b>Artists:</b>"
msgstr ""
#: mpdevil:1355
#: src/mpdevil.py:1365
msgid "<b>Albums:</b>"
msgstr ""
#: mpdevil:1356
#: src/mpdevil.py:1366
msgid "<b>Songs:</b>"
msgstr ""
#: mpdevil:1357
#: src/mpdevil.py:1367
msgid "<b>Total Playtime:</b>"
msgstr ""
#: mpdevil:1358
#: src/mpdevil.py:1368
msgid "<b>Database Update:</b>"
msgstr ""
#: mpdevil:1382
msgid "A simple music browser for MPD"
msgstr ""
#: mpdevil:1408
#. open-with button
#: src/mpdevil.py:1416
msgid "Open with…"
msgstr ""
#: mpdevil:1418 mpdevil:1709
#: src/mpdevil.py:1426 src/mpdevil.py:1703
msgid "Append"
msgstr ""
#: mpdevil:1419 mpdevil:1710
#: src/mpdevil.py:1427 src/mpdevil.py:1704
msgid "Play"
msgstr ""
#: mpdevil:1420 mpdevil:1711
#: src/mpdevil.py:1428 src/mpdevil.py:1705
msgid "Enqueue"
msgstr ""
#: mpdevil:1437
#: src/mpdevil.py:1445
msgid "MPD-Tag"
msgstr ""
#: mpdevil:1440
#: src/mpdevil.py:1448
msgid "Value"
msgstr ""
#: mpdevil:1581
#: src/mpdevil.py:1579
msgid "_Append"
msgstr ""
#: mpdevil:1581
#: src/mpdevil.py:1579
msgid "Add all titles to playlist"
msgstr ""
#: mpdevil:1582
#: src/mpdevil.py:1580
msgid "_Play"
msgstr ""
#: mpdevil:1582
#: src/mpdevil.py:1580
msgid "Directly play all titles"
msgstr ""
#: mpdevil:1583
#: src/mpdevil.py:1581
msgid "_Enqueue"
msgstr ""
#: mpdevil:1583
#: src/mpdevil.py:1581
msgid ""
"Append all titles after the currently playing track and clear the playlist "
"from all other songs"
msgstr ""
#: mpdevil:1676 mpdevil:2716
#: src/mpdevil.py:1670 src/mpdevil.py:2652
#, python-brace-format
msgid "{number} song ({duration})"
msgid_plural "{number} songs ({duration})"
msgstr[0] ""
msgstr[1] ""
#: mpdevil:1779
#: src/mpdevil.py:1773
#, python-brace-format
msgid "{hits} hit"
msgid_plural "{hits} hits"
msgstr[0] ""
msgstr[1] ""
#: mpdevil:1898
#: src/mpdevil.py:1892
msgid "all tags"
msgstr ""
#: mpdevil:2028
#: src/mpdevil.py:2024
msgid "all genres"
msgstr ""
#: mpdevil:2053
#: src/mpdevil.py:2050
msgid "all artists"
msgstr ""
#: mpdevil:2486
#: src/mpdevil.py:2683
msgid "Scroll to current song"
msgstr ""
#: mpdevil:2819
#: src/mpdevil.py:2785
msgid "searching…"
msgstr ""
#: mpdevil:2824
#: src/mpdevil.py:2790
msgid "connection error"
msgstr ""
#: mpdevil:2826
#: src/mpdevil.py:2792
msgid "lyrics not found"
msgstr ""
#: mpdevil:2934
#: src/mpdevil.py:2899
msgid "Lyrics"
msgstr ""
#: mpdevil:3025 mpdevil:3026
#: src/mpdevil.py:2990 src/mpdevil.py:2991
#, python-brace-format
msgid "{number} song"
msgid_plural "{number} songs"
msgstr[0] ""
msgstr[1] ""
#: mpdevil:3231
#: src/mpdevil.py:3196
msgid "Repeat mode"
msgstr ""
#: mpdevil:3232
#: src/mpdevil.py:3197
msgid "Random mode"
msgstr ""
#: mpdevil:3233
#: src/mpdevil.py:3198
msgid "Single mode"
msgstr ""
#: mpdevil:3234
#: src/mpdevil.py:3199
msgid "Consume mode"
msgstr ""
#: mpdevil:3451
msgid "General"
msgstr ""
#: mpdevil:3452
msgid "Window"
msgstr ""
#: mpdevil:3453
msgid "Playback"
msgstr ""
#: mpdevil:3454
msgid "Search, Album Dialog, Album List and Artist List"
msgstr ""
#: mpdevil:3464
msgid "Open online help"
msgstr ""
#: mpdevil:3465
msgid "Open shortcuts window"
msgstr ""
#: mpdevil:3466
msgid "Open menu"
msgstr ""
#: mpdevil:3467
msgid "Update database"
msgstr ""
#: mpdevil:3468
msgid "Quit"
msgstr ""
#: mpdevil:3469
msgid "Cycle through profiles"
msgstr ""
#: mpdevil:3470
msgid "Cycle through profiles in reversed order"
msgstr ""
#: mpdevil:3471
msgid "Toggle mini player"
msgstr ""
#: mpdevil:3472
msgid "Toggle genre filter"
msgstr ""
#: mpdevil:3473
msgid "Toggle lyrics"
msgstr ""
#: mpdevil:3474
msgid "Toggle search"
msgstr ""
#: mpdevil:3475 mpdevil:3635
msgid "Back to current album"
msgstr ""
#: mpdevil:3476
msgid "Play/Pause"
msgstr ""
#: mpdevil:3477
msgid "Stop"
msgstr ""
#: mpdevil:3478
msgid "Stop after current title"
msgstr ""
#: mpdevil:3479
msgid "Next title"
msgstr ""
#: mpdevil:3480
msgid "Previous title"
msgstr ""
#: mpdevil:3481
msgid "Seek forward"
msgstr ""
#: mpdevil:3482
msgid "Seek backward"
msgstr ""
#: mpdevil:3483
msgid "Toggle repeat mode"
msgstr ""
#: mpdevil:3484
msgid "Toggle random mode"
msgstr ""
#: mpdevil:3485
msgid "Toggle single mode"
msgstr ""
#: mpdevil:3486
msgid "Toggle consume mode"
msgstr ""
#: mpdevil:3487
msgid "Enqueue selected item"
msgstr ""
#: mpdevil:3488
msgid "Append selected item"
msgstr ""
#: mpdevil:3488 mpdevil:3491
msgid "Middle-click"
msgstr ""
#: mpdevil:3489
msgid "Play selected item immediately"
msgstr ""
#: mpdevil:3489
msgid "Double-click"
msgstr ""
#: mpdevil:3490 mpdevil:3493
msgid "Show additional information"
msgstr ""
#: mpdevil:3490 mpdevil:3493
msgid "Right-click"
msgstr ""
#: mpdevil:3491
msgid "Remove selected song"
msgstr ""
#: mpdevil:3492
msgid "Clear playlist"
msgstr ""
#: mpdevil:3512
#: src/mpdevil.py:3421
msgid "Updating Database…"
msgstr ""
#: mpdevil:3564
#: src/mpdevil.py:3473
#, python-brace-format
msgid "Connection to “{socket}” failed"
msgstr ""
#: mpdevil:3566
#: src/mpdevil.py:3475
#, python-brace-format
msgid "Connection to “{host}:{port}” failed"
msgstr ""
#: mpdevil:3632
#: src/mpdevil.py:3546
msgid "Search"
msgstr ""
#: mpdevil:3648
#: src/mpdevil.py:3549 data/ShortcutsWindow.ui:99
msgid "Back to current album"
msgstr ""
#: src/mpdevil.py:3562
msgid "Keyboard Shortcuts"
msgstr ""
#: mpdevil:3649
#: src/mpdevil.py:3563
msgid "Help"
msgstr ""
#: mpdevil:3650
#: src/mpdevil.py:3564
msgid "About mpdevil"
msgstr ""
#: mpdevil:3652
#: src/mpdevil.py:3566
msgid "Update Database"
msgstr ""
#: mpdevil:3653
#: src/mpdevil.py:3567
msgid "Server Stats"
msgstr ""
#: mpdevil:3660
#: src/mpdevil.py:3574
msgid "Mini Player"
msgstr ""
#: mpdevil:3661
#: src/mpdevil.py:3575
msgid "Genre Filter"
msgstr ""
#: mpdevil:3671
#: src/mpdevil.py:3585
msgid "Menu"
msgstr ""
#: mpdevil:3724 mpdevil:3726
#: src/mpdevil.py:3638 src/mpdevil.py:3640
msgid "connecting…"
msgstr ""
#: mpdevil:3885
#: src/mpdevil.py:3797
msgid "Debug mode"
msgstr ""
#: data/org.mpdevil.mpdevil.desktop.in:3
msgid "mpdevil"
msgstr ""
#: data/org.mpdevil.mpdevil.desktop.in:4
msgid "MPD Client"
msgstr ""
#: data/org.mpdevil.mpdevil.desktop.in:5 data/AboutDialog.ui:7
msgid "A simple music browser for MPD"
msgstr ""
#: data/ShortcutsWindow.ui:12
msgid "General"
msgstr ""
#: data/ShortcutsWindow.ui:16
msgid "Open online help"
msgstr ""
#: data/ShortcutsWindow.ui:23
msgid "Open shortcuts window"
msgstr ""
#: data/ShortcutsWindow.ui:30
msgid "Open menu"
msgstr ""
#: data/ShortcutsWindow.ui:37
msgid "Update database"
msgstr ""
#: data/ShortcutsWindow.ui:44
msgid "Quit"
msgstr ""
#: data/ShortcutsWindow.ui:53
msgid "Window"
msgstr ""
#: data/ShortcutsWindow.ui:57
msgid "Cycle through profiles"
msgstr ""
#: data/ShortcutsWindow.ui:64
msgid "Cycle through profiles in reversed order"
msgstr ""
#: data/ShortcutsWindow.ui:71
msgid "Toggle mini player"
msgstr ""
#: data/ShortcutsWindow.ui:78
msgid "Toggle genre filter"
msgstr ""
#: data/ShortcutsWindow.ui:85
msgid "Toggle lyrics"
msgstr ""
#: data/ShortcutsWindow.ui:92
msgid "Toggle search"
msgstr ""
#: data/ShortcutsWindow.ui:108
msgid "Playback"
msgstr ""
#: data/ShortcutsWindow.ui:112
msgid "Play/Pause"
msgstr ""
#: data/ShortcutsWindow.ui:119
msgid "Stop"
msgstr ""
#: data/ShortcutsWindow.ui:126
msgid "Stop after current title"
msgstr ""
#: data/ShortcutsWindow.ui:133
msgid "Next title"
msgstr ""
#: data/ShortcutsWindow.ui:140
msgid "Previous title"
msgstr ""
#: data/ShortcutsWindow.ui:147
msgid "Seek forward"
msgstr ""
#: data/ShortcutsWindow.ui:154
msgid "Seek backward"
msgstr ""
#: data/ShortcutsWindow.ui:161
msgid "Toggle repeat mode"
msgstr ""
#: data/ShortcutsWindow.ui:168
msgid "Toggle random mode"
msgstr ""
#: data/ShortcutsWindow.ui:175
msgid "Toggle single mode"
msgstr ""
#: data/ShortcutsWindow.ui:182
msgid "Toggle consume mode"
msgstr ""
#: data/ShortcutsWindow.ui:191
msgid "Search, Album Dialog, Album List and Artist List"
msgstr ""
#: data/ShortcutsWindow.ui:195
msgid "Enqueue selected item"
msgstr ""
#: data/ShortcutsWindow.ui:202
msgid "Append selected item"
msgstr ""
#: data/ShortcutsWindow.ui:203 data/ShortcutsWindow.ui:233
msgid "Middle-click"
msgstr ""
#: data/ShortcutsWindow.ui:210
msgid "Play selected item immediately"
msgstr ""
#: data/ShortcutsWindow.ui:211
msgid "Double-click"
msgstr ""
#: data/ShortcutsWindow.ui:218 data/ShortcutsWindow.ui:247
msgid "Show additional information"
msgstr ""
#: data/ShortcutsWindow.ui:219 data/ShortcutsWindow.ui:248
msgid "Right-click"
msgstr ""
#: data/ShortcutsWindow.ui:232
msgid "Remove selected song"
msgstr ""
#: data/ShortcutsWindow.ui:240
msgid "Clear playlist"
msgstr ""

511
po/nl.po
View File

@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-10-23 12:59+0200\n"
"PO-Revision-Date: 2021-10-24 08:52+0200\n"
"POT-Creation-Date: 2021-12-30 01:19+0100\n"
"PO-Revision-Date: 2021-12-30 17:16+0100\n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: nl\n"
@@ -18,93 +18,89 @@ msgstr ""
"X-Generator: Poedit 2.3.1\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: mpdevil:492
#: src/mpdevil.py:490
#, python-brace-format
msgid "{days} day"
msgid_plural "{days} days"
msgstr[0] "{days} dag"
msgstr[1] "{days} dagen"
#: mpdevil:529
#: src/mpdevil.py:527
#, python-brace-format
msgid "{channels} channel"
msgid_plural "{channels} channels"
msgstr[0] "{channels} kanaal"
msgstr[1] "{channels} kanalen"
#: mpdevil:994
#: src/mpdevil.py:1005
msgid "(restart required)"
msgstr "(herstart vereist)"
#: mpdevil:1040
#: src/mpdevil.py:1051
msgid "Use Client-side decoration"
msgstr "Gebruik vensterdecoratie van mpdevil"
#: mpdevil:1041
#: src/mpdevil.py:1052
msgid "Show stop button"
msgstr "Toon stopknop"
#: mpdevil:1042
#: src/mpdevil.py:1053
msgid "Show audio format"
msgstr "Toon audioformaat"
#: mpdevil:1043
#: src/mpdevil.py:1054
msgid "Show lyrics button"
msgstr "Toon songtekstknop"
#: mpdevil:1044
#: src/mpdevil.py:1055
msgid "Place playlist at the side"
msgstr "Plaats afspeellijst aan de zijkant"
#: mpdevil:1050
#: src/mpdevil.py:1061
msgid "Main cover size"
msgstr "Grootte albumhoes"
#: mpdevil:1051
#: src/mpdevil.py:1062
msgid "Album view cover size"
msgstr "Hoesgrootte in albumlijst"
#: mpdevil:1052
#: src/mpdevil.py:1063
msgid "Action bar icon size"
msgstr "Grootte iconen werkbalk"
#: mpdevil:1062
#: src/mpdevil.py:1073
msgid "Support “MPRIS”"
msgstr "Ondersteun „MPRIS”"
#: mpdevil:1063
msgid "Use “Album Artist” tag"
msgstr "Gebruik tag „Album Artist”"
#: mpdevil:1064
#: src/mpdevil.py:1074
msgid "Sort albums by year"
msgstr "Sorteer albums op jaar"
#: mpdevil:1065
#: src/mpdevil.py:1075
msgid "Send notification on title change"
msgstr "Verstuur een melding bij titelwisseling"
#: mpdevil:1066
#: src/mpdevil.py:1076
msgid "Play selected albums and titles immediately"
msgstr "Geselecteerde albums en titels direct afspelen"
#: mpdevil:1067
#: src/mpdevil.py:1077
msgid "Rewind via previous button"
msgstr "Terugspoelen met „vorige” knop"
#: mpdevil:1068
#: src/mpdevil.py:1078
msgid "Stop playback on quit"
msgstr "Stop afspelen bij afsluiten"
#: mpdevil:1095
#: src/mpdevil.py:1105
msgid "Choose directory"
msgstr "Kies een map"
#: mpdevil:1108
#: src/mpdevil.py:1118
msgid "Connect via Unix domain socket"
msgstr "Verbinden via Unix domain socket"
#: mpdevil:1127
#: src/mpdevil.py:1137
msgid ""
"The first image in the same directory as the song file matching this regex "
"will be displayed. %AlbumArtist% and %Album% will be replaced by the "
@@ -114,184 +110,188 @@ msgstr ""
"met deze regex wordt getoond. %AlbumArtist% en %Album% worden vervangen door "
"de bijbehorende tags van het muziekbestand."
#: mpdevil:1132
#: src/mpdevil.py:1142
msgid "Socket:"
msgstr "Socket:"
#: mpdevil:1134
#: src/mpdevil.py:1144
msgid "Host:"
msgstr "Host:"
#: mpdevil:1136
#: src/mpdevil.py:1146
msgid "Password:"
msgstr "Wachtwoord:"
#: mpdevil:1137
#: src/mpdevil.py:1147
msgid "Music lib:"
msgstr "Muziekmap:"
#: mpdevil:1139
#: src/mpdevil.py:1149
msgid "Cover regex:"
msgstr "Regex albumhoes:"
#: mpdevil:1163 mpdevil:3655
#: src/mpdevil.py:1173 src/mpdevil.py:3569
msgid "Profile 1"
msgstr "Profiel 1"
#: mpdevil:1164 mpdevil:3655
#: src/mpdevil.py:1174 src/mpdevil.py:3569
msgid "Profile 2"
msgstr "Profiel 2"
#: mpdevil:1165 mpdevil:3655
#: src/mpdevil.py:1175 src/mpdevil.py:3569
msgid "Profile 3"
msgstr "Profiel 3"
#: mpdevil:1169 mpdevil:3542
#. connect button
#: src/mpdevil.py:1179 src/mpdevil.py:3451
msgid "Connect"
msgstr "Verbinden"
#: mpdevil:1194
#. label
#: src/mpdevil.py:1204
msgid "Choose the order of information to appear in the playlist:"
msgstr "Kies de volgorde van de informatie getoond in de afspeellijst:"
#: mpdevil:1211 mpdevil:1643 mpdevil:1846 mpdevil:2505
#. fill store
#: src/mpdevil.py:1221 src/mpdevil.py:1641 src/mpdevil.py:1840
#: src/mpdevil.py:2461
msgid "No"
msgstr "Nr"
#: mpdevil:1211 mpdevil:2506
#: src/mpdevil.py:1221 src/mpdevil.py:2462
msgid "Disc"
msgstr "Disc"
#: mpdevil:1211 mpdevil:1646 mpdevil:1677 mpdevil:1847 mpdevil:2507
#: mpdevil:2613 mpdevil:2615
#: src/mpdevil.py:1221 src/mpdevil.py:1644 src/mpdevil.py:1671
#: src/mpdevil.py:1841 src/mpdevil.py:2463 src/mpdevil.py:2556
#: src/mpdevil.py:2558
msgid "Title"
msgstr "Titel"
#: mpdevil:1211 mpdevil:1848 mpdevil:2508
#: src/mpdevil.py:1221 src/mpdevil.py:1842 src/mpdevil.py:2464
msgid "Artist"
msgstr "Artiest"
#: mpdevil:1211 mpdevil:1849 mpdevil:2509
#: src/mpdevil.py:1221 src/mpdevil.py:1843 src/mpdevil.py:2465
msgid "Album"
msgstr "Album"
#: mpdevil:1211 mpdevil:1650 mpdevil:1850 mpdevil:2510
#: src/mpdevil.py:1221 src/mpdevil.py:1648 src/mpdevil.py:1844
#: src/mpdevil.py:2466
msgid "Length"
msgstr "Lengte"
#: mpdevil:1211 mpdevil:2511
#: src/mpdevil.py:1221 src/mpdevil.py:2467
msgid "Year"
msgstr "Jaar"
#: mpdevil:1211 mpdevil:2512
#: src/mpdevil.py:1221 src/mpdevil.py:2468
msgid "Genre"
msgstr "Genre"
#: mpdevil:1295 mpdevil:1297 mpdevil:3543 mpdevil:3647
#: src/mpdevil.py:1305 src/mpdevil.py:1307 src/mpdevil.py:3452
#: src/mpdevil.py:3561
msgid "Preferences"
msgstr "Voorkeuren"
#: mpdevil:1311 mpdevil:1322
#: src/mpdevil.py:1321 src/mpdevil.py:1332
msgid "View"
msgstr "Beeld"
#: mpdevil:1312 mpdevil:1323
#: src/mpdevil.py:1322 src/mpdevil.py:1333
msgid "Behavior"
msgstr "Gedrag"
#: mpdevil:1313 mpdevil:1324 mpdevil:3455
#: src/mpdevil.py:1323 src/mpdevil.py:1334 data/ShortcutsWindow.ui:228
msgid "Playlist"
msgstr "Afspeellijst"
#: mpdevil:1314 mpdevil:1325
#: src/mpdevil.py:1324 src/mpdevil.py:1335
msgid "Profiles"
msgstr "Profielen"
#: mpdevil:1342
#: src/mpdevil.py:1352
msgid "Stats"
msgstr "Statistieken"
#: mpdevil:1351
#: src/mpdevil.py:1361
msgid "<b>Protocol:</b>"
msgstr "<b>Protocol:</b>"
#: mpdevil:1352
#: src/mpdevil.py:1362
msgid "<b>Uptime:</b>"
msgstr "<b>Uptime:</b>"
#: mpdevil:1353
#: src/mpdevil.py:1363
msgid "<b>Playtime:</b>"
msgstr "<b>Afspeeltijd:</b>"
#: mpdevil:1354
#: src/mpdevil.py:1364
msgid "<b>Artists:</b>"
msgstr "<b>Artiesten:</b>"
#: mpdevil:1355
#: src/mpdevil.py:1365
msgid "<b>Albums:</b>"
msgstr "<b>Albums:</b>"
#: mpdevil:1356
#: src/mpdevil.py:1366
msgid "<b>Songs:</b>"
msgstr "<b>Titels:</b>"
#: mpdevil:1357
#: src/mpdevil.py:1367
msgid "<b>Total Playtime:</b>"
msgstr "<b>Totale speelduur:</b>"
#: mpdevil:1358
#: src/mpdevil.py:1368
msgid "<b>Database Update:</b>"
msgstr "<b>Database bijgewerkt:</b>"
#: mpdevil:1382
msgid "A simple music browser for MPD"
msgstr "Een simpele muziekspeler voor MPD"
#: mpdevil:1408
#. open-with button
#: src/mpdevil.py:1416
msgid "Open with…"
msgstr "Openen met…"
#: mpdevil:1418 mpdevil:1709
#: src/mpdevil.py:1426 src/mpdevil.py:1703
msgid "Append"
msgstr "Toevoegen"
#: mpdevil:1419 mpdevil:1710
#: src/mpdevil.py:1427 src/mpdevil.py:1704
msgid "Play"
msgstr "Afspelen"
#: mpdevil:1420 mpdevil:1711
#: src/mpdevil.py:1428 src/mpdevil.py:1705
msgid "Enqueue"
msgstr "In wachtrij plaatsen"
#: mpdevil:1437
#: src/mpdevil.py:1445
msgid "MPD-Tag"
msgstr "MPD-Tag"
#: mpdevil:1440
#: src/mpdevil.py:1448
msgid "Value"
msgstr "Waarde"
#: mpdevil:1581
#: src/mpdevil.py:1579
msgid "_Append"
msgstr "_Toevoegen"
#: mpdevil:1581
#: src/mpdevil.py:1579
msgid "Add all titles to playlist"
msgstr "Voeg alle titels toe aan de afspeellijst"
#: mpdevil:1582
#: src/mpdevil.py:1580
msgid "_Play"
msgstr "_Afspelen"
#: mpdevil:1582
#: src/mpdevil.py:1580
msgid "Directly play all titles"
msgstr "Alle titels direct afspelen"
#: mpdevil:1583
#: src/mpdevil.py:1581
msgid "_Enqueue"
msgstr "_In wachtrij plaatsen"
#: mpdevil:1583
#: src/mpdevil.py:1581
msgid ""
"Append all titles after the currently playing track and clear the playlist "
"from all other songs"
@@ -299,277 +299,292 @@ msgstr ""
"Alle titels toevoegen na de nu spelende titel en alle overige titels uit de "
"afspeellijst verwijderen"
#: mpdevil:1676 mpdevil:2716
#: src/mpdevil.py:1670 src/mpdevil.py:2652
#, python-brace-format
msgid "{number} song ({duration})"
msgid_plural "{number} songs ({duration})"
msgstr[0] "{number} nummer ({duration})"
msgstr[1] "{number} nummers ({duration})"
#: mpdevil:1779
#: src/mpdevil.py:1773
#, python-brace-format
msgid "{hits} hit"
msgid_plural "{hits} hits"
msgstr[0] "{hits} hit"
msgstr[1] "{hits} treffers"
#: mpdevil:1898
#: src/mpdevil.py:1892
msgid "all tags"
msgstr "alle tags"
#: mpdevil:2028
#: src/mpdevil.py:2024
msgid "all genres"
msgstr "alle genres"
#: mpdevil:2053
#: src/mpdevil.py:2050
msgid "all artists"
msgstr "alle artiesten"
#: mpdevil:2486
#: src/mpdevil.py:2683
msgid "Scroll to current song"
msgstr "Naar de huidige titel scrollen"
#: mpdevil:2819
#: src/mpdevil.py:2785
msgid "searching…"
msgstr "bezig met zoeken…"
#: mpdevil:2824
#: src/mpdevil.py:2790
msgid "connection error"
msgstr "verbindingsfout"
#: mpdevil:2826
#: src/mpdevil.py:2792
msgid "lyrics not found"
msgstr "geen songtekst gevonden"
#: mpdevil:2934
#: src/mpdevil.py:2899
msgid "Lyrics"
msgstr "Songtekst"
#: mpdevil:3025 mpdevil:3026
#: src/mpdevil.py:2990 src/mpdevil.py:2991
#, python-brace-format
msgid "{number} song"
msgid_plural "{number} songs"
msgstr[0] "{number} nummer"
msgstr[1] "{number} nummers"
#: mpdevil:3231
#: src/mpdevil.py:3196
msgid "Repeat mode"
msgstr "Herhaalmodus"
#: mpdevil:3232
#: src/mpdevil.py:3197
msgid "Random mode"
msgstr "Willekeurige modus"
#: mpdevil:3233
#: src/mpdevil.py:3198
msgid "Single mode"
msgstr "Enkele modus"
#: mpdevil:3234
#: src/mpdevil.py:3199
msgid "Consume mode"
msgstr "Verbruiksmodus"
#: mpdevil:3451
msgid "General"
msgstr "Algemeen"
#: mpdevil:3452
msgid "Window"
msgstr "Venster"
#: mpdevil:3453
msgid "Playback"
msgstr "Afspelen"
#: mpdevil:3454
msgid "Search, Album Dialog, Album List and Artist List"
msgstr "Zoeken, Albumdialoog, Albumlijst en Artiestenlijst"
#: mpdevil:3464
msgid "Open online help"
msgstr "Online hulp openen"
#: mpdevil:3465
msgid "Open shortcuts window"
msgstr "Venster met sneltoetsen openen"
#: mpdevil:3466
msgid "Open menu"
msgstr "Menu openen"
#: mpdevil:3467
msgid "Update database"
msgstr "Database bijwerken"
#: mpdevil:3468
msgid "Quit"
msgstr "Stoppen"
#: mpdevil:3469
msgid "Cycle through profiles"
msgstr "Profielen doorlopen"
#: mpdevil:3470
msgid "Cycle through profiles in reversed order"
msgstr "Profielen doorlopen in omgekeerde volgorde"
#: mpdevil:3471
msgid "Toggle mini player"
msgstr "Omschakelen naar minispeler"
#: mpdevil:3472
msgid "Toggle genre filter"
msgstr "Genrefilter aan/uitzetten"
#: mpdevil:3473
msgid "Toggle lyrics"
msgstr "Omschakelen naar songtekst"
#: mpdevil:3474
msgid "Toggle search"
msgstr "Omschakelen naar zoeken"
#: mpdevil:3475 mpdevil:3635
msgid "Back to current album"
msgstr "Terug naar huidige album"
#: mpdevil:3476
msgid "Play/Pause"
msgstr "Afspelen/Pauzeren"
#: mpdevil:3477
msgid "Stop"
msgstr "Stoppen"
#: mpdevil:3478
msgid "Stop after current title"
msgstr "Stop na huidige titel"
#: mpdevil:3479
msgid "Next title"
msgstr "Volgende titel"
#: mpdevil:3480
msgid "Previous title"
msgstr "Vorige titel"
#: mpdevil:3481
msgid "Seek forward"
msgstr "Vooruit spoelen"
#: mpdevil:3482
msgid "Seek backward"
msgstr "Achteruit spoelen"
#: mpdevil:3483
msgid "Toggle repeat mode"
msgstr "Omschakelen naar herhaalmodus"
#: mpdevil:3484
msgid "Toggle random mode"
msgstr "Omschakelen naar willekeurige modus"
#: mpdevil:3485
msgid "Toggle single mode"
msgstr "Omschakelen naar enkele modus"
#: mpdevil:3486
msgid "Toggle consume mode"
msgstr "Omschakelen naar verbruiksmodus"
#: mpdevil:3487
msgid "Enqueue selected item"
msgstr "Geselecteerde item in wachtrij plaatsen"
#: mpdevil:3488
msgid "Append selected item"
msgstr "Geselecteerde item toevoegen"
#: mpdevil:3488 mpdevil:3491
msgid "Middle-click"
msgstr "Middelklik"
#: mpdevil:3489
msgid "Play selected item immediately"
msgstr "Geselecteerde item direct afspelen"
#: mpdevil:3489
msgid "Double-click"
msgstr "Dubbelklik"
#: mpdevil:3490 mpdevil:3493
msgid "Show additional information"
msgstr "Toon extra informatie"
#: mpdevil:3490 mpdevil:3493
msgid "Right-click"
msgstr "Rechtsklik"
#: mpdevil:3491
msgid "Remove selected song"
msgstr "Geselecteerde titel verwijderen"
#: mpdevil:3492
msgid "Clear playlist"
msgstr "Afspeellijst legen"
#: mpdevil:3512
#: src/mpdevil.py:3421
msgid "Updating Database…"
msgstr "Database bijwerken…"
#: mpdevil:3564
#: src/mpdevil.py:3473
#, python-brace-format
msgid "Connection to “{socket}” failed"
msgstr "Verbinding met „{socket}” mislukt"
#: mpdevil:3566
#: src/mpdevil.py:3475
#, python-brace-format
msgid "Connection to “{host}:{port}” failed"
msgstr "Verbinding met „{host}:{port}” mislukt"
#: mpdevil:3632
#: src/mpdevil.py:3546
msgid "Search"
msgstr "Zoeken"
#: mpdevil:3648
#: src/mpdevil.py:3549 data/ShortcutsWindow.ui:99
msgid "Back to current album"
msgstr "Terug naar huidige album"
#: src/mpdevil.py:3562
msgid "Keyboard Shortcuts"
msgstr "Sneltoetsen"
#: mpdevil:3649
#: src/mpdevil.py:3563
msgid "Help"
msgstr "Hulp"
#: mpdevil:3650
#: src/mpdevil.py:3564
msgid "About mpdevil"
msgstr "Over mpdevil"
#: mpdevil:3652
#: src/mpdevil.py:3566
msgid "Update Database"
msgstr "Database bijwerken"
#: mpdevil:3653
#: src/mpdevil.py:3567
msgid "Server Stats"
msgstr "Serverstatistieken"
#: mpdevil:3660
#: src/mpdevil.py:3574
msgid "Mini Player"
msgstr "Minispeler"
#: mpdevil:3661
#: src/mpdevil.py:3575
msgid "Genre Filter"
msgstr "Genrefilter"
#: mpdevil:3671
#: src/mpdevil.py:3585
msgid "Menu"
msgstr "Menu"
#: mpdevil:3724 mpdevil:3726
#: src/mpdevil.py:3638 src/mpdevil.py:3640
msgid "connecting…"
msgstr "verbinding maken…"
#: mpdevil:3885
#: src/mpdevil.py:3797
msgid "Debug mode"
msgstr "Debugmodus"
#: data/org.mpdevil.mpdevil.desktop.in:3
msgid "mpdevil"
msgstr "mpdevil"
#: data/org.mpdevil.mpdevil.desktop.in:4
msgid "MPD Client"
msgstr "MPD Client"
#: data/org.mpdevil.mpdevil.desktop.in:5 data/AboutDialog.ui:7
msgid "A simple music browser for MPD"
msgstr "Een simpele muziekspeler voor MPD"
#: data/ShortcutsWindow.ui:12
msgid "General"
msgstr "Algemeen"
#: data/ShortcutsWindow.ui:16
msgid "Open online help"
msgstr "Online hulp openen"
#: data/ShortcutsWindow.ui:23
msgid "Open shortcuts window"
msgstr "Venster met sneltoetsen openen"
#: data/ShortcutsWindow.ui:30
msgid "Open menu"
msgstr "Menu openen"
#: data/ShortcutsWindow.ui:37
msgid "Update database"
msgstr "Database bijwerken"
#: data/ShortcutsWindow.ui:44
msgid "Quit"
msgstr "Stoppen"
#: data/ShortcutsWindow.ui:53
msgid "Window"
msgstr "Venster"
#: data/ShortcutsWindow.ui:57
msgid "Cycle through profiles"
msgstr "Profielen doorlopen"
#: data/ShortcutsWindow.ui:64
msgid "Cycle through profiles in reversed order"
msgstr "Profielen doorlopen in omgekeerde volgorde"
#: data/ShortcutsWindow.ui:71
msgid "Toggle mini player"
msgstr "Omschakelen naar minispeler"
#: data/ShortcutsWindow.ui:78
msgid "Toggle genre filter"
msgstr "Genrefilter aan/uitzetten"
#: data/ShortcutsWindow.ui:85
msgid "Toggle lyrics"
msgstr "Omschakelen naar songtekst"
#: data/ShortcutsWindow.ui:92
msgid "Toggle search"
msgstr "Omschakelen naar zoeken"
#: data/ShortcutsWindow.ui:108
msgid "Playback"
msgstr "Afspelen"
#: data/ShortcutsWindow.ui:112
msgid "Play/Pause"
msgstr "Afspelen/Pauzeren"
#: data/ShortcutsWindow.ui:119
msgid "Stop"
msgstr "Stoppen"
#: data/ShortcutsWindow.ui:126
msgid "Stop after current title"
msgstr "Stop na huidige titel"
#: data/ShortcutsWindow.ui:133
msgid "Next title"
msgstr "Volgende titel"
#: data/ShortcutsWindow.ui:140
msgid "Previous title"
msgstr "Vorige titel"
#: data/ShortcutsWindow.ui:147
msgid "Seek forward"
msgstr "Vooruit spoelen"
#: data/ShortcutsWindow.ui:154
msgid "Seek backward"
msgstr "Achteruit spoelen"
#: data/ShortcutsWindow.ui:161
msgid "Toggle repeat mode"
msgstr "Omschakelen naar herhaalmodus"
#: data/ShortcutsWindow.ui:168
msgid "Toggle random mode"
msgstr "Omschakelen naar willekeurige modus"
#: data/ShortcutsWindow.ui:175
msgid "Toggle single mode"
msgstr "Omschakelen naar enkele modus"
#: data/ShortcutsWindow.ui:182
msgid "Toggle consume mode"
msgstr "Omschakelen naar verbruiksmodus"
#: data/ShortcutsWindow.ui:191
msgid "Search, Album Dialog, Album List and Artist List"
msgstr "Zoeken, Albumdialoog, Albumlijst en Artiestenlijst"
#: data/ShortcutsWindow.ui:195
msgid "Enqueue selected item"
msgstr "Geselecteerde item in wachtrij plaatsen"
#: data/ShortcutsWindow.ui:202
msgid "Append selected item"
msgstr "Geselecteerde item toevoegen"
#: data/ShortcutsWindow.ui:203 data/ShortcutsWindow.ui:233
msgid "Middle-click"
msgstr "Middelklik"
#: data/ShortcutsWindow.ui:210
msgid "Play selected item immediately"
msgstr "Geselecteerde item direct afspelen"
#: data/ShortcutsWindow.ui:211
msgid "Double-click"
msgstr "Dubbelklik"
#: data/ShortcutsWindow.ui:218 data/ShortcutsWindow.ui:247
msgid "Show additional information"
msgstr "Toon extra informatie"
#: data/ShortcutsWindow.ui:219 data/ShortcutsWindow.ui:248
msgid "Right-click"
msgstr "Rechtsklik"
#: data/ShortcutsWindow.ui:232
msgid "Remove selected song"
msgstr "Geselecteerde titel verwijderen"
#: data/ShortcutsWindow.ui:240
msgid "Clear playlist"
msgstr "Afspeellijst legen"
#~ msgid "Use “Album Artist” tag"
#~ msgstr "Gebruik tag „Album Artist”"
#~ msgid "Filter by genre"
#~ msgstr "Filter op genre"

View File

@@ -1,30 +0,0 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import DistUtilsExtra.auto
DistUtilsExtra.auto.setup(
name='mpdevil',
version='1.4.1', # sync with bin/mpdevil
author="Martin Wagner",
author_email="martin.wagner.dev@gmail.com",
description=('A simple music browser for MPD'),
url="https://github.com/SoongNoonien/mpdevil",
license='GPL-3.0',
data_files=[
('share/metainfo/', ['data/org.mpdevil.mpdevil.appdata.xml']),
('share/icons/hicolor/16x16/apps/', ['data/icons/16x16/org.mpdevil.mpdevil.png']),
('share/icons/hicolor/24x24/apps/', ['data/icons/24x24/org.mpdevil.mpdevil.png']),
('share/icons/hicolor/32x32/apps/', ['data/icons/32x32/org.mpdevil.mpdevil.png']),
('share/icons/hicolor/48x48/apps/', ['data/icons/48x48/org.mpdevil.mpdevil.png']),
('share/icons/hicolor/64x64/apps/', ['data/icons/64x64/org.mpdevil.mpdevil.png']),
('share/icons/hicolor/128x128/apps/', ['data/icons/128x128/org.mpdevil.mpdevil.png']),
('share/icons/hicolor/256x256/apps/', ['data/icons/256x256/org.mpdevil.mpdevil.png']),
('share/icons/hicolor/scalable/apps/', ['data/icons/scalable/org.mpdevil.mpdevil.svg']),
('share/icons/hicolor/scalable/apps/', ['data/icons/scalable/org.mpdevil.mpdevil-symbolic.svg']),
('share/icons/hicolor/scalable/status/', ['data/icons/scalable/org.mpdevil.mpdevil-single-symbolic.svg']),
('share/icons/hicolor/scalable/status/', ['data/icons/scalable/org.mpdevil.mpdevil-consume-symbolic.svg']),
('share/icons/hicolor/scalable/status/', ['data/icons/scalable/org.mpdevil.mpdevil-consume-symbolic-rtl.svg']),
('share/icons/hicolor/scalable/actions/', ['data/icons/scalable/org.mpdevil.mpdevil-lyrics-symbolic.svg']),
],
)

10
src/meson.build Normal file
View File

@@ -0,0 +1,10 @@
conf = configuration_data()
conf.set('RESOURCES_DIR', resources_dir)
conf.set('LOCALE_DIR', join_paths(get_option('prefix'), get_option('datadir'), 'locale'))
configure_file(
input: 'mpdevil.py',
output: 'mpdevil',
configuration: conf,
install_dir: join_paths(get_option('prefix'), get_option('bindir'))
)

View File

@@ -32,18 +32,18 @@ import os
import sys
import re
import locale
from gettext import gettext as _, ngettext, textdomain, bindtextdomain
try:
locale.setlocale(locale.LC_ALL, "")
except locale.Error as e:
print(e)
from gettext import gettext as _, ngettext, textdomain, bindtextdomain
locale.bindtextdomain("mpdevil", "@LOCALE_DIR@")
locale.textdomain("mpdevil")
bindtextdomain("mpdevil", localedir="@LOCALE_DIR@")
textdomain("mpdevil")
if os.path.isfile("/.flatpak-info"): # test for flatpak environment
bindtextdomain("mpdevil", "/app/share/locale")
else:
bindtextdomain("mpdevil", localedir=None) # replace "None" by a static path if needed (e.g when installing on a non-FHS distro)
Gio.Resource._register(Gio.resource_load(os.path.join("@RESOURCES_DIR@", "mpdevil.gresource")))
VERSION="1.4.1" # sync with setup.py
COVER_REGEX=r"^\.?(album|cover|folder|front).*\.(gif|jpeg|jpg|png)$"
FALLBACK_COVER=Gtk.IconTheme.get_default().lookup_icon("media-optical", 128, Gtk.IconLookupFlags.FORCE_SVG).get_filename()
FALLBACK_SOCKET=os.path.join(GLib.get_user_runtime_dir(), "mpd/socket")
@@ -557,10 +557,13 @@ class Song(collections.UserDict):
def __missing__(self, key):
if self.data:
if key == "albumartist":
if "artist" in self.data:
return self.data["artist"]
else:
return MultiTag([""])
return self["artist"]
elif key == "albumartistsort":
return self["albumartist"]
elif key == "artistsort":
return self["artist"]
elif key == "albumsort":
return self["album"]
elif key == "title":
return MultiTag([os.path.basename(self.data["file"])])
elif key == "duration":
@@ -627,6 +630,37 @@ class Client(MPDClient):
# connect
self._settings.connect("changed::active-profile", self._on_active_profile_changed)
# workaround for list group
# see: https://github.com/Mic92/python-mpd2/pull/187
def _parse_objects(self, lines, delimiters=[], lookup_delimiter=False):
obj = {}
for key, value in self._parse_pairs(lines):
key = key.lower()
if lookup_delimiter and key not in delimiters:
delimiters = delimiters + [key]
if obj:
if key in delimiters:
if lookup_delimiter:
if key in obj:
yield obj
obj = obj.copy()
while delimiters[-1] != key:
obj.pop(delimiters[-1], None)
delimiters.pop()
else:
yield obj
obj = {}
elif key in obj:
if not isinstance(obj[key], list):
obj[key] = [obj[key], value]
else:
obj[key].append(value)
continue
obj[key] = value
if obj:
yield obj
_parse_objects_direct = _parse_objects
# overloads
def currentsong(self, *args):
return Song(super().currentsong(*args))
@@ -690,70 +724,12 @@ class Client(MPDClient):
except:
return False
def files_to_playlist(self, files, mode="default"): # modes: default, play, append, enqueue
def append(files):
for f in files:
self.add(f)
def play(files):
if files:
self.clear()
for f in files:
self.add(f)
self.play()
def enqueue(files):
status=self.status()
if status["state"] == "stop":
self.clear()
append(files)
else:
self.moveid(status["songid"], 0)
current_song_file=self.currentsong()["file"]
try:
self.delete((1,)) # delete all songs, but the first. bad song index possible
except MPDBase.CommandError:
pass
for f in files:
if f == current_song_file:
self.move(0, (int(self.status()["playlistlength"])-1))
else:
self.add(f)
if mode == "append":
append(files)
elif mode == "enqueue":
enqueue(files)
elif mode == "play":
play(files)
elif mode == "default":
def _to_playlist(self, append, mode="default"): # modes: default, play, append, enqueue
if mode == "default":
if self._settings.get_boolean("force-mode"):
play(files)
mode="play"
else:
enqueue(files)
def album_to_playlist(self, album, artist, year, genre, mode="default"):
if genre is None:
genre_filter=()
else:
genre_filter=("genre", genre)
songs=self.find("album", album, "date", year, self._settings.get_artist_type(), artist, *genre_filter)
self.files_to_playlist([song["file"] for song in songs], mode)
def artist_to_playlist(self, artist, genre, mode):
def append():
if self._settings.get_boolean("sort-albums-by-year"):
sort_tag="date"
else:
sort_tag="album"
if artist is None: # treat 'None' as 'all artists'
if genre is None:
self.searchadd("any", "", "sort", sort_tag)
else:
self.findadd("genre", genre, "sort", sort_tag)
else:
artist_type=self._settings.get_artist_type()
if genre is None:
self.findadd(artist_type, artist, "sort", sort_tag)
else:
self.findadd(artist_type, artist, "genre", genre, "sort", sort_tag)
mode="enqueue"
if mode == "append":
append()
elif mode == "play":
@@ -778,6 +754,44 @@ class Client(MPDClient):
self.move(0, duplicates[1]["pos"])
self.delete(int(duplicates[1]["pos"])-1)
def files_to_playlist(self, files, mode="default"):
def append():
for f in files:
self.add(f)
self._to_playlist(append, mode)
def filter_to_playlist(self, tag_filter, mode="default"):
def append():
if tag_filter:
self.findadd(*tag_filter)
else:
self.searchadd("any", "")
self._to_playlist(append, mode)
def album_to_playlist(self, albumartist, albumartistsort, album, albumsort, date, mode="default"):
tag_filter=("albumartist", albumartist, "albumartistsort", albumartistsort, "album", album, "albumsort", albumsort, "date", date)
self.filter_to_playlist(tag_filter, mode)
def artist_to_playlist(self, artist, genre, mode="default"):
def append():
if genre is None:
genre_filter=()
else:
genre_filter=("genre", genre)
if artist is None:
artists=self.get_artists(genre)
else:
artists=[artist]
for albumartist, albumartistsort in artists:
albums=self.list(
"album", "albumartist", albumartist, "albumartistsort", albumartistsort,
*genre_filter, "group", "date", "group", "albumsort")
for album in albums:
self.findadd("albumartist", albumartist, "albumartistsort", albumartistsort,
"album", album["album"], "albumsort", album["albumsort"], "date", album["date"])
self._to_playlist(append, mode)
def comp_list(self, *args): # simulates listing behavior of python-mpd2 1.0
native_list=self.list(*args)
if len(native_list) > 0:
@@ -788,6 +802,13 @@ class Client(MPDClient):
else:
return([])
def get_artists(self, genre):
if genre is None:
artists=self.list("albumartist", "group", "albumartistsort")
else:
artists=self.list("albumartist", "genre", genre, "group", "albumartistsort")
return [(artist["albumartist"], artist["albumartistsort"]) for artist in artists]
def get_cover_path(self, song):
path=None
song_file=song["file"]
@@ -963,12 +984,6 @@ class Settings(Gio.Settings):
array[pos]=value
self.set_value(key, GLib.Variant(vtype, array))
def get_artist_type(self):
if self.get_boolean("use-album-artist"):
return "albumartist"
else:
return "artist"
def get_profile(self, num):
return self._profiles[num]
@@ -1058,7 +1073,6 @@ class BehaviorSettings(SettingsList):
super().__init__()
toggle_data=[
(_("Support “MPRIS”"), "mpris", True),
(_("Use “Album Artist” tag"), "use-album-artist", False),
(_("Sort albums by year"), "sort-albums-by-year", False),
(_("Send notification on title change"), "send-notify", False),
(_("Play selected albums and titles immediately"), "force-mode", False),
@@ -1372,19 +1386,6 @@ class ServerStats(Gtk.Dialog):
self.show_all()
self.run()
class AboutDialog(Gtk.AboutDialog):
def __init__(self, window):
super().__init__(transient_for=window, modal=True)
self.set_program_name("mpdevil")
self.set_version(VERSION)
self.set_comments(_("A simple music browser for MPD"))
self.set_authors(["Martin Wagner"])
self.set_translator_credits("Martin de Reuver\nMartin Wagner")
self.set_website("https://github.com/SoongNoonien/mpdevil")
self.set_copyright("Copyright \xa9 2020-2021 Martin Wagner")
self.set_license_type(Gtk.License.GPL_3_0)
self.set_logo_icon_name("org.mpdevil.mpdevil")
###########################
# general purpose widgets #
###########################
@@ -1657,36 +1658,32 @@ class AlbumPopover(Gtk.Popover):
self.add(songs_window)
songs_window.show_all()
def open(self, album, album_artist, date, genre, widget, x, y):
def open(self, albumartist, albumartistsort, album, albumsort, date, widget, x, y):
self._rect.x=x
self._rect.y=y
self.set_pointing_to(self._rect)
self.set_relative_to(widget)
self._scroll.set_max_content_height(4*widget.get_allocated_height()//7)
self._store.clear()
if genre is None:
genre_filter=()
else:
genre_filter=("genre", genre)
artist_type=self._settings.get_artist_type()
count=self._client.count(artist_type, album_artist, "album", album, "date", date, *genre_filter)
tag_filter=("albumartist", albumartist, "albumartistsort", albumartistsort, "album", album, "albumsort", albumsort, "date", date)
count=self._client.count(*tag_filter)
duration=str(Duration(float(count["playtime"])))
length=int(count["songs"])
text=ngettext("{number} song ({duration})", "{number} songs ({duration})", length).format(number=length, duration=duration)
self._column_title.set_title("".join([_("Title"), text]))
self._client.restrict_tagtypes("track", "title", "artist")
songs=self._client.find("album", album, "date", date, artist_type, album_artist, *genre_filter)
songs=self._client.find(*tag_filter)
self._client.tagtypes("all")
for song in songs:
track=song["track"][0]
title=song["title"][0]
# only show artists =/= albumartist
try:
song["artist"].remove(album_artist)
song["artist"].remove(albumartist)
except ValueError:
pass
artist=str(song["artist"])
if artist == album_artist or not artist:
if artist == albumartist or not artist:
title_artist=f"<b>{GLib.markup_escape_text(title)}</b>"
else:
title_artist=f"<b>{GLib.markup_escape_text(title)}</b> • {GLib.markup_escape_text(artist)}"
@@ -1939,9 +1936,9 @@ class SelectionList(TreeView):
self._selected_path=None
# store
# (item, weight, initial-letter, weight-initials)
self._store=Gtk.ListStore(str, Pango.Weight, str, Pango.Weight)
self._store.append([self.select_all_string, Pango.Weight.BOOK, "", Pango.Weight.BOOK])
# (item, weight, initial-letter, weight-initials, sort-string)
self._store=Gtk.ListStore(str, Pango.Weight, str, Pango.Weight, str)
self._store.append([self.select_all_string, Pango.Weight.BOOK, "", Pango.Weight.BOOK, ""])
self.set_model(self._store)
self._selection=self.get_selection()
@@ -1962,27 +1959,28 @@ class SelectionList(TreeView):
def clear(self):
self._store.clear()
self._store.append([self.select_all_string, Pango.Weight.BOOK, "", Pango.Weight.BOOK])
self._store.append([self.select_all_string, Pango.Weight.BOOK, "", Pango.Weight.BOOK, ""])
self._selected_path=None
self.emit("clear")
def set_items(self, items):
self.clear()
current_char=""
items.sort(key=locale.strxfrm)
items.sort(key=lambda item: locale.strxfrm(item[:1]))
items.sort(key=lambda item: locale.strxfrm(item[1]))
items.sort(key=lambda item: locale.strxfrm(item[1][:1]))
for item in items:
if current_char == item[:1].upper():
self._store.insert_with_valuesv(-1, range(4), [item, Pango.Weight.BOOK, "", Pango.Weight.BOOK])
if current_char == item[1][:1].upper():
self._store.insert_with_valuesv(-1, range(5), [item[0], Pango.Weight.BOOK, "", Pango.Weight.BOOK, item[1]])
else:
self._store.insert_with_valuesv(-1, range(4), [item, Pango.Weight.BOOK, item[:1].upper(), Pango.Weight.BOLD])
current_char=item[:1].upper()
self._store.insert_with_valuesv(
-1, range(5), [item[0], Pango.Weight.BOOK, item[1][:1].upper(), Pango.Weight.BOLD, item[1]])
current_char=item[1][:1].upper()
def get_item(self, path):
def get_item_at_path(self, path):
if path == Gtk.TreePath(0):
return None
else:
return self._store[path][0]
return self._store[path][0,4]
def length(self):
return len(self._store)-1
@@ -1995,7 +1993,7 @@ class SelectionList(TreeView):
row_num=len(self._store)
for i in range(0, row_num):
path=Gtk.TreePath(i)
if self._store[path][0] == item:
if self._store[path][0] == item[0] and self._store[path][4] == item[1]:
self.select_path(path)
break
@@ -2003,13 +2001,14 @@ class SelectionList(TreeView):
self.set_cursor(Gtk.TreePath(0), None, False)
self.row_activated(Gtk.TreePath(0), self._column_item)
def get_selected(self):
def get_path_selected(self):
if self._selected_path is None:
raise ValueError("None selected")
elif self._selected_path == Gtk.TreePath(0):
return None
else:
return self._store[self._selected_path][0]
return self._selected_path
def get_item_selected(self):
return self.get_item_at_path(self.get_path_selected())
def highlight_selected(self):
self.set_cursor(self._selected_path, None, False)
@@ -2036,7 +2035,8 @@ class GenreList(SelectionList):
self.select_all()
def _refresh(self, *args):
self.set_items(self._client.comp_list("genre"))
l=self._client.comp_list("genre")
self.set_items(list(zip(l,l)))
self.select_all()
def _on_disconnected(self, *args):
@@ -2063,24 +2063,22 @@ class ArtistList(SelectionList):
# connect
self.connect("clear", lambda *args: self._artist_popover.popdown())
self.connect("button-press-event", self._on_button_press_event)
self._settings.connect("changed::use-album-artist", self._refresh)
self._client.emitter.connect("disconnected", self._on_disconnected)
self._client.emitter.connect("reconnected", self._on_reconnected)
self.genre_list.connect_after("item-selected", self._refresh)
def _refresh(self, *args):
genre=self.genre_list.get_selected()
if genre is None:
artists=self._client.comp_list(self._settings.get_artist_type())
else:
artists=self._client.comp_list(self._settings.get_artist_type(), "genre", genre)
genre=self.genre_list.get_item_selected()
if genre is not None:
genre=genre[0]
artists=self._client.get_artists(genre)
self.set_items(artists)
if genre is not None:
self.select_all()
else:
song=self._client.currentsong()
if song:
artist=song[self._settings.get_artist_type()][0]
artist=(song["albumartist"][0],song["albumartistsort"][0])
self.select(artist)
else:
if self.length() > 0:
@@ -2094,8 +2092,7 @@ class ArtistList(SelectionList):
path_re=widget.get_path_at_pos(int(event.x), int(event.y))
if path_re is not None:
path=path_re[0]
genre=self.genre_list.get_selected()
artist=self.get_item(path)
artist,genre=self.get_artist_at_path(path)
if event.button == 1:
self._client.artist_to_playlist(artist, genre, "play")
elif event.button == 2:
@@ -2103,20 +2100,28 @@ class ArtistList(SelectionList):
elif event.button == 3:
self._artist_popover.open(artist, genre, self, event.x, event.y)
def get_artist_at_path(self, path):
genre=self.genre_list.get_item_selected()
artist=self.get_item_at_path(path)
if genre is not None:
genre=genre[0]
return (artist, genre)
def get_artist_selected(self):
return self.get_artist_at_path(self.get_path_selected())
def add_to_playlist(self, mode):
selected_rows=self._selection.get_selected_rows()
if selected_rows is not None:
path=selected_rows[1][0]
genre=self.genre_list.get_selected()
artist=self.get_item(path)
artist,genre=self.get_artist_at_path(path)
self._client.artist_to_playlist(artist, genre, mode)
def show_info(self):
treeview, treeiter=self._selection.get_selected()
if treeiter is not None:
path=self._store.get_path(treeiter)
genre=self.genre_list.get_selected()
artist=self.get_item(path)
artist,genre=self.get_artist_at_path(path)
self._artist_popover.open(artist, genre, self, *self.get_popover_point(path))
def _on_disconnected(self, *args):
@@ -2137,28 +2142,22 @@ class AlbumLoadingThread(threading.Thread):
self._artist=artist
self._genre=genre
def _get_albums(self):
for albumartist, albumartistsort in self._artists:
albums=main_thread_function(self._client.list)(
"album", "albumartist", albumartist, "albumartistsort", albumartistsort,
*self._genre_filter, "group", "date", "group", "albumsort")
for album in albums:
album["albumartist"]=albumartist
album["albumartistsort"]=albumartistsort
yield album
def set_callback(self, callback):
self._callback=callback
def stop(self):
self._stop_flag=True
def _album_generator(self):
for artist in self._artists:
try: # client cloud meanwhile disconnect
grouped_albums=main_thread_function(self._client.list)(
"album", self._artist_type, artist, *self._genre_filter, "group", "date")
except (MPDBase.ConnectionError, ConnectionResetError) as e:
return
for album_group in grouped_albums:
date=album_group["date"]
if isinstance(album_group["album"], str):
albums=[album_group["album"]]
else:
albums=album_group["album"]
for album in albums:
yield {"name": album, "artist": artist, "date": date}
def start(self):
self._settings.set_property("cursor-watch", True)
self._progress_bar.show()
@@ -2167,16 +2166,17 @@ class AlbumLoadingThread(threading.Thread):
self._iconview.set_model(None)
self._store.clear()
self._cover_size=self._settings.get_int("album-cover")
self._artist_type=self._settings.get_artist_type()
if self._artist is None:
self._iconview.set_markup_column(2) # show artist names
else:
self._iconview.set_markup_column(1) # hide artist names
if self._genre is None:
self._genre_filter=()
else:
self._genre_filter=("genre", self._genre)
if self._artist is None:
self._iconview.set_markup_column(2) # show artist names
self._artists=self._client.comp_list(self._artist_type, *self._genre_filter)
self._artists=self._client.get_artists(self._genre)
else:
self._iconview.set_markup_column(1) # hide artist names
self._artists=[self._artist]
super().start()
@@ -2184,15 +2184,16 @@ class AlbumLoadingThread(threading.Thread):
# temporarily display all albums with fallback cover
fallback_cover=GdkPixbuf.Pixbuf.new_from_file_at_size(FALLBACK_COVER, self._cover_size, self._cover_size)
add=main_thread_function(self._store.append)
for i, album in enumerate(self._album_generator()):
for i, album in enumerate(self._get_albums()):
# album label
if album["date"]:
display_label=f"<b>{GLib.markup_escape_text(album['name'])}</b> ({GLib.markup_escape_text(album['date'])})"
display_label=f"<b>{GLib.markup_escape_text(album['album'])}</b> ({GLib.markup_escape_text(album['date'])})"
else:
display_label=f"<b>{GLib.markup_escape_text(album['name'])}</b>"
display_label_artist=f"{display_label}\n{GLib.markup_escape_text(album['artist'])}"
display_label=f"<b>{GLib.markup_escape_text(album['album'])}</b>"
display_label_artist=f"{display_label}\n{GLib.markup_escape_text(album['albumartist'])}"
# add album
add([fallback_cover,display_label,display_label_artist,album["name"],album["date"],album["artist"]])
add([fallback_cover,display_label,display_label_artist,
album["albumartist"],album["albumartistsort"],album["album"],album["albumsort"],album["date"]])
if i%10 == 0:
if self._stop_flag:
self._exit()
@@ -2200,9 +2201,9 @@ class AlbumLoadingThread(threading.Thread):
GLib.idle_add(self._progress_bar.pulse)
# sort model
if main_thread_function(self._settings.get_boolean)("sort-albums-by-year"):
main_thread_function(self._store.set_sort_column_id)(4, Gtk.SortType.ASCENDING)
main_thread_function(self._store.set_sort_column_id)(7, Gtk.SortType.ASCENDING)
else:
main_thread_function(self._store.set_sort_column_id)(1, Gtk.SortType.ASCENDING)
main_thread_function(self._store.set_sort_column_id)(6, Gtk.SortType.ASCENDING)
GLib.idle_add(self._iconview.set_model, self._store)
# load covers
total=2*len(self._store)
@@ -2212,7 +2213,9 @@ class AlbumLoadingThread(threading.Thread):
return None
else:
self._client.restrict_tagtypes("albumartist", "album")
song=self._client.find("album",row[3],"date",row[4],self._artist_type,row[5],*self._genre_filter,"window","0:1")[0]
song=self._client.find("albumartist", row[3], "albumartistsort",
row[4], "album", row[5], "albumsort", row[6],
"date", row[7], "window", "0:1")[0]
self._client.tagtypes("all")
return self._client.get_cover(song)
covers=[]
@@ -2256,8 +2259,8 @@ class AlbumList(Gtk.IconView):
self._client=client
self._artist_list=artist_list
# cover, display_label, display_label_artist, album, date, artist
self._store=Gtk.ListStore(GdkPixbuf.Pixbuf, str, str, str, str, str)
# cover, display_label, display_label_artist, albumartist, albumartistsort, album, albumsort, date
self._store=Gtk.ListStore(GdkPixbuf.Pixbuf, str, str, str, str, str, str, str)
self._store.set_default_sort_func(lambda *args: 0)
self.set_model(self._store)
@@ -2266,7 +2269,6 @@ class AlbumList(Gtk.IconView):
# popover
self._album_popover=AlbumPopover(self._client, self._settings)
self._artist_popover=ArtistPopover(self._client)
# cover thread
self._cover_thread=AlbumLoadingThread(self._client, self._settings, self.progress_bar, self, self._store, None, None)
@@ -2290,7 +2292,6 @@ class AlbumList(Gtk.IconView):
def _clear(self, *args):
def callback():
self._album_popover.popdown()
self._artist_popover.popdown()
self._workaround_clear()
if self._cover_thread.is_alive():
self._cover_thread.set_callback(callback)
@@ -2306,7 +2307,7 @@ class AlbumList(Gtk.IconView):
row_num=len(self._store)
for i in range(0, row_num):
path=Gtk.TreePath(i)
if self._store[path][3] == album:
if self._store[path][5] == album:
self.set_cursor(path, None, False)
self.select_path(path)
self.scroll_to_path(path, True, 0, 0)
@@ -2319,16 +2320,15 @@ class AlbumList(Gtk.IconView):
def _sort_settings(self, *args):
if not self._cover_thread.is_alive():
if self._settings.get_boolean("sort-albums-by-year"):
self._store.set_sort_column_id(4, Gtk.SortType.ASCENDING)
self._store.set_sort_column_id(7, Gtk.SortType.ASCENDING)
else:
self._store.set_sort_column_id(1, Gtk.SortType.ASCENDING)
self._store.set_sort_column_id(6, Gtk.SortType.ASCENDING)
def _refresh(self, *args):
def callback():
if self._cover_thread.is_alive(): # already started?
return False
artist=self._artist_list.get_selected()
genre=self._artist_list.genre_list.get_selected()
artist,genre=self._artist_list.get_artist_selected()
self._cover_thread=AlbumLoadingThread(self._client,self._settings,self.progress_bar,self,self._store,artist,genre)
self._cover_thread.start()
if self._cover_thread.is_alive():
@@ -2338,11 +2338,8 @@ class AlbumList(Gtk.IconView):
callback()
def _path_to_playlist(self, path, mode="default"):
album=self._store[path][3]
year=self._store[path][4]
artist=self._store[path][5]
genre=self._artist_list.genre_list.get_selected()
self._client.album_to_playlist(album, artist, year, genre, mode)
tags=self._store[path][3:8]
self._client.album_to_playlist(*tags, mode)
def _on_button_press_event(self, widget, event):
path=widget.get_path_at_pos(int(event.x), int(event.y))
@@ -2355,16 +2352,10 @@ class AlbumList(Gtk.IconView):
elif event.button == 3 and event.type == Gdk.EventType.BUTTON_PRESS:
v=self.get_vadjustment().get_value()
h=self.get_hadjustment().get_value()
genre=self._artist_list.genre_list.get_selected()
if path is not None:
album=self._store[path][3]
year=self._store[path][4]
artist=self._store[path][5]
tags=self._store[path][3:8]
# when using "button-press-event" in iconview popovers only show up in combination with idle_add (bug in GTK?)
GLib.idle_add(self._album_popover.open, album, artist, year, genre, widget, event.x-h, event.y-v)
else:
artist=self._artist_list.get_selected()
GLib.idle_add(self._artist_popover.open, artist, genre, widget, event.x-h, event.y-v)
GLib.idle_add(self._album_popover.open, *tags, widget, event.x-h, event.y-v)
def _on_item_activated(self, widget, path):
self._path_to_playlist(path)
@@ -2383,8 +2374,8 @@ class AlbumList(Gtk.IconView):
rect=self.get_allocation()
x=max(min(rect.x+cell.width//2, rect.x+rect.width), rect.x)
y=max(min(cell.y+cell.height//2, rect.y+rect.height), rect.y)
genre=self._artist_list.genre_list.get_selected()
self._album_popover.open(self._store[path][3], self._store[path][5], self._store[path][4], genre, self, x, y)
tags=self._store[path][3:8]
self._album_popover.open(*tags, self, x, y)
def add_to_playlist(self, mode):
paths=self.get_selected_items()
@@ -2428,16 +2419,15 @@ class Browser(Gtk.Paned):
def back_to_current_album(self, force=False):
song=self._client.currentsong()
if song:
# get artist name
artist=song[self._settings.get_artist_type()][0]
artist,genre=self._artist_list.get_artist_selected()
# deactivate genre filter to show all artists (if needed)
if song["genre"][0] != self._genre_list.get_selected() or force:
if song["genre"][0] != genre or force:
self._genre_list.deactivate()
# select artist
if self._artist_list.get_selected() is None and not force: # all artists selected
if artist is None and not force: # all artists selected
self._artist_list.highlight_selected()
else: # one artist selected
self._artist_list.select(artist)
self._artist_list.select((song["albumartist"][0],song["albumartistsort"][0]))
self._album_list.scroll_to_current_album()
else:
self._genre_list.deactivate()
@@ -2503,8 +2493,6 @@ class PlaylistView(TreeView):
self._settings.connect("changed::column-visibilities", self._load_settings)
self._settings.connect("changed::column-permutation", self._load_settings)
self._settings.bind("mini-player", self, "no-show-all", Gio.SettingsBindFlags.GET)
self._settings.bind("mini-player", self, "visible", Gio.SettingsBindFlags.INVERT_BOOLEAN|Gio.SettingsBindFlags.GET)
def _on_column_width(self, obj, typestring, pos):
self._settings.array_modify("ai", "column-sizes", pos, obj.get_property("fixed-width"))
@@ -2709,6 +2697,8 @@ class PlaylistWindow(Gtk.Overlay):
self._back_to_current_song_button.connect("clicked", self._on_back_to_current_song_button_clicked)
scroll.get_vadjustment().connect("value-changed", self._on_show_hide_back_button)
self._treeview.connect("notify::selected-path", self._on_show_hide_back_button)
settings.bind("mini-player", self, "no-show-all", Gio.SettingsBindFlags.GET)
settings.bind("mini-player", self, "visible", Gio.SettingsBindFlags.INVERT_BOOLEAN|Gio.SettingsBindFlags.GET)
# packing
self.add(scroll)
@@ -2844,17 +2834,16 @@ class CoverEventBox(Gtk.EventBox):
if self._client.connected():
song=self._client.currentsong()
if song:
artist=song[self._settings.get_artist_type()][0]
album=song["album"][0]
year=song["date"][0]
tags=(song["albumartist"][0], song["albumartistsort"][0],
song["album"][0], song["albumsort"][0], song["date"][0])
if event.button == 1 and event.type == Gdk.EventType.BUTTON_PRESS:
self._client.album_to_playlist(album, artist, year, None)
self._client.album_to_playlist(*tags)
elif event.button == 1 and event.type == Gdk.EventType._2BUTTON_PRESS:
self._client.album_to_playlist(album, artist, year, None, "play")
self._client.album_to_playlist(*tags, "play")
elif event.button == 2 and event.type == Gdk.EventType.BUTTON_PRESS:
self._client.album_to_playlist(album, artist, year, None, "append")
self._client.album_to_playlist(*tags, "append")
elif event.button == 3 and event.type == Gdk.EventType.BUTTON_PRESS:
self._album_popover.open(album, artist, year, None, widget, event.x, event.y)
self._album_popover.open(*tags, widget, event.x, event.y)
def _on_disconnected(self, *args):
self._album_popover.popdown()
@@ -3420,62 +3409,6 @@ class MPDActionGroup(Gio.SimpleActionGroup):
for action in self._enable_on_reconnect_data:
self.lookup_action(action).set_enabled(True)
####################
# shortcuts window #
####################
class ShortcutsWindow(Gtk.ShortcutsWindow):
def __init__(self):
super().__init__()
general_group=Gtk.ShortcutsGroup(title=_("General"), visible=True)
window_group=Gtk.ShortcutsGroup(title=_("Window"), visible=True)
playback_group=Gtk.ShortcutsGroup(title=_("Playback"), visible=True)
items_group=Gtk.ShortcutsGroup(title=_("Search, Album Dialog, Album List and Artist List"), visible=True)
playlist_group=Gtk.ShortcutsGroup(title=_("Playlist"), visible=True)
section=Gtk.ShortcutsSection(section_name="shortcuts", visible=True)
section.add(general_group)
section.add(window_group)
section.add(playback_group)
section.add(items_group)
section.add(playlist_group)
shortcut_data=(
("F1", _("Open online help"), None, general_group),
("<Control>question", _("Open shortcuts window"), None, general_group),
("F10", _("Open menu"), None, general_group),
("F5", _("Update database"), None, general_group),
("<Control>q", _("Quit"), None, general_group),
("<Control>p", _("Cycle through profiles"), None, window_group),
("<Shift><Control>p", _("Cycle through profiles in reversed order"), None, window_group),
("<Control>m", _("Toggle mini player"), None, window_group),
("<Control>g", _("Toggle genre filter"), None, window_group),
("<Control>l", _("Toggle lyrics"), None, window_group),
("<Control>f", _("Toggle search"), None, window_group),
("Escape", _("Back to current album"), None, window_group),
("space", _("Play/Pause"), None, playback_group),
("<Shift>space", _("Stop"), None, playback_group),
("<Control>space", _("Stop after current title"), None, playback_group),
("KP_Add", _("Next title"), None, playback_group),
("KP_Subtract", _("Previous title"), None, playback_group),
("KP_Multiply", _("Seek forward"), None, playback_group),
("KP_Divide", _("Seek backward"), None, playback_group),
("<Control>r", _("Toggle repeat mode"), None, playback_group),
("<Control>s", _("Toggle random mode"), None, playback_group),
("<Control>1", _("Toggle single mode"), None, playback_group),
("<Control>o", _("Toggle consume mode"), None, playback_group),
("<Control>e", _("Enqueue selected item"), None, items_group),
("<Control>plus", _("Append selected item"), _("Middle-click"), items_group),
("<Control>Return", _("Play selected item immediately"), _("Double-click"), items_group),
("<Control>i Menu", _("Show additional information"), _("Right-click"), items_group),
("Delete", _("Remove selected song"), _("Middle-click"), playlist_group),
("<Shift>Delete", _("Clear playlist"), None, playlist_group),
("<Control>i Menu", _("Show additional information"), _("Right-click"), playlist_group)
)
for accel, title, subtitle, group in shortcut_data:
shortcut=Gtk.ShortcutsShortcut(visible=True, accelerator=accel, title=title, subtitle=subtitle)
group.pack_start(shortcut, False, False, 0)
self.add(section)
###############
# main window #
###############
@@ -3587,9 +3520,9 @@ class MainWindow(Gtk.ApplicationWindow):
self.add_action(self._settings.create_action("active-profile"))
# shortcuts
shortcuts_window=ShortcutsWindow()
self.set_help_overlay(shortcuts_window)
shortcuts_window.set_modal(False)
builder=Gtk.Builder()
builder.add_from_resource("/org/mpdevil/mpdevil/ShortcutsWindow.ui")
self.set_help_overlay(builder.get_object("shortcuts_window"))
# widgets
self._paned0=Gtk.Paned()
@@ -3912,7 +3845,10 @@ class mpdevil(Gtk.Application):
return 0
def _on_about(self, *args):
dialog=AboutDialog(self._window)
builder=Gtk.Builder()
builder.add_from_resource("/org/mpdevil/mpdevil/AboutDialog.ui")
dialog=builder.get_object("about_dialog")
dialog.set_transient_for(self._window)
dialog.run()
dialog.destroy()