mirror of
https://github.com/SoongNoonien/mpdevil.git
synced 2023-08-10 21:12:44 +03:00
Compare commits
27 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
7037628af9 | ||
![]() |
26ee51fb18 | ||
![]() |
9625bd9cf3 | ||
![]() |
75d8ff21c6 | ||
![]() |
36b023f04c | ||
![]() |
177bd27aa5 | ||
![]() |
e07cce7ea6 | ||
![]() |
0332fe75b7 | ||
![]() |
e62f4824c2 | ||
![]() |
b9b1ba989a | ||
![]() |
f1831a5569 | ||
![]() |
b904907f6f | ||
![]() |
54673a9840 | ||
![]() |
89ffc03cb2 | ||
![]() |
d04c84e5d0 | ||
![]() |
6990d59f72 | ||
![]() |
421f685b58 | ||
![]() |
6238df4d21 | ||
![]() |
b8d1f9aafc | ||
![]() |
3414212173 | ||
![]() |
ab7c9c6bd6 | ||
![]() |
4c7f953c98 | ||
![]() |
8ba986bb4d | ||
![]() |
0230544df4 | ||
![]() |
0b08bd80bf | ||
![]() |
b786b55644 | ||
![]() |
6f608d923b |
33
README.md
Normal file
33
README.md
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
README for mpdevil
|
||||||
|
==================
|
||||||
|
mpdevil is focused on playing your local music directly instead of managing playlists or playing network streams. So it neither supports saving playlists nor restoring them. Therefore mpdevil is mainly a music browser which aims to be easy to use. mpdevil dosen't store any client side database of your music library. Instead all tags and covers get presented to you in real time. So you'll never see any outdated information in your browser. mpdevil strongly relies on tags especially on the AlbumArtist tag.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Features
|
||||||
|
--------
|
||||||
|
|
||||||
|
1. playing songs without doubleclicking
|
||||||
|
2. displaying covers
|
||||||
|
3. fetching lyrics form the web (based on PyLyrics 1.1.0)
|
||||||
|
4. searching songs in your music library
|
||||||
|
5. removing single tracks form playlist by hovering and pressing del
|
||||||
|
6. appending albums by middleclick
|
||||||
|
7. query albums by rightclick
|
||||||
|
8. sending notifications on title change
|
||||||
|
9. managing multiple mpd servers
|
||||||
|
|
||||||
|
TODO
|
||||||
|
----
|
||||||
|
1. MPRIS interface
|
||||||
|
2. connecting to mpd servers with password
|
||||||
|
|
||||||
|
Building and installation
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
To build from source, use::
|
||||||
|
|
||||||
|
./autogen.sh
|
||||||
|
make
|
||||||
|
make install
|
||||||
|
|
30
README.rst
30
README.rst
@@ -1,30 +0,0 @@
|
|||||||
README for mpdevil
|
|
||||||
==================
|
|
||||||
mpdevil is focused on playing your local music directly instead of managing playlists or playing network streams. So it neither supports saving playlists nor restoring them. Therefore mpdevil is mainly a music browser which aims to be easy to use. mpdevil dosen't store any client side database of your music library. Instead all tags and covers get presented to you in real time. So you'll never see any outdated information in your browser.
|
|
||||||
|
|
||||||
Features
|
|
||||||
--------
|
|
||||||
|
|
||||||
-playing songs without doubleclicking
|
|
||||||
|
|
||||||
-displaying covers
|
|
||||||
|
|
||||||
-fetching lyrics form the web (based on PyLyrics 1.1.0)
|
|
||||||
|
|
||||||
-searching songs in your music library
|
|
||||||
|
|
||||||
-removing single tracks form playlist by hovering and pressing del
|
|
||||||
|
|
||||||
-sending notifications on title change
|
|
||||||
|
|
||||||
-managing multiple mpd servers
|
|
||||||
|
|
||||||
Building and installation
|
|
||||||
-------------------------
|
|
||||||
|
|
||||||
To build from source, use::
|
|
||||||
|
|
||||||
./autogen.sh
|
|
||||||
make
|
|
||||||
make install
|
|
||||||
|
|
424
bin/mpdevil.py
424
bin/mpdevil.py
@@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/python
|
#!/usr/bin/python3
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# mpdevil - MPD Client.
|
# mpdevil - MPD Client.
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
import gi #python-gobject dev-python/pygobject:3[${PYTHON_USEDEP}]
|
import gi #python-gobject dev-python/pygobject:3[${PYTHON_USEDEP}]
|
||||||
gi.require_version('Gtk', '3.0')
|
gi.require_version('Gtk', '3.0')
|
||||||
from gi.repository import Gtk, Gio, Gdk, GdkPixbuf, GObject, GLib
|
from gi.repository import Gtk, Gio, Gdk, GdkPixbuf, Pango, GObject, GLib
|
||||||
from mpd import MPDClient
|
from mpd import MPDClient
|
||||||
import requests #dev-python/requests
|
import requests #dev-python/requests
|
||||||
from bs4 import BeautifulSoup, Comment #, NavigableString #dev-python/beautifulsoup
|
from bs4 import BeautifulSoup, Comment #, NavigableString #dev-python/beautifulsoup
|
||||||
@@ -79,8 +79,16 @@ class Cover(object):
|
|||||||
return GdkPixbuf.Pixbuf.new_from_file_at_size(self.path, size, size)
|
return GdkPixbuf.Pixbuf.new_from_file_at_size(self.path, size, size)
|
||||||
|
|
||||||
class Client(MPDClient):
|
class Client(MPDClient):
|
||||||
def __init__(self):
|
def __init__(self, settings):
|
||||||
MPDClient.__init__(self)
|
MPDClient.__init__(self)
|
||||||
|
self.settings = settings
|
||||||
|
|
||||||
|
def try_connect_default(self):
|
||||||
|
active=self.settings.get_int("active-profile")
|
||||||
|
try:
|
||||||
|
self.connect(self.settings.get_value("hosts")[active], self.settings.get_value("ports")[active])
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
def connected(self):
|
def connected(self):
|
||||||
try:
|
try:
|
||||||
@@ -89,6 +97,136 @@ class Client(MPDClient):
|
|||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
class Settings(Gio.Settings):
|
||||||
|
BASE_KEY = "org.mpdevil"
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__(schema=self.BASE_KEY)
|
||||||
|
|
||||||
|
def array_append(self, vtype, key, value): #append to Gio.Settings (self.settings) array
|
||||||
|
array=self.get_value(key).unpack()
|
||||||
|
array.append(value)
|
||||||
|
self.set_value(key, GLib.Variant(vtype, array))
|
||||||
|
|
||||||
|
def array_delete(self, vtype, key, pos): #delete entry of Gio.Settings (self.settings) array
|
||||||
|
array=self.get_value(key).unpack()
|
||||||
|
array.pop(pos)
|
||||||
|
self.set_value(key, GLib.Variant(vtype, array))
|
||||||
|
|
||||||
|
def array_modify(self, vtype, key, pos, value): #modify entry of Gio.Settings (self.settings) array
|
||||||
|
array=self.get_value(key).unpack()
|
||||||
|
array[pos]=value
|
||||||
|
self.set_value(key, GLib.Variant(vtype, array))
|
||||||
|
|
||||||
|
def get_gtk_icon_size(self, key):
|
||||||
|
icon_size=self.get_int(key)
|
||||||
|
if icon_size == 16:
|
||||||
|
return Gtk.IconSize.BUTTON
|
||||||
|
elif icon_size == 32:
|
||||||
|
return Gtk.IconSize.DND
|
||||||
|
elif icon_size == 48:
|
||||||
|
return Gtk.IconSize.DIALOG
|
||||||
|
else:
|
||||||
|
raise ValueError
|
||||||
|
|
||||||
|
class AlbumDialog(Gtk.Dialog):
|
||||||
|
def __init__(self, parent, client, album, artist, year):
|
||||||
|
Gtk.Dialog.__init__(self, title=(artist+" - "+album+" ("+year+")"), transient_for=parent)
|
||||||
|
self.add_buttons(Gtk.STOCK_ADD, Gtk.ResponseType.ACCEPT, Gtk.STOCK_MEDIA_PLAY, Gtk.ResponseType.YES, Gtk.STOCK_OPEN, Gtk.ResponseType.OK, Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE)
|
||||||
|
self.set_default_size(800, 600)
|
||||||
|
|
||||||
|
#adding vars
|
||||||
|
self.client=client
|
||||||
|
|
||||||
|
#scroll
|
||||||
|
scroll=Gtk.ScrolledWindow()
|
||||||
|
scroll.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
|
||||||
|
|
||||||
|
#Store
|
||||||
|
#(track, title, artist, duration, file)
|
||||||
|
self.store = Gtk.ListStore(str, str, str, str, str)
|
||||||
|
|
||||||
|
#TreeView
|
||||||
|
self.treeview = Gtk.TreeView(model=self.store)
|
||||||
|
self.treeview.set_search_column(-1)
|
||||||
|
self.treeview.columns_autosize()
|
||||||
|
|
||||||
|
self.selection = self.treeview.get_selection()
|
||||||
|
self.selection.set_mode(Gtk.SelectionMode.SINGLE)
|
||||||
|
|
||||||
|
#Column
|
||||||
|
renderer_text = Gtk.CellRendererText()
|
||||||
|
|
||||||
|
self.column_track = Gtk.TreeViewColumn(_("No"), renderer_text, text=0)
|
||||||
|
self.column_track.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
|
||||||
|
self.column_track.set_property("resizable", False)
|
||||||
|
self.treeview.append_column(self.column_track)
|
||||||
|
|
||||||
|
self.column_title = Gtk.TreeViewColumn(_("Title"), renderer_text, text=1)
|
||||||
|
self.column_title.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
|
||||||
|
self.column_title.set_property("resizable", False)
|
||||||
|
self.treeview.append_column(self.column_title)
|
||||||
|
|
||||||
|
self.column_artist = Gtk.TreeViewColumn(_("Artist"), renderer_text, text=2)
|
||||||
|
self.column_artist.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
|
||||||
|
self.column_artist.set_property("resizable", False)
|
||||||
|
self.treeview.append_column(self.column_artist)
|
||||||
|
|
||||||
|
self.column_time = Gtk.TreeViewColumn(_("Length"), renderer_text, text=3)
|
||||||
|
self.column_time.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
|
||||||
|
self.column_time.set_property("resizable", False)
|
||||||
|
self.treeview.append_column(self.column_time)
|
||||||
|
|
||||||
|
self.populate_treeview(album, artist, year)
|
||||||
|
|
||||||
|
#connect
|
||||||
|
self.title_activated=self.treeview.connect("row-activated", self.on_row_activated)
|
||||||
|
|
||||||
|
#packing
|
||||||
|
scroll.add(self.treeview)
|
||||||
|
self.vbox.pack_start(scroll, True, True, 0) #vbox default widget of dialogs
|
||||||
|
self.vbox.set_spacing(6)
|
||||||
|
self.show_all()
|
||||||
|
|
||||||
|
#selection workaround
|
||||||
|
self.selection.unselect_all()
|
||||||
|
self.title_change=self.selection.connect("changed", self.on_selection_change)
|
||||||
|
|
||||||
|
def on_row_activated(self, widget, path, view_column):
|
||||||
|
treeiter=self.store.get_iter(path)
|
||||||
|
selected_title=self.store.get_value(treeiter, 4)
|
||||||
|
self.client.clear()
|
||||||
|
self.client.add(selected_title)
|
||||||
|
self.client.play()
|
||||||
|
|
||||||
|
def on_selection_change(self, widget):
|
||||||
|
treeiter=widget.get_selected()[1]
|
||||||
|
if not treeiter == None:
|
||||||
|
selected_title=self.store.get_value(treeiter, 4)
|
||||||
|
self.client.add(selected_title)
|
||||||
|
|
||||||
|
def populate_treeview(self, album, artist, year):
|
||||||
|
songs=self.client.find("album", album, "date", year, "albumartist", artist)
|
||||||
|
if not songs == []:
|
||||||
|
for song in songs:
|
||||||
|
try:
|
||||||
|
title=song["title"]
|
||||||
|
except:
|
||||||
|
title=_("Unknown Title")
|
||||||
|
try:
|
||||||
|
artist=song["artist"]
|
||||||
|
except:
|
||||||
|
artist=_("Unknown Artist")
|
||||||
|
try:
|
||||||
|
track=song["track"].zfill(2)
|
||||||
|
except:
|
||||||
|
track="00"
|
||||||
|
try:
|
||||||
|
dura=float(song["duration"])
|
||||||
|
except:
|
||||||
|
dura=0.0
|
||||||
|
duration=str(datetime.timedelta(seconds=int(dura)))
|
||||||
|
self.store.append([track, title, artist, duration, song["file"]] )
|
||||||
|
|
||||||
class ArtistView(Gtk.ScrolledWindow):
|
class ArtistView(Gtk.ScrolledWindow):
|
||||||
def __init__(self, client):
|
def __init__(self, client):
|
||||||
Gtk.ScrolledWindow.__init__(self)
|
Gtk.ScrolledWindow.__init__(self)
|
||||||
@@ -113,7 +251,7 @@ class ArtistView(Gtk.ScrolledWindow):
|
|||||||
|
|
||||||
#Old Name Column
|
#Old Name Column
|
||||||
renderer_text = Gtk.CellRendererText()
|
renderer_text = Gtk.CellRendererText()
|
||||||
self.column_name = Gtk.TreeViewColumn(_("Artist"), renderer_text, text=0)
|
self.column_name = Gtk.TreeViewColumn(_("Album Artist"), renderer_text, text=0)
|
||||||
self.column_name.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
|
self.column_name.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
|
||||||
self.column_name.set_property("resizable", True)
|
self.column_name.set_property("resizable", True)
|
||||||
self.column_name.set_sort_column_id(0)
|
self.column_name.set_sort_column_id(0)
|
||||||
@@ -161,28 +299,19 @@ class AlbumView(Gtk.ScrolledWindow):
|
|||||||
|
|
||||||
self.add(self.iconview)
|
self.add(self.iconview)
|
||||||
|
|
||||||
def gen_title_list(self, album, artist, year): #needed for tooltips
|
def gen_tooltip(self, album, artist, year):
|
||||||
if self.settings.get_boolean("show-album-view-tooltips"):
|
if self.settings.get_boolean("show-album-view-tooltips"):
|
||||||
songs=self.client.find("album", album, "date", year, "albumartist", artist)
|
songs=self.client.find("album", album, "date", year, "albumartist", artist)
|
||||||
length=float(0)
|
length=float(0)
|
||||||
title_list=""
|
|
||||||
for song in songs:
|
for song in songs:
|
||||||
try:
|
try:
|
||||||
title=song["title"]
|
dura=float(song["duration"])
|
||||||
except:
|
except:
|
||||||
title=_("Unknown Title")
|
dura=0.0
|
||||||
try:
|
length=length+dura
|
||||||
track=song["track"].zfill(2)
|
|
||||||
except:
|
|
||||||
track="00"
|
|
||||||
length=length+float(song["duration"])
|
|
||||||
duration=str(datetime.timedelta(seconds=int(float(song["duration"]))))
|
|
||||||
title_list=title_list+"\n"+(track+" - "+title+" ("+duration+")")
|
|
||||||
if not year == "":
|
|
||||||
year=" ("+year+")"
|
|
||||||
length_human_readable=str(datetime.timedelta(seconds=int(length)))
|
length_human_readable=str(datetime.timedelta(seconds=int(length)))
|
||||||
title_list=(_("%(album)s%(year)s (tracks: %(total_tracks)i) (%(total_length)s):") % {"album": album, "year": year, "total_tracks": len(songs), "total_length": length_human_readable})+title_list
|
tooltip=(_("%(total_tracks)i titles (%(total_length)s)") % {"total_tracks": len(songs), "total_length": length_human_readable})
|
||||||
return title_list.replace("&", "") #& must not be in tooltips
|
return tooltip
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@@ -202,9 +331,9 @@ class AlbumView(Gtk.ScrolledWindow):
|
|||||||
cover=Cover(client=self.client, lib_path=self.settings.get_value("paths")[self.settings.get_int("active-profile")], song_file=song_file)
|
cover=Cover(client=self.client, lib_path=self.settings.get_value("paths")[self.settings.get_int("active-profile")], song_file=song_file)
|
||||||
img=cover.get_pixbuf(size)
|
img=cover.get_pixbuf(size)
|
||||||
if album["year"] == "":
|
if album["year"] == "":
|
||||||
self.store.append([img, album["album"], self.gen_title_list(album["album"], artist, album["year"]), album["album"], album["year"]])
|
self.store.append([img, album["album"], self.gen_tooltip(album["album"], artist, album["year"]), album["album"], album["year"]])
|
||||||
else:
|
else:
|
||||||
self.store.append([img, album["album"]+" ("+album["year"]+")", self.gen_title_list(album["album"], artist, album["year"]), album["album"], album["year"]])
|
self.store.append([img, album["album"]+" ("+album["year"]+")", self.gen_tooltip(album["album"], artist, album["year"]), album["album"], album["year"]])
|
||||||
while Gtk.events_pending():
|
while Gtk.events_pending():
|
||||||
Gtk.main_iteration_do(True)
|
Gtk.main_iteration_do(True)
|
||||||
|
|
||||||
@@ -227,7 +356,6 @@ class TrackView(Gtk.Box):
|
|||||||
#TreeView
|
#TreeView
|
||||||
self.treeview = Gtk.TreeView(model=self.store)
|
self.treeview = Gtk.TreeView(model=self.store)
|
||||||
self.treeview.set_search_column(-1)
|
self.treeview.set_search_column(-1)
|
||||||
self.treeview.set_tooltip_column(5)
|
|
||||||
self.treeview.columns_autosize()
|
self.treeview.columns_autosize()
|
||||||
|
|
||||||
#selection
|
#selection
|
||||||
@@ -269,6 +397,16 @@ class TrackView(Gtk.Box):
|
|||||||
#audio infos
|
#audio infos
|
||||||
audio=AudioType(self.client)
|
audio=AudioType(self.client)
|
||||||
|
|
||||||
|
#playlist info
|
||||||
|
self.playlist_info=Gtk.Label()
|
||||||
|
self.playlist_info.set_xalign(0)
|
||||||
|
self.playlist_info.set_ellipsize(Pango.EllipsizeMode.END)
|
||||||
|
|
||||||
|
#status bar
|
||||||
|
status_bar=Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
|
||||||
|
status_bar.pack_start(self.playlist_info, True, True, 0)
|
||||||
|
status_bar.pack_end(audio, False, False, 0)
|
||||||
|
|
||||||
#timeouts
|
#timeouts
|
||||||
GLib.timeout_add(1000, self.update_cover)
|
GLib.timeout_add(1000, self.update_cover)
|
||||||
GLib.timeout_add(100, self.refresh)
|
GLib.timeout_add(100, self.refresh)
|
||||||
@@ -283,7 +421,7 @@ class TrackView(Gtk.Box):
|
|||||||
#packing
|
#packing
|
||||||
self.pack_start(self.cover, False, False, 0)
|
self.pack_start(self.cover, False, False, 0)
|
||||||
self.pack_start(scroll, True, True, 0)
|
self.pack_start(scroll, True, True, 0)
|
||||||
self.pack_end(audio, False, False, 0)
|
self.pack_end(status_bar, False, False, 0)
|
||||||
|
|
||||||
def update_cover(self):
|
def update_cover(self):
|
||||||
try:
|
try:
|
||||||
@@ -302,14 +440,11 @@ class TrackView(Gtk.Box):
|
|||||||
for song in songs:
|
for song in songs:
|
||||||
self.client.add(song["file"])
|
self.client.add(song["file"])
|
||||||
else:
|
else:
|
||||||
if self.settings.get_boolean("add-album") and not force:
|
if self.settings.get_boolean("add-album") and not force and not self.client.status()["state"] == "stop":
|
||||||
self.selection.handler_block(self.title_change)
|
self.selection.handler_block(self.title_change)
|
||||||
status=self.client.status()
|
status=self.client.status()
|
||||||
try:
|
self.client.moveid(status["songid"], 0)
|
||||||
self.client.moveid(status["songid"], 0) #bad song index possible
|
self.song_to_delete=self.client.playlistinfo()[0]["file"]
|
||||||
self.song_to_delete=self.client.playlistinfo()[0]["file"]
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
self.selection.handler_unblock(self.title_change)
|
self.selection.handler_unblock(self.title_change)
|
||||||
try:
|
try:
|
||||||
self.client.delete((1,)) # delete all songs, but the first. #bad song index possible
|
self.client.delete((1,)) # delete all songs, but the first. #bad song index possible
|
||||||
@@ -330,15 +465,17 @@ class TrackView(Gtk.Box):
|
|||||||
self.client.clear()
|
self.client.clear()
|
||||||
for song in songs:
|
for song in songs:
|
||||||
self.client.add(song["file"])
|
self.client.add(song["file"])
|
||||||
self.client.play(0)
|
self.client.play()
|
||||||
|
|
||||||
def refresh(self):
|
def refresh(self):
|
||||||
self.selection.handler_block(self.title_change)
|
self.selection.handler_block(self.title_change)
|
||||||
if self.client.connected():
|
if self.client.connected():
|
||||||
if self.client.playlist() != self.playlist:
|
if self.client.playlist() != self.playlist:
|
||||||
|
self.playlist_info.set_text("")
|
||||||
self.store.clear()
|
self.store.clear()
|
||||||
songs=self.client.playlistinfo()
|
songs=self.client.playlistinfo()
|
||||||
if not songs == []:
|
if not songs == []:
|
||||||
|
whole_length=float(0)
|
||||||
for song in songs:
|
for song in songs:
|
||||||
try:
|
try:
|
||||||
title=song["title"]
|
title=song["title"]
|
||||||
@@ -356,8 +493,15 @@ class TrackView(Gtk.Box):
|
|||||||
album=song["album"]
|
album=song["album"]
|
||||||
except:
|
except:
|
||||||
album=_("Unknown Album")
|
album=_("Unknown Album")
|
||||||
duration=str(datetime.timedelta(seconds=int(float(song["duration"]))))
|
try:
|
||||||
|
dura=float(song["duration"])
|
||||||
|
except:
|
||||||
|
dura=0.0
|
||||||
|
whole_length=whole_length+dura
|
||||||
|
duration=str(datetime.timedelta(seconds=int(dura )))
|
||||||
self.store.append([track, title, artist, album, duration, song["file"].replace("&", "")])
|
self.store.append([track, title, artist, album, duration, song["file"].replace("&", "")])
|
||||||
|
whole_length_human_readable=str(datetime.timedelta(seconds=int(whole_length)))
|
||||||
|
self.playlist_info.set_text(_("%(total_tracks)i titles (%(total_length)s)") % {"total_tracks": len(songs), "total_length": whole_length_human_readable})
|
||||||
self.playlist=self.client.playlist()
|
self.playlist=self.client.playlist()
|
||||||
else:
|
else:
|
||||||
if not self.song_to_delete == "":
|
if not self.song_to_delete == "":
|
||||||
@@ -373,8 +517,9 @@ class TrackView(Gtk.Box):
|
|||||||
path = Gtk.TreePath(int(song))
|
path = Gtk.TreePath(int(song))
|
||||||
self.selection.select_path(path)
|
self.selection.select_path(path)
|
||||||
except:
|
except:
|
||||||
self.selection.select_path(Gtk.TreePath(0))
|
self.selection.unselect_all()
|
||||||
else:
|
else:
|
||||||
|
self.playlist_info.set_text("")
|
||||||
self.store.clear()
|
self.store.clear()
|
||||||
self.playlist=[]
|
self.playlist=[]
|
||||||
self.selection.handler_unblock(self.title_change)
|
self.selection.handler_unblock(self.title_change)
|
||||||
@@ -417,12 +562,13 @@ class TrackView(Gtk.Box):
|
|||||||
self.client.play(selected_title)
|
self.client.play(selected_title)
|
||||||
|
|
||||||
class Browser(Gtk.Box):
|
class Browser(Gtk.Box):
|
||||||
def __init__(self, client, settings):
|
def __init__(self, client, settings, window):
|
||||||
Gtk.Box.__init__(self, orientation=Gtk.Orientation.HORIZONTAL, spacing=3)
|
Gtk.Box.__init__(self, orientation=Gtk.Orientation.HORIZONTAL, spacing=3)
|
||||||
|
|
||||||
#adding vars
|
#adding vars
|
||||||
self.client=client
|
self.client=client
|
||||||
self.settings=settings
|
self.settings=settings
|
||||||
|
self.window=window
|
||||||
|
|
||||||
#widgets
|
#widgets
|
||||||
self.artist_list=ArtistView(self.client)
|
self.artist_list=ArtistView(self.client)
|
||||||
@@ -502,14 +648,26 @@ class Browser(Gtk.Box):
|
|||||||
|
|
||||||
def on_album_view_button_press_event(self, widget, event):
|
def on_album_view_button_press_event(self, widget, event):
|
||||||
path = widget.get_path_at_pos(int(event.x), int(event.y))
|
path = widget.get_path_at_pos(int(event.x), int(event.y))
|
||||||
if event.button == 3:
|
if not path == None:
|
||||||
if not path == None:
|
if not event.button == 1:
|
||||||
treeiter=self.album_list.store.get_iter(path)
|
treeiter=self.album_list.store.get_iter(path)
|
||||||
selected_album=self.album_list.store.get_value(treeiter, 3)
|
selected_album=self.album_list.store.get_value(treeiter, 3)
|
||||||
selected_album_year=self.album_list.store.get_value(treeiter, 4)
|
selected_album_year=self.album_list.store.get_value(treeiter, 4)
|
||||||
treeiter=self.artist_list.selection.get_selected()[1]
|
treeiter=self.artist_list.selection.get_selected()[1]
|
||||||
selected_artist=self.artist_list.store.get_value(treeiter, 0)
|
selected_artist=self.artist_list.store.get_value(treeiter, 0)
|
||||||
|
if event.button == 2:
|
||||||
self.title_list.album_to_playlist(selected_album, selected_artist, selected_album_year, True)
|
self.title_list.album_to_playlist(selected_album, selected_artist, selected_album_year, True)
|
||||||
|
elif event.button == 3:
|
||||||
|
if self.client.connected():
|
||||||
|
album = AlbumDialog(self.window, self.client, selected_album, selected_artist, selected_album_year)
|
||||||
|
response = album.run()
|
||||||
|
if response == Gtk.ResponseType.OK:
|
||||||
|
self.album_list.iconview.select_path(path)
|
||||||
|
elif response == Gtk.ResponseType.ACCEPT:
|
||||||
|
self.title_list.album_to_playlist(selected_album, selected_artist, selected_album_year, True)
|
||||||
|
elif response == Gtk.ResponseType.YES:
|
||||||
|
self.title_list.album_to_playlist(selected_album, selected_artist, selected_album_year, False, True)
|
||||||
|
album.destroy()
|
||||||
|
|
||||||
def on_album_selection_change(self, widget):
|
def on_album_selection_change(self, widget):
|
||||||
paths=widget.get_selected_items()
|
paths=widget.get_selected_items()
|
||||||
@@ -603,21 +761,6 @@ class ProfileSettings(Gtk.Grid):
|
|||||||
self.attach_next_to(self.port_entry, port_label, Gtk.PositionType.RIGHT, 1, 1)
|
self.attach_next_to(self.port_entry, port_label, Gtk.PositionType.RIGHT, 1, 1)
|
||||||
self.attach_next_to(self.path_select_button, path_label, Gtk.PositionType.RIGHT, 1, 1)
|
self.attach_next_to(self.path_select_button, path_label, Gtk.PositionType.RIGHT, 1, 1)
|
||||||
|
|
||||||
def settings_array_append(self, vtype, key, value): #append to Gio.Settings (self.settings) array
|
|
||||||
array=self.settings.get_value(key).unpack()
|
|
||||||
array.append(value)
|
|
||||||
self.settings.set_value(key, GLib.Variant(vtype, array))
|
|
||||||
|
|
||||||
def settings_array_delete(self, vtype, key, pos): #delete entry of Gio.Settings (self.settings) array
|
|
||||||
array=self.settings.get_value(key).unpack()
|
|
||||||
array.pop(pos)
|
|
||||||
self.settings.set_value(key, GLib.Variant(vtype, array))
|
|
||||||
|
|
||||||
def settings_array_modify(self, vtype, key, pos, value): #modify entry of Gio.Settings (self.settings) array
|
|
||||||
array=self.settings.get_value(key).unpack()
|
|
||||||
array[pos]=value
|
|
||||||
self.settings.set_value(key, GLib.Variant(vtype, array))
|
|
||||||
|
|
||||||
def profiles_combo_reload(self, *args):
|
def profiles_combo_reload(self, *args):
|
||||||
self.profiles_combo.handler_block(self.profiles_combo_changed)
|
self.profiles_combo.handler_block(self.profiles_combo_changed)
|
||||||
self.profile_entry.handler_block(self.profile_entry_changed)
|
self.profile_entry.handler_block(self.profile_entry_changed)
|
||||||
@@ -635,33 +778,33 @@ class ProfileSettings(Gtk.Grid):
|
|||||||
|
|
||||||
def on_add_button_clicked(self, *args):
|
def on_add_button_clicked(self, *args):
|
||||||
pos=self.profiles_combo.get_active()
|
pos=self.profiles_combo.get_active()
|
||||||
self.settings_array_append('as', "profiles", "new profile")
|
self.settings.array_append('as', "profiles", "new profile")
|
||||||
self.settings_array_append('as', "hosts", "localhost")
|
self.settings.array_append('as', "hosts", "localhost")
|
||||||
self.settings_array_append('ai', "ports", 6600)
|
self.settings.array_append('ai', "ports", 6600)
|
||||||
self.settings_array_append('as', "paths", "")
|
self.settings.array_append('as', "paths", "")
|
||||||
self.profiles_combo_reload()
|
self.profiles_combo_reload()
|
||||||
self.profiles_combo.set_active(pos)
|
self.profiles_combo.set_active(pos)
|
||||||
|
|
||||||
def on_delete_button_clicked(self, *args):
|
def on_delete_button_clicked(self, *args):
|
||||||
pos=self.profiles_combo.get_active()
|
pos=self.profiles_combo.get_active()
|
||||||
self.settings_array_delete('as', "profiles", pos)
|
self.settings.array_delete('as', "profiles", pos)
|
||||||
self.settings_array_delete('as', "hosts", pos)
|
self.settings.array_delete('as', "hosts", pos)
|
||||||
self.settings_array_delete('ai', "ports", pos)
|
self.settings.array_delete('ai', "ports", pos)
|
||||||
self.settings_array_delete('as', "paths", pos)
|
self.settings.array_delete('as', "paths", pos)
|
||||||
self.profiles_combo_reload()
|
self.profiles_combo_reload()
|
||||||
self.profiles_combo.set_active(0)
|
self.profiles_combo.set_active(0)
|
||||||
|
|
||||||
def on_profile_entry_changed(self, *args):
|
def on_profile_entry_changed(self, *args):
|
||||||
pos=self.profiles_combo.get_active()
|
pos=self.profiles_combo.get_active()
|
||||||
self.settings_array_modify('as', "profiles", pos, self.profile_entry.get_text())
|
self.settings.array_modify('as', "profiles", pos, self.profile_entry.get_text())
|
||||||
self.profiles_combo_reload()
|
self.profiles_combo_reload()
|
||||||
self.profiles_combo.set_active(pos)
|
self.profiles_combo.set_active(pos)
|
||||||
|
|
||||||
def on_host_entry_changed(self, *args):
|
def on_host_entry_changed(self, *args):
|
||||||
self.settings_array_modify('as', "hosts", self.profiles_combo.get_active(), self.host_entry.get_text())
|
self.settings.array_modify('as', "hosts", self.profiles_combo.get_active(), self.host_entry.get_text())
|
||||||
|
|
||||||
def on_port_entry_changed(self, *args):
|
def on_port_entry_changed(self, *args):
|
||||||
self.settings_array_modify('ai', "ports", self.profiles_combo.get_active(), self.port_entry.get_int())
|
self.settings.array_modify('ai', "ports", self.profiles_combo.get_active(), self.port_entry.get_int())
|
||||||
|
|
||||||
def on_path_select_button_clicked(self, widget, parent):
|
def on_path_select_button_clicked(self, widget, parent):
|
||||||
dialog = Gtk.FileChooserDialog(title=_("Choose directory"), transient_for=parent, action=Gtk.FileChooserAction.SELECT_FOLDER)
|
dialog = Gtk.FileChooserDialog(title=_("Choose directory"), transient_for=parent, action=Gtk.FileChooserAction.SELECT_FOLDER)
|
||||||
@@ -671,7 +814,7 @@ class ProfileSettings(Gtk.Grid):
|
|||||||
dialog.set_current_folder(self.settings.get_value("paths")[self.profiles_combo.get_active()])
|
dialog.set_current_folder(self.settings.get_value("paths")[self.profiles_combo.get_active()])
|
||||||
response = dialog.run()
|
response = dialog.run()
|
||||||
if response == Gtk.ResponseType.OK:
|
if response == Gtk.ResponseType.OK:
|
||||||
self.settings_array_modify('as', "paths", self.profiles_combo.get_active(), dialog.get_filename())
|
self.settings.array_modify('as', "paths", self.profiles_combo.get_active(), dialog.get_filename())
|
||||||
dialog.destroy()
|
dialog.destroy()
|
||||||
|
|
||||||
def on_profiles_changed(self, *args):
|
def on_profiles_changed(self, *args):
|
||||||
@@ -708,10 +851,19 @@ class GeneralSettings(Gtk.Grid):
|
|||||||
track_cover_size=IntEntry(self.settings.get_int("track-cover"), 100, 1200)
|
track_cover_size=IntEntry(self.settings.get_int("track-cover"), 100, 1200)
|
||||||
album_cover_size=IntEntry(self.settings.get_int("album-cover"), 50, 600)
|
album_cover_size=IntEntry(self.settings.get_int("album-cover"), 50, 600)
|
||||||
|
|
||||||
|
icon_size_label=Gtk.Label(label=_("Button icon size (restart required):"))
|
||||||
|
icon_size_label.set_xalign(1)
|
||||||
|
icon_size_combo=Gtk.ComboBoxText()
|
||||||
|
icon_size_combo.set_entry_text_column(0)
|
||||||
|
sizes=[16, 32, 48]
|
||||||
|
for i in sizes:
|
||||||
|
icon_size_combo.append_text(str(i))
|
||||||
|
icon_size_combo.set_active(sizes.index(self.settings.get_int("icon-size")))
|
||||||
|
|
||||||
show_stop=Gtk.CheckButton(label=_("Show stop button"))
|
show_stop=Gtk.CheckButton(label=_("Show stop button"))
|
||||||
show_stop.set_active(self.settings.get_boolean("show-stop"))
|
show_stop.set_active(self.settings.get_boolean("show-stop"))
|
||||||
|
|
||||||
show_album_view_tooltips=Gtk.CheckButton(label=_("Show title list as tooltip in album view"))
|
show_album_view_tooltips=Gtk.CheckButton(label=_("Show tooltips in album view"))
|
||||||
show_album_view_tooltips.set_active(self.settings.get_boolean("show-album-view-tooltips"))
|
show_album_view_tooltips.set_active(self.settings.get_boolean("show-album-view-tooltips"))
|
||||||
|
|
||||||
send_notify=Gtk.CheckButton(label=_("Send notification on title change"))
|
send_notify=Gtk.CheckButton(label=_("Send notification on title change"))
|
||||||
@@ -726,6 +878,7 @@ class GeneralSettings(Gtk.Grid):
|
|||||||
#connect
|
#connect
|
||||||
track_cover_size.connect("value-changed", self.on_int_changed, "track-cover")
|
track_cover_size.connect("value-changed", self.on_int_changed, "track-cover")
|
||||||
album_cover_size.connect("value-changed", self.on_int_changed, "album-cover")
|
album_cover_size.connect("value-changed", self.on_int_changed, "album-cover")
|
||||||
|
icon_size_combo.connect("changed", self.on_icon_size_changed)
|
||||||
show_stop.connect("toggled", self.on_toggled, "show-stop")
|
show_stop.connect("toggled", self.on_toggled, "show-stop")
|
||||||
show_album_view_tooltips.connect("toggled", self.on_toggled, "show-album-view-tooltips")
|
show_album_view_tooltips.connect("toggled", self.on_toggled, "show-album-view-tooltips")
|
||||||
send_notify.connect("toggled", self.on_toggled, "send-notify")
|
send_notify.connect("toggled", self.on_toggled, "send-notify")
|
||||||
@@ -735,9 +888,11 @@ class GeneralSettings(Gtk.Grid):
|
|||||||
#packing
|
#packing
|
||||||
self.add(track_cover_label)
|
self.add(track_cover_label)
|
||||||
self.attach_next_to(album_cover_label, track_cover_label, Gtk.PositionType.BOTTOM, 1, 1)
|
self.attach_next_to(album_cover_label, track_cover_label, Gtk.PositionType.BOTTOM, 1, 1)
|
||||||
|
self.attach_next_to(icon_size_label, album_cover_label, Gtk.PositionType.BOTTOM, 1, 1)
|
||||||
self.attach_next_to(track_cover_size, track_cover_label, Gtk.PositionType.RIGHT, 1, 1)
|
self.attach_next_to(track_cover_size, track_cover_label, Gtk.PositionType.RIGHT, 1, 1)
|
||||||
self.attach_next_to(album_cover_size, album_cover_label, Gtk.PositionType.RIGHT, 1, 1)
|
self.attach_next_to(album_cover_size, album_cover_label, Gtk.PositionType.RIGHT, 1, 1)
|
||||||
self.attach_next_to(show_stop, album_cover_label, Gtk.PositionType.BOTTOM, 2, 1)
|
self.attach_next_to(icon_size_combo, icon_size_label, Gtk.PositionType.RIGHT, 1, 1)
|
||||||
|
self.attach_next_to(show_stop, icon_size_label, Gtk.PositionType.BOTTOM, 2, 1)
|
||||||
self.attach_next_to(show_album_view_tooltips, show_stop, Gtk.PositionType.BOTTOM, 2, 1)
|
self.attach_next_to(show_album_view_tooltips, show_stop, Gtk.PositionType.BOTTOM, 2, 1)
|
||||||
self.attach_next_to(send_notify, show_album_view_tooltips, Gtk.PositionType.BOTTOM, 2, 1)
|
self.attach_next_to(send_notify, show_album_view_tooltips, Gtk.PositionType.BOTTOM, 2, 1)
|
||||||
self.attach_next_to(add_album, send_notify, Gtk.PositionType.BOTTOM, 2, 1)
|
self.attach_next_to(add_album, send_notify, Gtk.PositionType.BOTTOM, 2, 1)
|
||||||
@@ -749,6 +904,10 @@ class GeneralSettings(Gtk.Grid):
|
|||||||
def on_toggled(self, widget, key):
|
def on_toggled(self, widget, key):
|
||||||
self.settings.set_boolean(key, widget.get_active())
|
self.settings.set_boolean(key, widget.get_active())
|
||||||
|
|
||||||
|
def on_icon_size_changed(self, box):
|
||||||
|
active_size=int(box.get_active_text())
|
||||||
|
self.settings.set_int("icon-size", active_size)
|
||||||
|
|
||||||
class SettingsDialog(Gtk.Dialog):
|
class SettingsDialog(Gtk.Dialog):
|
||||||
def __init__(self, parent, settings):
|
def __init__(self, parent, settings):
|
||||||
Gtk.Dialog.__init__(self, title=_("Settings"), transient_for=parent)
|
Gtk.Dialog.__init__(self, title=_("Settings"), transient_for=parent)
|
||||||
@@ -767,6 +926,7 @@ class SettingsDialog(Gtk.Dialog):
|
|||||||
tabs.append_page(general, Gtk.Label(label=_("General")))
|
tabs.append_page(general, Gtk.Label(label=_("General")))
|
||||||
tabs.append_page(profiles, Gtk.Label(label=_("Profiles")))
|
tabs.append_page(profiles, Gtk.Label(label=_("Profiles")))
|
||||||
self.vbox.pack_start(tabs, True, True, 0) #vbox default widget of dialogs
|
self.vbox.pack_start(tabs, True, True, 0) #vbox default widget of dialogs
|
||||||
|
self.vbox.set_spacing(6)
|
||||||
|
|
||||||
self.show_all()
|
self.show_all()
|
||||||
|
|
||||||
@@ -777,12 +937,13 @@ class ClientControl(Gtk.ButtonBox):
|
|||||||
#adding vars
|
#adding vars
|
||||||
self.client=client
|
self.client=client
|
||||||
self.settings=settings
|
self.settings=settings
|
||||||
|
self.icon_size=self.settings.get_gtk_icon_size("icon-size")
|
||||||
|
|
||||||
#widgets
|
#widgets
|
||||||
self.play_button = Gtk.Button(image=Gtk.Image.new_from_icon_name("media-playback-start", Gtk.IconSize.DND))
|
self.play_button = Gtk.Button(image=Gtk.Image.new_from_icon_name("media-playback-start-symbolic", self.icon_size))
|
||||||
self.stop_button = Gtk.Button(image=Gtk.Image.new_from_icon_name("media-playback-stop", Gtk.IconSize.DND))
|
self.stop_button = Gtk.Button(image=Gtk.Image.new_from_icon_name("media-playback-stop-symbolic", self.icon_size))
|
||||||
self.prev_button = Gtk.Button(image=Gtk.Image.new_from_icon_name("media-skip-backward", Gtk.IconSize.DND))
|
self.prev_button = Gtk.Button(image=Gtk.Image.new_from_icon_name("media-skip-backward-symbolic", self.icon_size))
|
||||||
self.next_button = Gtk.Button(image=Gtk.Image.new_from_icon_name("media-skip-forward", Gtk.IconSize.DND))
|
self.next_button = Gtk.Button(image=Gtk.Image.new_from_icon_name("media-skip-forward-symbolic", self.icon_size))
|
||||||
|
|
||||||
#connect
|
#connect
|
||||||
self.play_button.connect("clicked", self.on_play_clicked)
|
self.play_button.connect("clicked", self.on_play_clicked)
|
||||||
@@ -805,15 +966,15 @@ class ClientControl(Gtk.ButtonBox):
|
|||||||
if self.client.connected():
|
if self.client.connected():
|
||||||
status=self.client.status()
|
status=self.client.status()
|
||||||
if status["state"] == "play":
|
if status["state"] == "play":
|
||||||
self.play_button.set_image(Gtk.Image.new_from_icon_name("media-playback-pause", Gtk.IconSize.DND))
|
self.play_button.set_image(Gtk.Image.new_from_icon_name("media-playback-pause-symbolic", self.icon_size))
|
||||||
self.prev_button.set_sensitive(True)
|
self.prev_button.set_sensitive(True)
|
||||||
self.next_button.set_sensitive(True)
|
self.next_button.set_sensitive(True)
|
||||||
elif status["state"] == "pause":
|
elif status["state"] == "pause":
|
||||||
self.play_button.set_image(Gtk.Image.new_from_icon_name("media-playback-start", Gtk.IconSize.DND))
|
self.play_button.set_image(Gtk.Image.new_from_icon_name("media-playback-start-symbolic", self.icon_size))
|
||||||
self.prev_button.set_sensitive(True)
|
self.prev_button.set_sensitive(True)
|
||||||
self.next_button.set_sensitive(True)
|
self.next_button.set_sensitive(True)
|
||||||
else:
|
else:
|
||||||
self.play_button.set_image(Gtk.Image.new_from_icon_name("media-playback-start", Gtk.IconSize.DND))
|
self.play_button.set_image(Gtk.Image.new_from_icon_name("media-playback-start-symbolic", self.icon_size))
|
||||||
self.prev_button.set_sensitive(False)
|
self.prev_button.set_sensitive(False)
|
||||||
self.next_button.set_sensitive(False)
|
self.next_button.set_sensitive(False)
|
||||||
return True
|
return True
|
||||||
@@ -830,7 +991,7 @@ class ClientControl(Gtk.ButtonBox):
|
|||||||
self.client.play(status["song"])
|
self.client.play(status["song"])
|
||||||
except:
|
except:
|
||||||
try:
|
try:
|
||||||
self.client.play(0) #bad song index possible
|
self.client.play()
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
self.update()
|
self.update()
|
||||||
@@ -865,7 +1026,9 @@ class SeekBar(Gtk.Box):
|
|||||||
|
|
||||||
#widgets
|
#widgets
|
||||||
self.elapsed=Gtk.Label()
|
self.elapsed=Gtk.Label()
|
||||||
|
self.elapsed.set_width_chars(7)
|
||||||
self.rest=Gtk.Label()
|
self.rest=Gtk.Label()
|
||||||
|
self.rest.set_width_chars(8)
|
||||||
self.scale=Gtk.Scale.new_with_range(orientation=Gtk.Orientation.HORIZONTAL, min=0, max=100, step=0.001)
|
self.scale=Gtk.Scale.new_with_range(orientation=Gtk.Orientation.HORIZONTAL, min=0, max=100, step=0.001)
|
||||||
self.scale.set_draw_value(False)
|
self.scale.set_draw_value(False)
|
||||||
|
|
||||||
@@ -882,13 +1045,10 @@ class SeekBar(Gtk.Box):
|
|||||||
|
|
||||||
def seek(self, range, scroll, value):
|
def seek(self, range, scroll, value):
|
||||||
status=self.client.status()
|
status=self.client.status()
|
||||||
try:
|
duration=float(status["duration"])
|
||||||
duration=float(status["duration"])
|
factor=(value/100)
|
||||||
factor=(value/100)
|
pos=(duration*factor)
|
||||||
pos=(duration*factor)
|
self.client.seekcur(pos)
|
||||||
self.client.seekcur(pos)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
try:
|
try:
|
||||||
@@ -908,22 +1068,25 @@ class SeekBar(Gtk.Box):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
class PlaybackOptions(Gtk.Box):
|
class PlaybackOptions(Gtk.Box):
|
||||||
def __init__(self, client):
|
def __init__(self, client, settings):
|
||||||
Gtk.Box.__init__(self)
|
Gtk.Box.__init__(self)
|
||||||
|
|
||||||
#adding vars
|
#adding vars
|
||||||
self.client=client
|
self.client=client
|
||||||
|
self.settings=settings
|
||||||
|
self.icon_size=self.settings.get_gtk_icon_size("icon-size")
|
||||||
|
|
||||||
#widgets
|
#widgets
|
||||||
self.random=Gtk.ToggleButton(image=Gtk.Image.new_from_icon_name("media-playlist-shuffle-symbolic", Gtk.IconSize.DND))
|
self.random=Gtk.ToggleButton(image=Gtk.Image.new_from_icon_name("media-playlist-shuffle-symbolic", self.icon_size))
|
||||||
self.random.set_tooltip_text(_("Random mode"))
|
self.random.set_tooltip_text(_("Random mode"))
|
||||||
self.repeat=Gtk.ToggleButton(image=Gtk.Image.new_from_icon_name("media-playlist-repeat-symbolic", Gtk.IconSize.DND))
|
self.repeat=Gtk.ToggleButton(image=Gtk.Image.new_from_icon_name("media-playlist-repeat-symbolic", self.icon_size))
|
||||||
self.repeat.set_tooltip_text(_("Repeat mode"))
|
self.repeat.set_tooltip_text(_("Repeat mode"))
|
||||||
self.single=Gtk.ToggleButton(image=Gtk.Image.new_from_icon_name("zoom-original-symbolic", Gtk.IconSize.DND))
|
self.single=Gtk.ToggleButton(image=Gtk.Image.new_from_icon_name("zoom-original-symbolic", self.icon_size))
|
||||||
self.single.set_tooltip_text(_("Single mode"))
|
self.single.set_tooltip_text(_("Single mode"))
|
||||||
self.consume=Gtk.ToggleButton(image=Gtk.Image.new_from_icon_name("edit-cut-symbolic", Gtk.IconSize.DND))
|
self.consume=Gtk.ToggleButton(image=Gtk.Image.new_from_icon_name("edit-cut-symbolic", self.icon_size))
|
||||||
self.consume.set_tooltip_text(_("Consume mode"))
|
self.consume.set_tooltip_text(_("Consume mode"))
|
||||||
self.volume=Gtk.VolumeButton()
|
self.volume=Gtk.VolumeButton()
|
||||||
|
self.volume.set_property("size", self.icon_size)
|
||||||
|
|
||||||
#connect
|
#connect
|
||||||
self.random_toggled=self.random.connect("toggled", self.set_random)
|
self.random_toggled=self.random.connect("toggled", self.set_random)
|
||||||
@@ -1024,6 +1187,7 @@ class AudioType(Gtk.EventBox):
|
|||||||
#widgets
|
#widgets
|
||||||
self.label=Gtk.Label()
|
self.label=Gtk.Label()
|
||||||
self.label.set_xalign(1)
|
self.label.set_xalign(1)
|
||||||
|
self.label.set_ellipsize(Pango.EllipsizeMode.END)
|
||||||
self.popover=Gtk.Popover()
|
self.popover=Gtk.Popover()
|
||||||
|
|
||||||
#Store
|
#Store
|
||||||
@@ -1098,16 +1262,18 @@ class ProfileSelect(Gtk.ComboBoxText):
|
|||||||
self.client=client
|
self.client=client
|
||||||
self.settings=settings
|
self.settings=settings
|
||||||
|
|
||||||
|
#connect
|
||||||
self.changed=self.connect("changed", self.on_changed)
|
self.changed=self.connect("changed", self.on_changed)
|
||||||
|
|
||||||
self.reload()
|
|
||||||
self.set_active(self.settings.get_int("active-profile"))
|
|
||||||
|
|
||||||
self.settings.connect("changed::profiles", self.on_settings_changed)
|
self.settings.connect("changed::profiles", self.on_settings_changed)
|
||||||
self.settings.connect("changed::hosts", self.on_settings_changed)
|
self.settings.connect("changed::hosts", self.on_settings_changed)
|
||||||
self.settings.connect("changed::ports", self.on_settings_changed)
|
self.settings.connect("changed::ports", self.on_settings_changed)
|
||||||
self.settings.connect("changed::paths", self.on_settings_changed)
|
self.settings.connect("changed::paths", self.on_settings_changed)
|
||||||
|
|
||||||
|
self.reload()
|
||||||
|
self.handler_block(self.changed)
|
||||||
|
self.set_active(self.settings.get_int("active-profile"))
|
||||||
|
self.handler_unblock(self.changed)
|
||||||
|
|
||||||
def reload(self, *args):
|
def reload(self, *args):
|
||||||
self.handler_block(self.changed)
|
self.handler_block(self.changed)
|
||||||
self.remove_all()
|
self.remove_all()
|
||||||
@@ -1121,11 +1287,8 @@ class ProfileSelect(Gtk.ComboBoxText):
|
|||||||
def on_changed(self, *args):
|
def on_changed(self, *args):
|
||||||
active=self.get_active()
|
active=self.get_active()
|
||||||
self.settings.set_int("active-profile", active)
|
self.settings.set_int("active-profile", active)
|
||||||
try:
|
self.client.disconnect()
|
||||||
self.client.disconnect()
|
self.client.try_connect_default()
|
||||||
self.client.connect(self.settings.get_value("hosts")[active], self.settings.get_value("ports")[active])
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
class ServerStats(Gtk.Dialog):
|
class ServerStats(Gtk.Dialog):
|
||||||
def __init__(self, parent, client):
|
def __init__(self, parent, client):
|
||||||
@@ -1168,7 +1331,7 @@ class ServerStats(Gtk.Dialog):
|
|||||||
class Search(Gtk.Dialog):
|
class Search(Gtk.Dialog):
|
||||||
def __init__(self, parent, client):
|
def __init__(self, parent, client):
|
||||||
Gtk.Dialog.__init__(self, title=_("Search"), transient_for=parent)
|
Gtk.Dialog.__init__(self, title=_("Search"), transient_for=parent)
|
||||||
self.add_button(Gtk.STOCK_OK, Gtk.ResponseType.OK)
|
self.add_button(Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE)
|
||||||
self.set_default_size(800, 600)
|
self.set_default_size(800, 600)
|
||||||
|
|
||||||
#adding vars
|
#adding vars
|
||||||
@@ -1180,7 +1343,6 @@ class Search(Gtk.Dialog):
|
|||||||
|
|
||||||
#search entry
|
#search entry
|
||||||
self.search_entry=Gtk.SearchEntry()
|
self.search_entry=Gtk.SearchEntry()
|
||||||
self.search_entry.connect("search-changed", self.on_search_changed)
|
|
||||||
|
|
||||||
#label
|
#label
|
||||||
self.label=Gtk.Label()
|
self.label=Gtk.Label()
|
||||||
@@ -1193,7 +1355,6 @@ class Search(Gtk.Dialog):
|
|||||||
#TreeView
|
#TreeView
|
||||||
self.treeview = Gtk.TreeView(model=self.store)
|
self.treeview = Gtk.TreeView(model=self.store)
|
||||||
self.treeview.set_search_column(-1)
|
self.treeview.set_search_column(-1)
|
||||||
self.treeview.set_tooltip_column(5)
|
|
||||||
self.treeview.columns_autosize()
|
self.treeview.columns_autosize()
|
||||||
|
|
||||||
self.selection = self.treeview.get_selection()
|
self.selection = self.treeview.get_selection()
|
||||||
@@ -1205,31 +1366,37 @@ class Search(Gtk.Dialog):
|
|||||||
self.column_track = Gtk.TreeViewColumn(_("No"), renderer_text, text=0)
|
self.column_track = Gtk.TreeViewColumn(_("No"), renderer_text, text=0)
|
||||||
self.column_track.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
|
self.column_track.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
|
||||||
self.column_track.set_property("resizable", False)
|
self.column_track.set_property("resizable", False)
|
||||||
|
self.column_track.set_sort_column_id(0)
|
||||||
self.treeview.append_column(self.column_track)
|
self.treeview.append_column(self.column_track)
|
||||||
|
|
||||||
self.column_title = Gtk.TreeViewColumn(_("Title"), renderer_text, text=1)
|
self.column_title = Gtk.TreeViewColumn(_("Title"), renderer_text, text=1)
|
||||||
self.column_title.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
|
self.column_title.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
|
||||||
self.column_title.set_property("resizable", False)
|
self.column_title.set_property("resizable", False)
|
||||||
|
self.column_title.set_sort_column_id(1)
|
||||||
self.treeview.append_column(self.column_title)
|
self.treeview.append_column(self.column_title)
|
||||||
|
|
||||||
self.column_artist = Gtk.TreeViewColumn(_("Artist"), renderer_text, text=2)
|
self.column_artist = Gtk.TreeViewColumn(_("Artist"), renderer_text, text=2)
|
||||||
self.column_artist.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
|
self.column_artist.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
|
||||||
self.column_artist.set_property("resizable", False)
|
self.column_artist.set_property("resizable", False)
|
||||||
|
self.column_artist.set_sort_column_id(2)
|
||||||
self.treeview.append_column(self.column_artist)
|
self.treeview.append_column(self.column_artist)
|
||||||
|
|
||||||
self.column_album = Gtk.TreeViewColumn(_("Album"), renderer_text, text=3)
|
self.column_album = Gtk.TreeViewColumn(_("Album"), renderer_text, text=3)
|
||||||
self.column_album.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
|
self.column_album.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
|
||||||
self.column_album.set_property("resizable", False)
|
self.column_album.set_property("resizable", False)
|
||||||
|
self.column_album.set_sort_column_id(3)
|
||||||
self.treeview.append_column(self.column_album)
|
self.treeview.append_column(self.column_album)
|
||||||
|
|
||||||
self.column_time = Gtk.TreeViewColumn(_("Length"), renderer_text, text=4)
|
self.column_time = Gtk.TreeViewColumn(_("Length"), renderer_text, text=4)
|
||||||
self.column_time.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
|
self.column_time.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
|
||||||
self.column_time.set_property("resizable", False)
|
self.column_time.set_property("resizable", False)
|
||||||
|
self.column_time.set_sort_column_id(4)
|
||||||
self.treeview.append_column(self.column_time)
|
self.treeview.append_column(self.column_time)
|
||||||
|
|
||||||
#connect
|
#connect
|
||||||
self.title_activated=self.treeview.connect("row-activated", self.on_row_activated)
|
self.title_activated=self.treeview.connect("row-activated", self.on_row_activated)
|
||||||
self.title_change=self.selection.connect("changed", self.on_selection_change)
|
self.title_change=self.selection.connect("changed", self.on_selection_change)
|
||||||
|
self.search_entry.connect("search-changed", self.on_search_changed)
|
||||||
|
|
||||||
#packing
|
#packing
|
||||||
scroll.add(self.treeview)
|
scroll.add(self.treeview)
|
||||||
@@ -1243,7 +1410,7 @@ class Search(Gtk.Dialog):
|
|||||||
selected_title=self.store.get_value(treeiter, 5)
|
selected_title=self.store.get_value(treeiter, 5)
|
||||||
self.client.clear()
|
self.client.clear()
|
||||||
self.client.add(selected_title)
|
self.client.add(selected_title)
|
||||||
self.client.play(0)
|
self.client.play()
|
||||||
|
|
||||||
def on_selection_change(self, widget):
|
def on_selection_change(self, widget):
|
||||||
treeiter=widget.get_selected()[1]
|
treeiter=widget.get_selected()[1]
|
||||||
@@ -1253,7 +1420,7 @@ class Search(Gtk.Dialog):
|
|||||||
|
|
||||||
def on_search_changed(self, widget):
|
def on_search_changed(self, widget):
|
||||||
self.store.clear()
|
self.store.clear()
|
||||||
for song in self.client.search("title", self.search_entry.get_text()):
|
for song in self.client.search("any", self.search_entry.get_text()):
|
||||||
try:
|
try:
|
||||||
title=song["title"]
|
title=song["title"]
|
||||||
except:
|
except:
|
||||||
@@ -1270,7 +1437,11 @@ class Search(Gtk.Dialog):
|
|||||||
album=song["album"]
|
album=song["album"]
|
||||||
except:
|
except:
|
||||||
album=_("Unknown Album")
|
album=_("Unknown Album")
|
||||||
duration=str(datetime.timedelta(seconds=int(float(song["duration"]))))
|
try:
|
||||||
|
dura=float(song["duration"])
|
||||||
|
except:
|
||||||
|
dura=0.0
|
||||||
|
duration=str(datetime.timedelta(seconds=int(dura)))
|
||||||
self.store.append([track, title, artist, album, duration, song["file"].replace("&", "")] )
|
self.store.append([track, title, artist, album, duration, song["file"].replace("&", "")] )
|
||||||
self.label.set_text(_("Hits: %i") % (len(self.store)))
|
self.label.set_text(_("Hits: %i") % (len(self.store)))
|
||||||
|
|
||||||
@@ -1281,15 +1452,11 @@ class LyricsWindow(Gtk.Window): #Lyrics view with own client because MPDClient i
|
|||||||
self.set_default_size(450, 800)
|
self.set_default_size(450, 800)
|
||||||
|
|
||||||
#adding vars
|
#adding vars
|
||||||
self.client=Client()
|
|
||||||
self.settings=settings
|
self.settings=settings
|
||||||
|
self.client=Client(self.settings)
|
||||||
|
|
||||||
#connect client
|
#connect client
|
||||||
active=self.settings.get_int("active-profile")
|
self.client.try_connect_default()
|
||||||
try:
|
|
||||||
self.client.connect(self.settings.get_value("hosts")[active], self.settings.get_value("ports")[active])
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
self.current_song={}
|
self.current_song={}
|
||||||
|
|
||||||
#widgets
|
#widgets
|
||||||
@@ -1316,7 +1483,7 @@ class LyricsWindow(Gtk.Window): #Lyrics view with own client because MPDClient i
|
|||||||
|
|
||||||
def update_loop():
|
def update_loop():
|
||||||
while not self.stop:
|
while not self.stop:
|
||||||
try:
|
if self.client.connected():
|
||||||
cs=self.client.currentsong()
|
cs=self.client.currentsong()
|
||||||
cs.pop("pos") #avoid unnecessary reloads caused by position change of current title
|
cs.pop("pos") #avoid unnecessary reloads caused by position change of current title
|
||||||
if cs != self.current_song:
|
if cs != self.current_song:
|
||||||
@@ -1327,7 +1494,7 @@ class LyricsWindow(Gtk.Window): #Lyrics view with own client because MPDClient i
|
|||||||
text=_("not found")
|
text=_("not found")
|
||||||
GLib.idle_add(update_label, text)
|
GLib.idle_add(update_label, text)
|
||||||
self.current_song=cs
|
self.current_song=cs
|
||||||
except:
|
else:
|
||||||
self.current_song={}
|
self.current_song={}
|
||||||
GLib.idle_add(update_label, _("not connected"))
|
GLib.idle_add(update_label, _("not connected"))
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
@@ -1371,12 +1538,8 @@ class LyricsWindow(Gtk.Window): #Lyrics view with own client because MPDClient i
|
|||||||
return output.encode('utf-8')
|
return output.encode('utf-8')
|
||||||
|
|
||||||
def on_settings_changed(self, *args):
|
def on_settings_changed(self, *args):
|
||||||
active=self.settings.get_int("active-profile")
|
self.client.disconnect()
|
||||||
try:
|
self.client.try_connect_default()
|
||||||
self.client.disconnect()
|
|
||||||
self.client.connect(self.settings.get_value("hosts")[active], self.settings.get_value("ports")[active])
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
class MainWindow(Gtk.ApplicationWindow):
|
class MainWindow(Gtk.ApplicationWindow):
|
||||||
def __init__(self, app, client, settings):
|
def __init__(self, app, client, settings):
|
||||||
@@ -1388,6 +1551,7 @@ class MainWindow(Gtk.ApplicationWindow):
|
|||||||
#adding vars
|
#adding vars
|
||||||
self.client=client
|
self.client=client
|
||||||
self.songid_playing=None
|
self.songid_playing=None
|
||||||
|
self.icon_size=self.settings.get_gtk_icon_size("icon-size")
|
||||||
|
|
||||||
#actions
|
#actions
|
||||||
save_action = Gio.SimpleAction.new("save", None)
|
save_action = Gio.SimpleAction.new("save", None)
|
||||||
@@ -1407,18 +1571,18 @@ class MainWindow(Gtk.ApplicationWindow):
|
|||||||
self.add_action(update_action)
|
self.add_action(update_action)
|
||||||
|
|
||||||
#widgets
|
#widgets
|
||||||
self.browser=Browser(self.client, self.settings)
|
self.browser=Browser(self.client, self.settings, self)
|
||||||
self.profiles=ProfileSelect(self.client, self.settings)
|
self.profiles=ProfileSelect(self.client, self.settings)
|
||||||
self.profiles.set_tooltip_text(_("Select profile"))
|
self.profiles.set_tooltip_text(_("Select profile"))
|
||||||
self.control=ClientControl(self.client, self.settings)
|
self.control=ClientControl(self.client, self.settings)
|
||||||
self.progress=SeekBar(self.client)
|
self.progress=SeekBar(self.client)
|
||||||
self.go_home_button=Gtk.Button(image=Gtk.Image.new_from_icon_name("go-home", Gtk.IconSize.DND))
|
self.go_home_button=Gtk.Button(image=Gtk.Image.new_from_icon_name("go-home-symbolic", self.icon_size))
|
||||||
self.go_home_button.set_tooltip_text(_("Return to album of current title"))
|
self.go_home_button.set_tooltip_text(_("Return to album of current title"))
|
||||||
self.search_button=Gtk.Button(image=Gtk.Image.new_from_icon_name("system-search", Gtk.IconSize.DND))
|
self.search_button=Gtk.Button(image=Gtk.Image.new_from_icon_name("system-search-symbolic", self.icon_size))
|
||||||
self.search_button.set_tooltip_text(_("Title search"))
|
self.search_button.set_tooltip_text(_("Title search"))
|
||||||
self.lyrics_button=Gtk.ToggleButton(image=Gtk.Image.new_from_icon_name("media-view-subtitles", Gtk.IconSize.DND))
|
self.lyrics_button=Gtk.ToggleButton(image=Gtk.Image.new_from_icon_name("media-view-subtitles-symbolic", self.icon_size))
|
||||||
self.lyrics_button.set_tooltip_text(_("Show lyrics"))
|
self.lyrics_button.set_tooltip_text(_("Show lyrics"))
|
||||||
self.play_opts=PlaybackOptions(self.client)
|
self.play_opts=PlaybackOptions(self.client, self.settings)
|
||||||
|
|
||||||
#info bar
|
#info bar
|
||||||
self.info_bar=Gtk.InfoBar.new()
|
self.info_bar=Gtk.InfoBar.new()
|
||||||
@@ -1471,6 +1635,11 @@ class MainWindow(Gtk.ApplicationWindow):
|
|||||||
|
|
||||||
self.add(self.vbox)
|
self.add(self.vbox)
|
||||||
|
|
||||||
|
#connect client
|
||||||
|
self.client.try_connect_default()
|
||||||
|
|
||||||
|
self.show_all()
|
||||||
|
|
||||||
def update(self, app): #update title and send notify
|
def update(self, app): #update title and send notify
|
||||||
if self.client.connected():
|
if self.client.connected():
|
||||||
self.info_bar.set_revealed(False)
|
self.info_bar.set_revealed(False)
|
||||||
@@ -1509,11 +1678,7 @@ class MainWindow(Gtk.ApplicationWindow):
|
|||||||
|
|
||||||
def on_info_bar_response(self, info_bar, response_id):
|
def on_info_bar_response(self, info_bar, response_id):
|
||||||
if response_id == Gtk.ResponseType.OK:
|
if response_id == Gtk.ResponseType.OK:
|
||||||
active=self.settings.get_int("active-profile")
|
self.client.try_connect_default()
|
||||||
try:
|
|
||||||
self.client.connect(self.settings.get_value("hosts")[active], self.settings.get_value("ports")[active])
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
info_bar.set_revealed(False)
|
info_bar.set_revealed(False)
|
||||||
|
|
||||||
def on_search_clicked(self, widget):
|
def on_search_clicked(self, widget):
|
||||||
@@ -1558,17 +1723,17 @@ class MainWindow(Gtk.ApplicationWindow):
|
|||||||
self.client.update()
|
self.client.update()
|
||||||
|
|
||||||
class mpdevil(Gtk.Application):
|
class mpdevil(Gtk.Application):
|
||||||
BASE_KEY = "org.mpdevil"
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, application_id="org.mpdevil", flags=Gio.ApplicationFlags.FLAGS_NONE, **kwargs)
|
super().__init__(*args, application_id="org.mpdevil", flags=Gio.ApplicationFlags.FLAGS_NONE, **kwargs)
|
||||||
self.client=Client()
|
self.settings = Settings()
|
||||||
self.settings = Gio.Settings.new(self.BASE_KEY)
|
self.client=Client(self.settings)
|
||||||
self.window=None
|
self.window=None
|
||||||
|
|
||||||
def do_activate(self):
|
def do_activate(self):
|
||||||
self.window = MainWindow(self, self.client, self.settings)
|
if not self.window: #allow just one instance
|
||||||
self.window.connect("delete-event", self.on_delete_event)
|
self.window = MainWindow(self, self.client, self.settings)
|
||||||
self.window.show_all()
|
self.window.connect("delete-event", self.on_delete_event)
|
||||||
|
self.window.present()
|
||||||
|
|
||||||
def do_startup(self):
|
def do_startup(self):
|
||||||
Gtk.Application.do_startup(self)
|
Gtk.Application.do_startup(self)
|
||||||
@@ -1592,6 +1757,7 @@ class mpdevil(Gtk.Application):
|
|||||||
dialog.set_version(VERSION)
|
dialog.set_version(VERSION)
|
||||||
dialog.set_comments(_("A small MPD client written in python"))
|
dialog.set_comments(_("A small MPD client written in python"))
|
||||||
dialog.set_authors(["Martin Wagner"])
|
dialog.set_authors(["Martin Wagner"])
|
||||||
|
dialog.set_website("https://github.com/SoongNoonien/mpdevil")
|
||||||
dialog.set_logo_icon_name(PACKAGE)
|
dialog.set_logo_icon_name(PACKAGE)
|
||||||
dialog.run()
|
dialog.run()
|
||||||
dialog.destroy()
|
dialog.destroy()
|
||||||
|
18
configure.ac
18
configure.ac
@@ -1,7 +1,7 @@
|
|||||||
dnl -*- Mode: autoconf -*-
|
dnl -*- Mode: autoconf -*-
|
||||||
dnl Process this file with autoconf to produce a configure script.
|
dnl Process this file with autoconf to produce a configure script.
|
||||||
AC_PREREQ([2.68])
|
AC_PREREQ([2.68])
|
||||||
AC_INIT([mpdevil], [0.3])
|
AC_INIT([mpdevil], [0.4.2])
|
||||||
AC_CONFIG_SRCDIR([bin/mpdevil.py])
|
AC_CONFIG_SRCDIR([bin/mpdevil.py])
|
||||||
AM_INIT_AUTOMAKE
|
AM_INIT_AUTOMAKE
|
||||||
AC_CONFIG_MACRO_DIR([m4])
|
AC_CONFIG_MACRO_DIR([m4])
|
||||||
@@ -50,7 +50,7 @@ if $PYTHON -c "$prog" 1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD; then
|
|||||||
AC_MSG_RESULT(found)
|
AC_MSG_RESULT(found)
|
||||||
else
|
else
|
||||||
AC_MSG_RESULT(not found)
|
AC_MSG_RESULT(not found)
|
||||||
AC_MSG_ERROR(MPDClient not found)
|
AC_MSG_ERROR(python module mpd not found)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
dnl Check for beautifulsoup
|
dnl Check for beautifulsoup
|
||||||
@@ -62,7 +62,19 @@ if $PYTHON -c "$prog" 1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD; then
|
|||||||
AC_MSG_RESULT(found)
|
AC_MSG_RESULT(found)
|
||||||
else
|
else
|
||||||
AC_MSG_RESULT(not found)
|
AC_MSG_RESULT(not found)
|
||||||
AC_MSG_ERROR(beautifulsoup not found)
|
AC_MSG_ERROR(python module bs4 not found)
|
||||||
|
fi
|
||||||
|
|
||||||
|
dnl Check for requests
|
||||||
|
AC_MSG_CHECKING(for requests installed)
|
||||||
|
prog="
|
||||||
|
import requests
|
||||||
|
"
|
||||||
|
if $PYTHON -c "$prog" 1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD; then
|
||||||
|
AC_MSG_RESULT(found)
|
||||||
|
else
|
||||||
|
AC_MSG_RESULT(not found)
|
||||||
|
AC_MSG_ERROR(python module requests not found)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AC_CONFIG_FILES([Makefile
|
AC_CONFIG_FILES([Makefile
|
||||||
|
@@ -31,6 +31,11 @@
|
|||||||
<summary>Size of main cover</summary>
|
<summary>Size of main cover</summary>
|
||||||
<description></description>
|
<description></description>
|
||||||
</key>
|
</key>
|
||||||
|
<key type="i" name="icon-size">
|
||||||
|
<default>16</default>
|
||||||
|
<summary>Size of button icons in control bar</summary>
|
||||||
|
<description></description>
|
||||||
|
</key>
|
||||||
<key type="b" name="show-stop">
|
<key type="b" name="show-stop">
|
||||||
<default>false</default>
|
<default>false</default>
|
||||||
<summary>Show stop button</summary>
|
<summary>Show stop button</summary>
|
||||||
|
144
po/de.po
144
po/de.po
@@ -7,8 +7,8 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2020-01-06 00:53+0100\n"
|
"POT-Creation-Date: 2020-01-28 19:56+0100\n"
|
||||||
"PO-Revision-Date: 2020-01-06 00:55+0100\n"
|
"PO-Revision-Date: 2020-01-28 19:58+0100\n"
|
||||||
"Last-Translator: \n"
|
"Last-Translator: \n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
"Language: de\n"
|
"Language: de\n"
|
||||||
@@ -18,136 +18,144 @@ msgstr ""
|
|||||||
"X-Generator: Poedit 2.2.4\n"
|
"X-Generator: Poedit 2.2.4\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
#: mpdevil.py:116 mpdevil.py:250 mpdevil.py:1215
|
#: mpdevil.py:159 mpdevil.py:368 mpdevil.py:1366
|
||||||
msgid "Artist"
|
|
||||||
msgstr "Künstler"
|
|
||||||
|
|
||||||
#: mpdevil.py:173 mpdevil.py:346 mpdevil.py:1260
|
|
||||||
msgid "Unknown Title"
|
|
||||||
msgstr "Unbekannter Titel"
|
|
||||||
|
|
||||||
#: mpdevil.py:184
|
|
||||||
#, python-format
|
|
||||||
msgid "%(album)s%(year)s (tracks: %(total_tracks)i) (%(total_length)s):"
|
|
||||||
msgstr "%(album)s%(year)s (Titel: %(total_tracks)i) (%(total_length)s):"
|
|
||||||
|
|
||||||
#: mpdevil.py:240 mpdevil.py:1205
|
|
||||||
msgid "No"
|
msgid "No"
|
||||||
msgstr "Nr."
|
msgstr "Nr."
|
||||||
|
|
||||||
#: mpdevil.py:245 mpdevil.py:1210
|
#: mpdevil.py:164 mpdevil.py:373 mpdevil.py:1372
|
||||||
msgid "Title"
|
msgid "Title"
|
||||||
msgstr "Titel"
|
msgstr "Titel"
|
||||||
|
|
||||||
#: mpdevil.py:255 mpdevil.py:1225
|
#: mpdevil.py:169 mpdevil.py:378 mpdevil.py:1378
|
||||||
|
msgid "Artist"
|
||||||
|
msgstr "Interpret"
|
||||||
|
|
||||||
|
#: mpdevil.py:174 mpdevil.py:383 mpdevil.py:1390
|
||||||
msgid "Length"
|
msgid "Length"
|
||||||
msgstr "Länge"
|
msgstr "Länge"
|
||||||
|
|
||||||
#: mpdevil.py:354 mpdevil.py:1268
|
#: mpdevil.py:214 mpdevil.py:483 mpdevil.py:1427
|
||||||
|
msgid "Unknown Title"
|
||||||
|
msgstr "Unbekannter Titel"
|
||||||
|
|
||||||
|
#: mpdevil.py:218 mpdevil.py:491 mpdevil.py:1435
|
||||||
msgid "Unknown Artist"
|
msgid "Unknown Artist"
|
||||||
msgstr "Unbekannter Künstler"
|
msgstr "Unbekannter Künstler"
|
||||||
|
|
||||||
#: mpdevil.py:358 mpdevil.py:1272
|
#: mpdevil.py:254
|
||||||
|
msgid "Album Artist"
|
||||||
|
msgstr "Albuminterpret"
|
||||||
|
|
||||||
|
#: mpdevil.py:313 mpdevil.py:504
|
||||||
|
#, python-format
|
||||||
|
msgid "%(total_tracks)i titles (%(total_length)s)"
|
||||||
|
msgstr "%(total_tracks)i Titel (%(total_length)s)"
|
||||||
|
|
||||||
|
#: mpdevil.py:495 mpdevil.py:1439
|
||||||
msgid "Unknown Album"
|
msgid "Unknown Album"
|
||||||
msgstr "Unbekanntes Album"
|
msgstr "Unbekanntes Album"
|
||||||
|
|
||||||
#: mpdevil.py:567
|
#: mpdevil.py:725
|
||||||
msgid "Select"
|
msgid "Select"
|
||||||
msgstr "Auswählen"
|
msgstr "Auswählen"
|
||||||
|
|
||||||
#: mpdevil.py:569
|
#: mpdevil.py:727
|
||||||
msgid "Profile:"
|
msgid "Profile:"
|
||||||
msgstr "Profil:"
|
msgstr "Profil:"
|
||||||
|
|
||||||
#: mpdevil.py:571
|
#: mpdevil.py:729
|
||||||
msgid "Name:"
|
msgid "Name:"
|
||||||
msgstr "Name:"
|
msgstr "Name:"
|
||||||
|
|
||||||
#: mpdevil.py:573
|
#: mpdevil.py:731
|
||||||
msgid "Host:"
|
msgid "Host:"
|
||||||
msgstr "Host:"
|
msgstr "Host:"
|
||||||
|
|
||||||
#: mpdevil.py:575
|
#: mpdevil.py:733
|
||||||
msgid "Port:"
|
msgid "Port:"
|
||||||
msgstr "Port:"
|
msgstr "Port:"
|
||||||
|
|
||||||
#: mpdevil.py:577
|
#: mpdevil.py:735
|
||||||
msgid "Music lib:"
|
msgid "Music lib:"
|
||||||
msgstr "Musikverzeichnis:"
|
msgstr "Musikverzeichnis:"
|
||||||
|
|
||||||
#: mpdevil.py:667
|
#: mpdevil.py:810
|
||||||
msgid "Choose directory"
|
msgid "Choose directory"
|
||||||
msgstr "Verzeichnis Wählen"
|
msgstr "Verzeichnis Wählen"
|
||||||
|
|
||||||
#: mpdevil.py:703
|
#: mpdevil.py:846
|
||||||
msgid "Main cover size:"
|
msgid "Main cover size:"
|
||||||
msgstr "Größe des Haupt-Covers:"
|
msgstr "Größe des Haupt-Covers:"
|
||||||
|
|
||||||
#: mpdevil.py:705
|
#: mpdevil.py:848
|
||||||
msgid "Album-view cover size:"
|
msgid "Album-view cover size:"
|
||||||
msgstr "Covergröße in Albumansicht:"
|
msgstr "Covergröße in Albumansicht:"
|
||||||
|
|
||||||
#: mpdevil.py:711
|
#: mpdevil.py:854
|
||||||
|
msgid "Button icon size (restart required):"
|
||||||
|
msgstr "Symbolgröße der Knöpfe (Neustart erforderlich):"
|
||||||
|
|
||||||
|
#: mpdevil.py:863
|
||||||
msgid "Show stop button"
|
msgid "Show stop button"
|
||||||
msgstr "Zeige Stopp-Knopf"
|
msgstr "Zeige Stopp-Knopf"
|
||||||
|
|
||||||
#: mpdevil.py:714
|
#: mpdevil.py:866
|
||||||
msgid "Show title list as tooltip in album view"
|
msgid "Show tooltips in album view"
|
||||||
msgstr "Zeige Titellisten als Tooltips in Albumansicht"
|
msgstr "Zeige Tooltips in Albumansicht"
|
||||||
|
|
||||||
#: mpdevil.py:717
|
#: mpdevil.py:869
|
||||||
msgid "Send notification on title change"
|
msgid "Send notification on title change"
|
||||||
msgstr "Sende Benachrichtigung bei Titelwechsel"
|
msgstr "Sende Benachrichtigung bei Titelwechsel"
|
||||||
|
|
||||||
#: mpdevil.py:720
|
#: mpdevil.py:872
|
||||||
msgid "Stop playback on quit"
|
msgid "Stop playback on quit"
|
||||||
msgstr "Wiedergabe beim Beenden stoppen"
|
msgstr "Wiedergabe beim Beenden stoppen"
|
||||||
|
|
||||||
#: mpdevil.py:723
|
#: mpdevil.py:875
|
||||||
msgid "Play selected album after current title"
|
msgid "Play selected album after current title"
|
||||||
msgstr "Ausgewähltes Album hinter aktuellem Titel einreihen"
|
msgstr "Ausgewähltes Album hinter aktuellem Titel einreihen"
|
||||||
|
|
||||||
#: mpdevil.py:754 mpdevil.py:1432
|
#: mpdevil.py:913 mpdevil.py:1596
|
||||||
msgid "Settings"
|
msgid "Settings"
|
||||||
msgstr "Einstellungen"
|
msgstr "Einstellungen"
|
||||||
|
|
||||||
#: mpdevil.py:767
|
#: mpdevil.py:926
|
||||||
msgid "General"
|
msgid "General"
|
||||||
msgstr "Allgemein"
|
msgstr "Allgemein"
|
||||||
|
|
||||||
#: mpdevil.py:768
|
#: mpdevil.py:927
|
||||||
msgid "Profiles"
|
msgid "Profiles"
|
||||||
msgstr "Profile"
|
msgstr "Profile"
|
||||||
|
|
||||||
#: mpdevil.py:919
|
#: mpdevil.py:1081
|
||||||
msgid "Random mode"
|
msgid "Random mode"
|
||||||
msgstr "Zufallsmodus"
|
msgstr "Zufallsmodus"
|
||||||
|
|
||||||
#: mpdevil.py:921
|
#: mpdevil.py:1083
|
||||||
msgid "Repeat mode"
|
msgid "Repeat mode"
|
||||||
msgstr "Dauerschleife"
|
msgstr "Dauerschleife"
|
||||||
|
|
||||||
#: mpdevil.py:923
|
#: mpdevil.py:1085
|
||||||
msgid "Single mode"
|
msgid "Single mode"
|
||||||
msgstr "Einzelstückmodus"
|
msgstr "Einzelstückmodus"
|
||||||
|
|
||||||
#: mpdevil.py:925
|
#: mpdevil.py:1087
|
||||||
msgid "Consume mode"
|
msgid "Consume mode"
|
||||||
msgstr "Playliste verbrauchen"
|
msgstr "Playliste verbrauchen"
|
||||||
|
|
||||||
#: mpdevil.py:1019
|
#: mpdevil.py:1182
|
||||||
msgid "Right click to show additional information"
|
msgid "Right click to show additional information"
|
||||||
msgstr "Rechtsclick für weitere Informationen"
|
msgstr "Rechtsclick für weitere Informationen"
|
||||||
|
|
||||||
#: mpdevil.py:1042
|
#: mpdevil.py:1206
|
||||||
msgid "MPD-Tag"
|
msgid "MPD-Tag"
|
||||||
msgstr "MPD-Tag"
|
msgstr "MPD-Tag"
|
||||||
|
|
||||||
#: mpdevil.py:1045 mpdevil.py:1153
|
#: mpdevil.py:1209 mpdevil.py:1316
|
||||||
msgid "Value"
|
msgid "Value"
|
||||||
msgstr "Wert"
|
msgstr "Wert"
|
||||||
|
|
||||||
#: mpdevil.py:1066
|
#: mpdevil.py:1230
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"%(bitrate)s kb/s, %(frequency)s kHz, %(resolution)s bit, %(channels)s "
|
"%(bitrate)s kb/s, %(frequency)s kHz, %(resolution)s bit, %(channels)s "
|
||||||
@@ -156,88 +164,88 @@ msgstr ""
|
|||||||
"%(bitrate)s kb/s, %(frequency)s kHz, %(resolution)s bit, %(channels)s "
|
"%(bitrate)s kb/s, %(frequency)s kHz, %(resolution)s bit, %(channels)s "
|
||||||
"Kanäle, %(file_type)s"
|
"Kanäle, %(file_type)s"
|
||||||
|
|
||||||
#: mpdevil.py:1132
|
#: mpdevil.py:1295
|
||||||
msgid "Stats"
|
msgid "Stats"
|
||||||
msgstr "Statistik"
|
msgstr "Statistik"
|
||||||
|
|
||||||
#: mpdevil.py:1150
|
#: mpdevil.py:1313
|
||||||
msgid "Tag"
|
msgid "Tag"
|
||||||
msgstr "Tag"
|
msgstr "Tag"
|
||||||
|
|
||||||
#: mpdevil.py:1170
|
#: mpdevil.py:1333
|
||||||
msgid "Search"
|
msgid "Search"
|
||||||
msgstr "Suche"
|
msgstr "Suche"
|
||||||
|
|
||||||
#: mpdevil.py:1220
|
#: mpdevil.py:1384
|
||||||
msgid "Album"
|
msgid "Album"
|
||||||
msgstr "Album"
|
msgstr "Album"
|
||||||
|
|
||||||
#: mpdevil.py:1275
|
#: mpdevil.py:1446
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Hits: %i"
|
msgid "Hits: %i"
|
||||||
msgstr "Treffer: %i"
|
msgstr "Treffer: %i"
|
||||||
|
|
||||||
#: mpdevil.py:1279
|
#: mpdevil.py:1450
|
||||||
msgid "Lyrics"
|
msgid "Lyrics"
|
||||||
msgstr "Liedtext"
|
msgstr "Liedtext"
|
||||||
|
|
||||||
#: mpdevil.py:1323
|
#: mpdevil.py:1490
|
||||||
msgid "searching..."
|
msgid "searching..."
|
||||||
msgstr "suche..."
|
msgstr "suche..."
|
||||||
|
|
||||||
#: mpdevil.py:1327
|
#: mpdevil.py:1494
|
||||||
msgid "not found"
|
msgid "not found"
|
||||||
msgstr "nicht gefunden"
|
msgstr "nicht gefunden"
|
||||||
|
|
||||||
#: mpdevil.py:1332
|
#: mpdevil.py:1499
|
||||||
msgid "not connected"
|
msgid "not connected"
|
||||||
msgstr "nicht verbunden"
|
msgstr "nicht verbunden"
|
||||||
|
|
||||||
#: mpdevil.py:1412
|
#: mpdevil.py:1576
|
||||||
msgid "Select profile"
|
msgid "Select profile"
|
||||||
msgstr "Profil auswählen"
|
msgstr "Profil auswählen"
|
||||||
|
|
||||||
#: mpdevil.py:1416
|
#: mpdevil.py:1580
|
||||||
msgid "Return to album of current title"
|
msgid "Return to album of current title"
|
||||||
msgstr "Zu Album des aktuellen Titels zurückkehren"
|
msgstr "Zu Album des aktuellen Titels zurückkehren"
|
||||||
|
|
||||||
#: mpdevil.py:1418
|
#: mpdevil.py:1582
|
||||||
msgid "Title search"
|
msgid "Title search"
|
||||||
msgstr "Titelsuche"
|
msgstr "Titelsuche"
|
||||||
|
|
||||||
#: mpdevil.py:1420
|
#: mpdevil.py:1584
|
||||||
msgid "Show lyrics"
|
msgid "Show lyrics"
|
||||||
msgstr "Zeige Liedtext"
|
msgstr "Zeige Liedtext"
|
||||||
|
|
||||||
#: mpdevil.py:1427
|
#: mpdevil.py:1591
|
||||||
msgid "Not connected to MPD-server. Reconnect?"
|
msgid "Not connected to MPD-server. Reconnect?"
|
||||||
msgstr "Nicht mit MPD-Server verbunden. Verbindung wiederherstellen?"
|
msgstr "Nicht mit MPD-Server verbunden. Verbindung wiederherstellen?"
|
||||||
|
|
||||||
#: mpdevil.py:1431
|
#: mpdevil.py:1595
|
||||||
msgid "Save window size"
|
msgid "Save window size"
|
||||||
msgstr "Fenstergröße speichern"
|
msgstr "Fenstergröße speichern"
|
||||||
|
|
||||||
#: mpdevil.py:1433
|
#: mpdevil.py:1597
|
||||||
msgid "Update database"
|
msgid "Update database"
|
||||||
msgstr "Datenbank aktualisieren"
|
msgstr "Datenbank aktualisieren"
|
||||||
|
|
||||||
#: mpdevil.py:1434
|
#: mpdevil.py:1598
|
||||||
msgid "Server stats"
|
msgid "Server stats"
|
||||||
msgstr "Serverstatistik"
|
msgstr "Serverstatistik"
|
||||||
|
|
||||||
#: mpdevil.py:1435
|
#: mpdevil.py:1599
|
||||||
msgid "About"
|
msgid "About"
|
||||||
msgstr "Über"
|
msgstr "Über"
|
||||||
|
|
||||||
#: mpdevil.py:1436
|
#: mpdevil.py:1600
|
||||||
msgid "Quit"
|
msgid "Quit"
|
||||||
msgstr "Beenden"
|
msgstr "Beenden"
|
||||||
|
|
||||||
#: mpdevil.py:1441
|
#: mpdevil.py:1605
|
||||||
msgid "Main menu"
|
msgid "Main menu"
|
||||||
msgstr "Hauptmenu"
|
msgstr "Hauptmenu"
|
||||||
|
|
||||||
#: mpdevil.py:1593
|
#: mpdevil.py:1758
|
||||||
msgid "A small MPD client written in python"
|
msgid "A small MPD client written in python"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
140
po/mpdevil.pot
140
po/mpdevil.pot
@@ -8,7 +8,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2020-01-06 00:53+0100\n"
|
"POT-Creation-Date: 2020-01-28 19:56+0100\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
@@ -17,223 +17,231 @@ msgstr ""
|
|||||||
"Content-Type: text/plain; charset=CHARSET\n"
|
"Content-Type: text/plain; charset=CHARSET\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
#: mpdevil.py:116 mpdevil.py:250 mpdevil.py:1215
|
#: mpdevil.py:159 mpdevil.py:368 mpdevil.py:1366
|
||||||
msgid "Artist"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: mpdevil.py:173 mpdevil.py:346 mpdevil.py:1260
|
|
||||||
msgid "Unknown Title"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: mpdevil.py:184
|
|
||||||
#, python-format
|
|
||||||
msgid "%(album)s%(year)s (tracks: %(total_tracks)i) (%(total_length)s):"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: mpdevil.py:240 mpdevil.py:1205
|
|
||||||
msgid "No"
|
msgid "No"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:245 mpdevil.py:1210
|
#: mpdevil.py:164 mpdevil.py:373 mpdevil.py:1372
|
||||||
msgid "Title"
|
msgid "Title"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:255 mpdevil.py:1225
|
#: mpdevil.py:169 mpdevil.py:378 mpdevil.py:1378
|
||||||
|
msgid "Artist"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mpdevil.py:174 mpdevil.py:383 mpdevil.py:1390
|
||||||
msgid "Length"
|
msgid "Length"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:354 mpdevil.py:1268
|
#: mpdevil.py:214 mpdevil.py:483 mpdevil.py:1427
|
||||||
|
msgid "Unknown Title"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mpdevil.py:218 mpdevil.py:491 mpdevil.py:1435
|
||||||
msgid "Unknown Artist"
|
msgid "Unknown Artist"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:358 mpdevil.py:1272
|
#: mpdevil.py:254
|
||||||
|
msgid "Album Artist"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mpdevil.py:313 mpdevil.py:504
|
||||||
|
#, python-format
|
||||||
|
msgid "%(total_tracks)i titles (%(total_length)s)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mpdevil.py:495 mpdevil.py:1439
|
||||||
msgid "Unknown Album"
|
msgid "Unknown Album"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:567
|
#: mpdevil.py:725
|
||||||
msgid "Select"
|
msgid "Select"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:569
|
#: mpdevil.py:727
|
||||||
msgid "Profile:"
|
msgid "Profile:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:571
|
#: mpdevil.py:729
|
||||||
msgid "Name:"
|
msgid "Name:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:573
|
#: mpdevil.py:731
|
||||||
msgid "Host:"
|
msgid "Host:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:575
|
#: mpdevil.py:733
|
||||||
msgid "Port:"
|
msgid "Port:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:577
|
#: mpdevil.py:735
|
||||||
msgid "Music lib:"
|
msgid "Music lib:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:667
|
#: mpdevil.py:810
|
||||||
msgid "Choose directory"
|
msgid "Choose directory"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:703
|
#: mpdevil.py:846
|
||||||
msgid "Main cover size:"
|
msgid "Main cover size:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:705
|
#: mpdevil.py:848
|
||||||
msgid "Album-view cover size:"
|
msgid "Album-view cover size:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:711
|
#: mpdevil.py:854
|
||||||
|
msgid "Button icon size (restart required):"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mpdevil.py:863
|
||||||
msgid "Show stop button"
|
msgid "Show stop button"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:714
|
#: mpdevil.py:866
|
||||||
msgid "Show title list as tooltip in album view"
|
msgid "Show tooltips in album view"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:717
|
#: mpdevil.py:869
|
||||||
msgid "Send notification on title change"
|
msgid "Send notification on title change"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:720
|
#: mpdevil.py:872
|
||||||
msgid "Stop playback on quit"
|
msgid "Stop playback on quit"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:723
|
#: mpdevil.py:875
|
||||||
msgid "Play selected album after current title"
|
msgid "Play selected album after current title"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:754 mpdevil.py:1432
|
#: mpdevil.py:913 mpdevil.py:1596
|
||||||
msgid "Settings"
|
msgid "Settings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:767
|
#: mpdevil.py:926
|
||||||
msgid "General"
|
msgid "General"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:768
|
#: mpdevil.py:927
|
||||||
msgid "Profiles"
|
msgid "Profiles"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:919
|
#: mpdevil.py:1081
|
||||||
msgid "Random mode"
|
msgid "Random mode"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:921
|
#: mpdevil.py:1083
|
||||||
msgid "Repeat mode"
|
msgid "Repeat mode"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:923
|
#: mpdevil.py:1085
|
||||||
msgid "Single mode"
|
msgid "Single mode"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:925
|
#: mpdevil.py:1087
|
||||||
msgid "Consume mode"
|
msgid "Consume mode"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:1019
|
#: mpdevil.py:1182
|
||||||
msgid "Right click to show additional information"
|
msgid "Right click to show additional information"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:1042
|
#: mpdevil.py:1206
|
||||||
msgid "MPD-Tag"
|
msgid "MPD-Tag"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:1045 mpdevil.py:1153
|
#: mpdevil.py:1209 mpdevil.py:1316
|
||||||
msgid "Value"
|
msgid "Value"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:1066
|
#: mpdevil.py:1230
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"%(bitrate)s kb/s, %(frequency)s kHz, %(resolution)s bit, %(channels)s "
|
"%(bitrate)s kb/s, %(frequency)s kHz, %(resolution)s bit, %(channels)s "
|
||||||
"channels, %(file_type)s"
|
"channels, %(file_type)s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:1132
|
#: mpdevil.py:1295
|
||||||
msgid "Stats"
|
msgid "Stats"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:1150
|
#: mpdevil.py:1313
|
||||||
msgid "Tag"
|
msgid "Tag"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:1170
|
#: mpdevil.py:1333
|
||||||
msgid "Search"
|
msgid "Search"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:1220
|
#: mpdevil.py:1384
|
||||||
msgid "Album"
|
msgid "Album"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:1275
|
#: mpdevil.py:1446
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Hits: %i"
|
msgid "Hits: %i"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:1279
|
#: mpdevil.py:1450
|
||||||
msgid "Lyrics"
|
msgid "Lyrics"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:1323
|
#: mpdevil.py:1490
|
||||||
msgid "searching..."
|
msgid "searching..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:1327
|
#: mpdevil.py:1494
|
||||||
msgid "not found"
|
msgid "not found"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:1332
|
#: mpdevil.py:1499
|
||||||
msgid "not connected"
|
msgid "not connected"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:1412
|
#: mpdevil.py:1576
|
||||||
msgid "Select profile"
|
msgid "Select profile"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:1416
|
#: mpdevil.py:1580
|
||||||
msgid "Return to album of current title"
|
msgid "Return to album of current title"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:1418
|
#: mpdevil.py:1582
|
||||||
msgid "Title search"
|
msgid "Title search"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:1420
|
#: mpdevil.py:1584
|
||||||
msgid "Show lyrics"
|
msgid "Show lyrics"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:1427
|
#: mpdevil.py:1591
|
||||||
msgid "Not connected to MPD-server. Reconnect?"
|
msgid "Not connected to MPD-server. Reconnect?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:1431
|
#: mpdevil.py:1595
|
||||||
msgid "Save window size"
|
msgid "Save window size"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:1433
|
#: mpdevil.py:1597
|
||||||
msgid "Update database"
|
msgid "Update database"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:1434
|
#: mpdevil.py:1598
|
||||||
msgid "Server stats"
|
msgid "Server stats"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:1435
|
#: mpdevil.py:1599
|
||||||
msgid "About"
|
msgid "About"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:1436
|
#: mpdevil.py:1600
|
||||||
msgid "Quit"
|
msgid "Quit"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:1441
|
#: mpdevil.py:1605
|
||||||
msgid "Main menu"
|
msgid "Main menu"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mpdevil.py:1593
|
#: mpdevil.py:1758
|
||||||
msgid "A small MPD client written in python"
|
msgid "A small MPD client written in python"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
BIN
screenshots/mainwindow.png
Normal file
BIN
screenshots/mainwindow.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1005 KiB |
Reference in New Issue
Block a user