fixup! Adjust line length to match Code Style Guide (see #103)
This commit is contained in:
parent
c04216e634
commit
ded9cf026b
11 changed files with 326 additions and 685 deletions
|
|
@ -11,9 +11,7 @@ from gi.repository import Gtk, GObject, Adw
|
||||||
@Gtk.Template(resource_path='/xyz/suruatoel/mcg/ui/album-headerbar.ui')
|
@Gtk.Template(resource_path='/xyz/suruatoel/mcg/ui/album-headerbar.ui')
|
||||||
class AlbumHeaderbar(Adw.Bin):
|
class AlbumHeaderbar(Adw.Bin):
|
||||||
__gtype_name__ = 'McgAlbumHeaderbar'
|
__gtype_name__ = 'McgAlbumHeaderbar'
|
||||||
__gsignals__ = {
|
__gsignals__ = {'close': (GObject.SIGNAL_RUN_FIRST, None, ())}
|
||||||
'close': (GObject.SIGNAL_RUN_FIRST, None, ())
|
|
||||||
}
|
|
||||||
|
|
||||||
# Widgets
|
# Widgets
|
||||||
standalone_title = Gtk.Template.Child()
|
standalone_title = Gtk.Template.Child()
|
||||||
|
|
|
||||||
|
|
@ -15,10 +15,8 @@ class Application(Gtk.Application):
|
||||||
DOMAIN = 'mcg'
|
DOMAIN = 'mcg'
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__(
|
super().__init__(application_id=Application.ID,
|
||||||
application_id=Application.ID,
|
flags=Gio.ApplicationFlags.FLAGS_NONE)
|
||||||
flags=Gio.ApplicationFlags.FLAGS_NONE
|
|
||||||
)
|
|
||||||
self._window = None
|
self._window = None
|
||||||
self._info_dialog = None
|
self._info_dialog = None
|
||||||
self._verbosity = logging.WARNING
|
self._verbosity = logging.WARNING
|
||||||
|
|
@ -56,25 +54,20 @@ class Application(Gtk.Application):
|
||||||
self._info_dialog.set_application_name("CoverGrid")
|
self._info_dialog.set_application_name("CoverGrid")
|
||||||
self._info_dialog.set_version("3.2.1")
|
self._info_dialog.set_version("3.2.1")
|
||||||
self._info_dialog.set_comments(
|
self._info_dialog.set_comments(
|
||||||
"""CoverGrid is a client for the Music Player Daemon, focusing on
|
"""CoverGrid is a client for the Music Player Daemon, focusing on \
|
||||||
albums instead of single tracks.
|
albums instead of single tracks.""")
|
||||||
"""
|
|
||||||
)
|
|
||||||
self._info_dialog.set_website("https://www.suruatoel.xyz/codes/mcg")
|
self._info_dialog.set_website("https://www.suruatoel.xyz/codes/mcg")
|
||||||
self._info_dialog.set_license_type(Gtk.License.GPL_3_0)
|
self._info_dialog.set_license_type(Gtk.License.GPL_3_0)
|
||||||
self._info_dialog.set_issue_url(
|
self._info_dialog.set_issue_url(
|
||||||
"https://git.suruatoel.xyz/coderkun/mcg"
|
"https://git.suruatoel.xyz/coderkun/mcg")
|
||||||
)
|
|
||||||
self._info_dialog.present()
|
self._info_dialog.present()
|
||||||
|
|
||||||
def on_menu_quit(self, action, value):
|
def on_menu_quit(self, action, value):
|
||||||
self.quit()
|
self.quit()
|
||||||
|
|
||||||
def _setup_logging(self):
|
def _setup_logging(self):
|
||||||
logging.basicConfig(
|
logging.basicConfig(level=self._verbosity,
|
||||||
level=self._verbosity,
|
format="%(asctime)s %(levelname)s: %(message)s")
|
||||||
format="%(asctime)s %(levelname)s: %(message)s"
|
|
||||||
)
|
|
||||||
|
|
||||||
def _load_settings(self):
|
def _load_settings(self):
|
||||||
self._settings = Gio.Settings.new(Application.ID)
|
self._settings = Gio.Settings.new(Application.ID)
|
||||||
|
|
@ -87,10 +80,8 @@ class Application(Gtk.Application):
|
||||||
styleProvider = Gtk.CssProvider()
|
styleProvider = Gtk.CssProvider()
|
||||||
styleProvider.load_from_resource(self._get_resource_path('gtk.css'))
|
styleProvider.load_from_resource(self._get_resource_path('gtk.css'))
|
||||||
Gtk.StyleContext.add_provider_for_display(
|
Gtk.StyleContext.add_provider_for_display(
|
||||||
Gdk.Display.get_default(),
|
Gdk.Display.get_default(), styleProvider,
|
||||||
styleProvider,
|
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
|
||||||
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
|
|
||||||
)
|
|
||||||
|
|
||||||
def _setup_actions(self):
|
def _setup_actions(self):
|
||||||
action = Gio.SimpleAction.new("info", None)
|
action = Gio.SimpleAction.new("info", None)
|
||||||
|
|
|
||||||
152
src/client.py
152
src/client.py
|
|
@ -188,10 +188,8 @@ class Client(Base):
|
||||||
def get_output_devices(self):
|
def get_output_devices(self):
|
||||||
"""Determine the list of audio output devices."""
|
"""Determine the list of audio output devices."""
|
||||||
self._logger.info("get output devices")
|
self._logger.info("get output devices")
|
||||||
self._add_action_signal(
|
self._add_action_signal(Client.SIGNAL_LOAD_OUTPUT_DEVICES,
|
||||||
Client.SIGNAL_LOAD_OUTPUT_DEVICES,
|
self._get_output_devices)
|
||||||
self._get_output_devices
|
|
||||||
)
|
|
||||||
|
|
||||||
def enable_output_device(self, device, enabled):
|
def enable_output_device(self, device, enabled):
|
||||||
"""Enable/disable an audio output device."""
|
"""Enable/disable an audio output device."""
|
||||||
|
|
@ -208,10 +206,8 @@ class Client(Base):
|
||||||
|
|
||||||
def load_playlist(self):
|
def load_playlist(self):
|
||||||
self._logger.info("load playlist")
|
self._logger.info("load playlist")
|
||||||
self._add_action_signal(
|
self._add_action_signal(Client.SIGNAL_LOAD_PLAYLIST,
|
||||||
Client.SIGNAL_LOAD_PLAYLIST,
|
self._load_playlist)
|
||||||
self._load_playlist
|
|
||||||
)
|
|
||||||
|
|
||||||
def clear_playlist(self):
|
def clear_playlist(self):
|
||||||
"""Clear the current playlist"""
|
"""Clear the current playlist"""
|
||||||
|
|
@ -268,10 +264,8 @@ class Client(Base):
|
||||||
|
|
||||||
def get_albumart(self, album):
|
def get_albumart(self, album):
|
||||||
self._logger.info("get albumart")
|
self._logger.info("get albumart")
|
||||||
self._add_action_signal(
|
self._add_action_signal(Client.SIGNAL_LOAD_ALBUMART,
|
||||||
Client.SIGNAL_LOAD_ALBUMART,
|
self._get_albumart, album)
|
||||||
self._get_albumart, album
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_albumart_now(self, album):
|
def get_albumart_now(self, album):
|
||||||
self._logger.info("get albumart now")
|
self._logger.info("get albumart now")
|
||||||
|
|
@ -301,13 +295,8 @@ class Client(Base):
|
||||||
def _connect_socket(self, host, port):
|
def _connect_socket(self, host, port):
|
||||||
sock = None
|
sock = None
|
||||||
error = None
|
error = None
|
||||||
resources = socket.getaddrinfo(
|
resources = socket.getaddrinfo(host, port, socket.AF_UNSPEC,
|
||||||
host,
|
socket.SOCK_STREAM, socket.IPPROTO_TCP)
|
||||||
port,
|
|
||||||
socket.AF_UNSPEC,
|
|
||||||
socket.SOCK_STREAM,
|
|
||||||
socket.IPPROTO_TCP
|
|
||||||
)
|
|
||||||
for res in resources:
|
for res in resources:
|
||||||
af, socktype, proto, canonname, sa = res
|
af, socktype, proto, canonname, sa = res
|
||||||
try:
|
try:
|
||||||
|
|
@ -331,9 +320,8 @@ class Client(Base):
|
||||||
if not greeting.startswith(Client.PROTOCOL_GREETING):
|
if not greeting.startswith(Client.PROTOCOL_GREETING):
|
||||||
self._disconnect_socket()
|
self._disconnect_socket()
|
||||||
raise ProtocolException("invalid greeting: {}".format(greeting))
|
raise ProtocolException("invalid greeting: {}".format(greeting))
|
||||||
self._protocol_version = greeting[
|
self._protocol_version = greeting[len(Client.PROTOCOL_GREETING
|
||||||
len(Client.PROTOCOL_GREETING):
|
):].strip()
|
||||||
].strip()
|
|
||||||
self._logger.debug("protocol version: %s", self._protocol_version)
|
self._logger.debug("protocol version: %s", self._protocol_version)
|
||||||
|
|
||||||
def _disconnect(self):
|
def _disconnect(self):
|
||||||
|
|
@ -446,7 +434,7 @@ class Client(Base):
|
||||||
artists = 0
|
artists = 0
|
||||||
if 'artists' in stats:
|
if 'artists' in stats:
|
||||||
artists = int(stats['artists'])
|
artists = int(stats['artists'])
|
||||||
# Albums
|
# Albums
|
||||||
albums = 0
|
albums = 0
|
||||||
if 'albums' in stats:
|
if 'albums' in stats:
|
||||||
albums = int(stats['albums'])
|
albums = int(stats['albums'])
|
||||||
|
|
@ -497,12 +485,7 @@ class Client(Base):
|
||||||
self._logger.debug("album: %r", album)
|
self._logger.debug("album: %r", album)
|
||||||
# Tracks
|
# Tracks
|
||||||
songs = self._parse_list(
|
songs = self._parse_list(
|
||||||
self._call(
|
self._call('find album ', album.get_title()), ['file'])
|
||||||
'find album ',
|
|
||||||
album.get_title()
|
|
||||||
),
|
|
||||||
['file']
|
|
||||||
)
|
|
||||||
for song in songs:
|
for song in songs:
|
||||||
track = self._extract_track(song)
|
track = self._extract_track(song)
|
||||||
if track:
|
if track:
|
||||||
|
|
@ -515,12 +498,8 @@ class Client(Base):
|
||||||
|
|
||||||
def _load_playlist(self):
|
def _load_playlist(self):
|
||||||
self._playlist = []
|
self._playlist = []
|
||||||
songs = self._parse_list(
|
songs = self._parse_list(self._call('playlistinfo'),
|
||||||
self._call(
|
['file', 'playlist'])
|
||||||
'playlistinfo'
|
|
||||||
),
|
|
||||||
['file', 'playlist']
|
|
||||||
)
|
|
||||||
for song in songs:
|
for song in songs:
|
||||||
self._logger.debug("song: %r", song)
|
self._logger.debug("song: %r", song)
|
||||||
# Track
|
# Track
|
||||||
|
|
@ -528,13 +507,11 @@ class Client(Base):
|
||||||
self._logger.debug("track: %r", track)
|
self._logger.debug("track: %r", track)
|
||||||
# Album
|
# Album
|
||||||
album = self._extract_album(song, lookup=False)
|
album = self._extract_album(song, lookup=False)
|
||||||
if (
|
if (len(self._playlist) == 0
|
||||||
len(self._playlist) == 0
|
or self._playlist[len(self._playlist) - 1] != album):
|
||||||
or self._playlist[len(self._playlist)-1] != album
|
|
||||||
):
|
|
||||||
self._playlist.append(album)
|
self._playlist.append(album)
|
||||||
else:
|
else:
|
||||||
album = self._playlist[len(self._playlist)-1]
|
album = self._playlist[len(self._playlist) - 1]
|
||||||
self._logger.debug("album: %r", album)
|
self._logger.debug("album: %r", album)
|
||||||
if track:
|
if track:
|
||||||
album.add_track(track)
|
album.add_track(track)
|
||||||
|
|
@ -584,11 +561,7 @@ class Client(Base):
|
||||||
self._logger.info("addid: %r", track.get_file())
|
self._logger.info("addid: %r", track.get_file())
|
||||||
track_id = None
|
track_id = None
|
||||||
track_id_response = self._parse_dict(
|
track_id_response = self._parse_dict(
|
||||||
self._call(
|
self._call('addid', track.get_file()))
|
||||||
'addid',
|
|
||||||
track.get_file()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
if 'id' in track_id_response:
|
if 'id' in track_id_response:
|
||||||
track_id = track_id_response['id']
|
track_id = track_id_response['id']
|
||||||
self._logger.debug("track id: %r", track_id)
|
self._logger.debug("track id: %r", track_id)
|
||||||
|
|
@ -613,33 +586,24 @@ class Client(Base):
|
||||||
def _get_albumart(self, album):
|
def _get_albumart(self, album):
|
||||||
if album in self._albums:
|
if album in self._albums:
|
||||||
album = self._albums[album]
|
album = self._albums[album]
|
||||||
self._logger.debug(
|
self._logger.debug("get albumart for album \"%s\"",
|
||||||
"get albumart for album \"%s\"",
|
album.get_title())
|
||||||
album.get_title()
|
|
||||||
)
|
|
||||||
|
|
||||||
# Use "albumart" command
|
# Use "albumart" command
|
||||||
if album.get_tracks():
|
if album.get_tracks():
|
||||||
try:
|
try:
|
||||||
return (
|
return (album,
|
||||||
album,
|
self._read_binary('albumart',
|
||||||
self._read_binary(
|
album.get_tracks()[0].get_file(),
|
||||||
'albumart',
|
False))
|
||||||
album.get_tracks()[0].get_file(),
|
|
||||||
False
|
|
||||||
)
|
|
||||||
)
|
|
||||||
except CommandException as e:
|
except CommandException as e:
|
||||||
# The "albumart" command throws an exception if not found
|
# The "albumart" command throws an exception if not found
|
||||||
if e.get_error_number() != Client.PROTOCOL_ERROR_NOEXISTS:
|
if e.get_error_number() != Client.PROTOCOL_ERROR_NOEXISTS:
|
||||||
raise e
|
raise e
|
||||||
# If no albumart can be found, use "readpicture" command
|
# If no albumart can be found, use "readpicture" command
|
||||||
for track in album.get_tracks():
|
for track in album.get_tracks():
|
||||||
data = self._read_binary(
|
data = self._read_binary('readpicture',
|
||||||
'readpicture',
|
track.get_file(), True)
|
||||||
track.get_file(),
|
|
||||||
True
|
|
||||||
)
|
|
||||||
if data:
|
if data:
|
||||||
return (album, data)
|
return (album, data)
|
||||||
|
|
||||||
|
|
@ -648,11 +612,9 @@ class Client(Base):
|
||||||
def _start_worker(self):
|
def _start_worker(self):
|
||||||
"""Start the worker thread which waits for action to be performed."""
|
"""Start the worker thread which waits for action to be performed."""
|
||||||
self._logger.debug("start worker")
|
self._logger.debug("start worker")
|
||||||
self._worker = threading.Thread(
|
self._worker = threading.Thread(target=self._run,
|
||||||
target=self._run,
|
name='mcg-worker',
|
||||||
name='mcg-worker',
|
args=())
|
||||||
args=()
|
|
||||||
)
|
|
||||||
self._worker.setDaemon(True)
|
self._worker.setDaemon(True)
|
||||||
self._worker.start()
|
self._worker.start()
|
||||||
self._logger.debug("worker started")
|
self._logger.debug("worker started")
|
||||||
|
|
@ -680,12 +642,8 @@ class Client(Base):
|
||||||
|
|
||||||
def _add_action_signal(self, signal, method, *args):
|
def _add_action_signal(self, signal, method, *args):
|
||||||
"""Add an action to the action list that triggers a callback."""
|
"""Add an action to the action list that triggers a callback."""
|
||||||
self._logger.debug(
|
self._logger.debug("add action signal %r: %r (%r)", signal,
|
||||||
"add action signal %r: %r (%r)",
|
method.__name__, args)
|
||||||
signal,
|
|
||||||
method.__name__,
|
|
||||||
args
|
|
||||||
)
|
|
||||||
future = Future(signal)
|
future = Future(signal)
|
||||||
future.add_done_callback(self._callback_future)
|
future.add_done_callback(self._callback_future)
|
||||||
self._add_action_future(future, method, *args)
|
self._add_action_future(future, method, *args)
|
||||||
|
|
@ -741,11 +699,7 @@ class Client(Base):
|
||||||
def _write(self, command, args=None):
|
def _write(self, command, args=None):
|
||||||
if args is not None and len(args) > 0:
|
if args is not None and len(args) > 0:
|
||||||
line = '{} "{}"\n'.format(
|
line = '{} "{}"\n'.format(
|
||||||
command,
|
command, '" "'.join(str(x).replace('"', '\\\"') for x in args))
|
||||||
'" "'.join(
|
|
||||||
str(x).replace('"', '\\\"') for x in args
|
|
||||||
)
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
line = '{}\n'.format(command)
|
line = '{}\n'.format(command)
|
||||||
self._logger.debug("write: %r", line)
|
self._logger.debug("write: %r", line)
|
||||||
|
|
@ -828,7 +782,7 @@ class Client(Base):
|
||||||
if not data:
|
if not data:
|
||||||
data = bytearray(size)
|
data = bytearray(size)
|
||||||
# Create a view for the current chunk of data
|
# Create a view for the current chunk of data
|
||||||
data_view = memoryview(data)[offset:offset+binary]
|
data_view = memoryview(data)[offset:offset + binary]
|
||||||
# Read actual bytes
|
# Read actual bytes
|
||||||
self._read_bytes(data_view, binary)
|
self._read_bytes(data_view, binary)
|
||||||
offset += binary
|
offset += binary
|
||||||
|
|
@ -858,9 +812,9 @@ class Client(Base):
|
||||||
def _buffer_get_char(self, char):
|
def _buffer_get_char(self, char):
|
||||||
pos = self._buffer.find(char)
|
pos = self._buffer.find(char)
|
||||||
if pos < 0:
|
if pos < 0:
|
||||||
pos = len(self._buffer)-1
|
pos = len(self._buffer) - 1
|
||||||
buf = self._buffer[0:pos+1]
|
buf = self._buffer[0:pos + 1]
|
||||||
self._buffer = self._buffer[pos+1:]
|
self._buffer = self._buffer[pos + 1:]
|
||||||
return buf
|
return buf
|
||||||
|
|
||||||
def _buffer_get_size(self, size):
|
def _buffer_get_size(self, size):
|
||||||
|
|
@ -994,8 +948,7 @@ class MCGAlbum:
|
||||||
def get_artists(self):
|
def get_artists(self):
|
||||||
if self._albumartists:
|
if self._albumartists:
|
||||||
return [
|
return [
|
||||||
artist
|
artist for artist in self._artists
|
||||||
for artist in self._artists
|
|
||||||
if artist not in self._albumartists
|
if artist not in self._albumartists
|
||||||
]
|
]
|
||||||
return self._artists
|
return self._artists
|
||||||
|
|
@ -1138,8 +1091,7 @@ class MCGTrack:
|
||||||
def get_artists(self):
|
def get_artists(self):
|
||||||
if self._albumartists:
|
if self._albumartists:
|
||||||
return [
|
return [
|
||||||
artist
|
artist for artist in self._artists
|
||||||
for artist in self._artists
|
|
||||||
if artist not in self._albumartists
|
if artist not in self._albumartists
|
||||||
]
|
]
|
||||||
return self._artists
|
return self._artists
|
||||||
|
|
@ -1164,7 +1116,7 @@ class MCGTrack:
|
||||||
if type(track) is list:
|
if type(track) is list:
|
||||||
track = track[0]
|
track = track[0]
|
||||||
if type(track) is str and '/' in track:
|
if type(track) is str and '/' in track:
|
||||||
track = track[0: track.index('/')]
|
track = track[0:track.index('/')]
|
||||||
if track is not None:
|
if track is not None:
|
||||||
try:
|
try:
|
||||||
track = int(track)
|
track = int(track)
|
||||||
|
|
@ -1201,13 +1153,10 @@ class MCGTrack:
|
||||||
|
|
||||||
|
|
||||||
class MCGPlaylistTrack(MCGTrack):
|
class MCGPlaylistTrack(MCGTrack):
|
||||||
|
|
||||||
def __init__(self, track, id, pos):
|
def __init__(self, track, id, pos):
|
||||||
MCGTrack.__init__(
|
MCGTrack.__init__(self, track.get_artists(), track.get_title(),
|
||||||
self,
|
track.get_file())
|
||||||
track.get_artists(),
|
|
||||||
track.get_title(),
|
|
||||||
track.get_file()
|
|
||||||
)
|
|
||||||
self.set_albumartists(track.get_albumartists())
|
self.set_albumartists(track.get_albumartists())
|
||||||
self.set_track(track.get_track())
|
self.set_track(track.get_track())
|
||||||
self.set_length(track.get_length())
|
self.set_length(track.get_length())
|
||||||
|
|
@ -1228,11 +1177,7 @@ class MCGConfig(configparser.ConfigParser):
|
||||||
def __init__(self, filename):
|
def __init__(self, filename):
|
||||||
configparser.ConfigParser.__init__(self)
|
configparser.ConfigParser.__init__(self)
|
||||||
self._filename = os.path.expanduser(
|
self._filename = os.path.expanduser(
|
||||||
os.path.join(
|
os.path.join(MCGConfig.CONFIG_DIR, filename))
|
||||||
MCGConfig.CONFIG_DIR,
|
|
||||||
filename
|
|
||||||
)
|
|
||||||
)
|
|
||||||
self._create_dir()
|
self._create_dir()
|
||||||
|
|
||||||
def load(self):
|
def load(self):
|
||||||
|
|
@ -1258,12 +1203,8 @@ class MCGCache():
|
||||||
self._logger = logging.getLogger(__name__)
|
self._logger = logging.getLogger(__name__)
|
||||||
self._host = host
|
self._host = host
|
||||||
self._size = size
|
self._size = size
|
||||||
self._dirname = os.path.expanduser(
|
self._dirname = os.path.expanduser(os.path.join(
|
||||||
os.path.join(
|
MCGCache.DIRNAME, host))
|
||||||
MCGCache.DIRNAME,
|
|
||||||
host
|
|
||||||
)
|
|
||||||
)
|
|
||||||
if not os.path.exists(self._dirname):
|
if not os.path.exists(self._dirname):
|
||||||
os.makedirs(self._dirname)
|
os.makedirs(self._dirname)
|
||||||
self._read_size()
|
self._read_size()
|
||||||
|
|
@ -1284,8 +1225,7 @@ class MCGCache():
|
||||||
self._logger.warning(
|
self._logger.warning(
|
||||||
"invalid cache file: %s, deleting file",
|
"invalid cache file: %s, deleting file",
|
||||||
filename,
|
filename,
|
||||||
exc_info=True
|
exc_info=True)
|
||||||
)
|
|
||||||
size = None
|
size = None
|
||||||
# Clear cache if size has changed
|
# Clear cache if size has changed
|
||||||
if size != self._size:
|
if size != self._size:
|
||||||
|
|
|
||||||
|
|
@ -31,9 +31,7 @@ class ConnectionPanel(Adw.Bin):
|
||||||
# Zeroconf provider
|
# Zeroconf provider
|
||||||
self._zeroconf_provider = ZeroconfProvider()
|
self._zeroconf_provider = ZeroconfProvider()
|
||||||
self._zeroconf_provider.connect_signal(
|
self._zeroconf_provider.connect_signal(
|
||||||
ZeroconfProvider.SIGNAL_SERVICE_NEW,
|
ZeroconfProvider.SIGNAL_SERVICE_NEW, self.on_new_service)
|
||||||
self.on_new_service
|
|
||||||
)
|
|
||||||
|
|
||||||
def on_new_service(self, service):
|
def on_new_service(self, service):
|
||||||
name, host, port = service
|
name, host, port = service
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,8 @@ class CoverPanel(Gtk.Overlay):
|
||||||
__gtype_name__ = 'McgCoverPanel'
|
__gtype_name__ = 'McgCoverPanel'
|
||||||
__gsignals__ = {
|
__gsignals__ = {
|
||||||
'toggle-fullscreen': (GObject.SIGNAL_RUN_FIRST, None, ()),
|
'toggle-fullscreen': (GObject.SIGNAL_RUN_FIRST, None, ()),
|
||||||
'set-song': (GObject.SIGNAL_RUN_FIRST, None, (int, int,)),
|
'set-song': (GObject.SIGNAL_RUN_FIRST, None, (int, int, )),
|
||||||
'albumart': (GObject.SIGNAL_RUN_FIRST, None, (str,))
|
'albumart': (GObject.SIGNAL_RUN_FIRST, None, (str, ))
|
||||||
}
|
}
|
||||||
|
|
||||||
# Widgets
|
# Widgets
|
||||||
|
|
@ -48,8 +48,7 @@ class CoverPanel(Gtk.Overlay):
|
||||||
self._timer = None
|
self._timer = None
|
||||||
self._properties = {}
|
self._properties = {}
|
||||||
self._icon_theme = Gtk.IconTheme.get_for_display(
|
self._icon_theme = Gtk.IconTheme.get_for_display(
|
||||||
Gdk.Display.get_default()
|
Gdk.Display.get_default())
|
||||||
)
|
|
||||||
self._fullscreened = False
|
self._fullscreened = False
|
||||||
self._current_size = None
|
self._current_size = None
|
||||||
|
|
||||||
|
|
@ -64,10 +63,8 @@ class CoverPanel(Gtk.Overlay):
|
||||||
# Button controller for songs scale
|
# Button controller for songs scale
|
||||||
buttonController = Gtk.GestureClick()
|
buttonController = Gtk.GestureClick()
|
||||||
buttonController.connect('pressed', self.on_songs_scale_pressed)
|
buttonController.connect('pressed', self.on_songs_scale_pressed)
|
||||||
buttonController.connect(
|
buttonController.connect('unpaired-release',
|
||||||
'unpaired-release',
|
self.on_songs_scale_released)
|
||||||
self.on_songs_scale_released
|
|
||||||
)
|
|
||||||
self.songs_scale.add_controller(buttonController)
|
self.songs_scale.add_controller(buttonController)
|
||||||
|
|
||||||
def get_toolbar(self):
|
def get_toolbar(self):
|
||||||
|
|
@ -94,7 +91,7 @@ class CoverPanel(Gtk.Overlay):
|
||||||
time = self._current_album.get_length()
|
time = self._current_album.get_length()
|
||||||
tracks = self._current_album.get_tracks()
|
tracks = self._current_album.get_tracks()
|
||||||
pos = 0
|
pos = 0
|
||||||
for index in range(len(tracks)-1, -1, -1):
|
for index in range(len(tracks) - 1, -1, -1):
|
||||||
time = time - tracks[index].get_length()
|
time = time - tracks[index].get_length()
|
||||||
pos = tracks[index].get_pos()
|
pos = tracks[index].get_pos()
|
||||||
if time < value:
|
if time < value:
|
||||||
|
|
@ -107,11 +104,8 @@ class CoverPanel(Gtk.Overlay):
|
||||||
# Set labels
|
# Set labels
|
||||||
self.album_title_label.set_label(album.get_title())
|
self.album_title_label.set_label(album.get_title())
|
||||||
self.album_date_label.set_label(', '.join(album.get_dates()))
|
self.album_date_label.set_label(', '.join(album.get_dates()))
|
||||||
self.album_artist_label.set_label(
|
self.album_artist_label.set_label(', '.join(
|
||||||
', '.join(
|
album.get_albumartists()))
|
||||||
album.get_albumartists()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Set tracks
|
# Set tracks
|
||||||
self._set_tracks(album)
|
self._set_tracks(album)
|
||||||
|
|
@ -135,7 +129,7 @@ class CoverPanel(Gtk.Overlay):
|
||||||
for index in range(0, pos):
|
for index in range(0, pos):
|
||||||
time = time + tracks[index].get_length()
|
time = time + tracks[index].get_length()
|
||||||
|
|
||||||
self.songs_scale.set_value(time+1)
|
self.songs_scale.set_value(time + 1)
|
||||||
self._timer = GObject.timeout_add(1000, self._playing)
|
self._timer = GObject.timeout_add(1000, self._playing)
|
||||||
|
|
||||||
def set_pause(self):
|
def set_pause(self):
|
||||||
|
|
@ -180,18 +174,12 @@ class CoverPanel(Gtk.Overlay):
|
||||||
if length > 0 and length < album.get_length():
|
if length > 0 and length < album.get_length():
|
||||||
cur_length = cur_length + 1
|
cur_length = cur_length + 1
|
||||||
self.songs_scale.add_mark(
|
self.songs_scale.add_mark(
|
||||||
cur_length,
|
cur_length, Gtk.PositionType.RIGHT,
|
||||||
Gtk.PositionType.RIGHT,
|
GObject.markup_escape_text(Utils.create_track_title(track)))
|
||||||
GObject.markup_escape_text(
|
|
||||||
Utils.create_track_title(track)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
length = length + track.get_length()
|
length = length + track.get_length()
|
||||||
self.songs_scale.add_mark(
|
self.songs_scale.add_mark(
|
||||||
length,
|
length, Gtk.PositionType.RIGHT,
|
||||||
Gtk.PositionType.RIGHT,
|
"{0[0]:02d}:{0[1]:02d} minutes".format(divmod(length, 60)))
|
||||||
"{0[0]:02d}:{0[1]:02d} minutes".format(divmod(length, 60))
|
|
||||||
)
|
|
||||||
|
|
||||||
def _enable_tracklist(self):
|
def _enable_tracklist(self):
|
||||||
if self._current_album:
|
if self._current_album:
|
||||||
|
|
@ -228,7 +216,10 @@ class CoverPanel(Gtk.Overlay):
|
||||||
current_width, current_height = self._current_size
|
current_width, current_height = self._current_size
|
||||||
if size_width == current_width and size_height == current_height:
|
if size_width == current_width and size_height == current_height:
|
||||||
return
|
return
|
||||||
self._current_size = (size_width, size_height,)
|
self._current_size = (
|
||||||
|
size_width,
|
||||||
|
size_height,
|
||||||
|
)
|
||||||
|
|
||||||
# Get pixelbuffer
|
# Get pixelbuffer
|
||||||
pixbuf = self._cover_pixbuf
|
pixbuf = self._cover_pixbuf
|
||||||
|
|
@ -243,15 +234,10 @@ class CoverPanel(Gtk.Overlay):
|
||||||
ratio = min(ratioW, ratioH)
|
ratio = min(ratioW, ratioH)
|
||||||
ratio = min(ratio, 1)
|
ratio = min(ratio, 1)
|
||||||
# Neue Breite und Höhe berechnen
|
# Neue Breite und Höhe berechnen
|
||||||
width = int(math.floor(pixbuf.get_width()*ratio))
|
width = int(math.floor(pixbuf.get_width() * ratio))
|
||||||
height = int(math.floor(pixbuf.get_height()*ratio))
|
height = int(math.floor(pixbuf.get_height() * ratio))
|
||||||
if width <= 0 or height <= 0:
|
if width <= 0 or height <= 0:
|
||||||
return
|
return
|
||||||
self.cover_image.set_from_pixbuf(
|
self.cover_image.set_from_pixbuf(
|
||||||
pixbuf.scale_simple(
|
pixbuf.scale_simple(width, height, GdkPixbuf.InterpType.HYPER))
|
||||||
width,
|
|
||||||
height,
|
|
||||||
GdkPixbuf.InterpType.HYPER
|
|
||||||
)
|
|
||||||
)
|
|
||||||
self.cover_image.show()
|
self.cover_image.show()
|
||||||
|
|
|
||||||
|
|
@ -25,15 +25,14 @@ class LibraryPanel(Adw.Bin):
|
||||||
'open-standalone': (GObject.SIGNAL_RUN_FIRST, None, ()),
|
'open-standalone': (GObject.SIGNAL_RUN_FIRST, None, ()),
|
||||||
'close-standalone': (GObject.SIGNAL_RUN_FIRST, None, ()),
|
'close-standalone': (GObject.SIGNAL_RUN_FIRST, None, ()),
|
||||||
'update': (GObject.SIGNAL_RUN_FIRST, None, ()),
|
'update': (GObject.SIGNAL_RUN_FIRST, None, ()),
|
||||||
'play': (GObject.SIGNAL_RUN_FIRST, None, (str,)),
|
'play': (GObject.SIGNAL_RUN_FIRST, None, (str, )),
|
||||||
'queue': (GObject.SIGNAL_RUN_FIRST, None, (str,)),
|
'queue': (GObject.SIGNAL_RUN_FIRST, None, (str, )),
|
||||||
'queue-multiple': (
|
'queue-multiple':
|
||||||
GObject.SIGNAL_RUN_FIRST, None, (GObject.TYPE_PYOBJECT,)
|
(GObject.SIGNAL_RUN_FIRST, None, (GObject.TYPE_PYOBJECT, )),
|
||||||
),
|
'item-size-changed': (GObject.SIGNAL_RUN_FIRST, None, (int, )),
|
||||||
'item-size-changed': (GObject.SIGNAL_RUN_FIRST, None, (int,)),
|
'sort-order-changed': (GObject.SIGNAL_RUN_FIRST, None, (int, )),
|
||||||
'sort-order-changed': (GObject.SIGNAL_RUN_FIRST, None, (int,)),
|
'sort-type-changed': (GObject.SIGNAL_RUN_FIRST, None, (bool, )),
|
||||||
'sort-type-changed': (GObject.SIGNAL_RUN_FIRST, None, (bool,)),
|
'albumart': (GObject.SIGNAL_RUN_FIRST, None, (str, )),
|
||||||
'albumart': (GObject.SIGNAL_RUN_FIRST, None, (str,)),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Widgets
|
# Widgets
|
||||||
|
|
@ -88,8 +87,7 @@ class LibraryPanel(Adw.Bin):
|
||||||
self._library_lock = threading.Lock()
|
self._library_lock = threading.Lock()
|
||||||
self._library_stop = threading.Event()
|
self._library_stop = threading.Event()
|
||||||
self._icon_theme = Gtk.IconTheme.get_for_display(
|
self._icon_theme = Gtk.IconTheme.get_for_display(
|
||||||
Gdk.Display.get_default()
|
Gdk.Display.get_default())
|
||||||
)
|
|
||||||
self._standalone_pixbuf = None
|
self._standalone_pixbuf = None
|
||||||
self._selected_albums = []
|
self._selected_albums = []
|
||||||
self._is_selected = False
|
self._is_selected = False
|
||||||
|
|
@ -97,20 +95,16 @@ class LibraryPanel(Adw.Bin):
|
||||||
# Widgets
|
# Widgets
|
||||||
# Header bar
|
# Header bar
|
||||||
self._headerbar_standalone = AlbumHeaderbar()
|
self._headerbar_standalone = AlbumHeaderbar()
|
||||||
self._headerbar_standalone.connect(
|
self._headerbar_standalone.connect('close',
|
||||||
'close',
|
self.on_standalone_close_clicked)
|
||||||
self.on_standalone_close_clicked
|
|
||||||
)
|
|
||||||
# Library Grid: Model
|
# Library Grid: Model
|
||||||
self._library_grid_model = Gio.ListStore()
|
self._library_grid_model = Gio.ListStore()
|
||||||
self._library_grid_filter = Gtk.FilterListModel()
|
self._library_grid_filter = Gtk.FilterListModel()
|
||||||
self._library_grid_filter.set_model(self._library_grid_model)
|
self._library_grid_filter.set_model(self._library_grid_model)
|
||||||
self._library_grid_selection_multi = Gtk.MultiSelection.new(
|
self._library_grid_selection_multi = Gtk.MultiSelection.new(
|
||||||
self._library_grid_filter
|
self._library_grid_filter)
|
||||||
)
|
|
||||||
self._library_grid_selection_single = Gtk.SingleSelection.new(
|
self._library_grid_selection_single = Gtk.SingleSelection.new(
|
||||||
self._library_grid_filter
|
self._library_grid_filter)
|
||||||
)
|
|
||||||
# Library Grid
|
# Library Grid
|
||||||
self.library_grid.set_model(self._library_grid_selection_single)
|
self.library_grid.set_model(self._library_grid_selection_single)
|
||||||
# Toolbar menu
|
# Toolbar menu
|
||||||
|
|
@ -124,10 +118,8 @@ class LibraryPanel(Adw.Bin):
|
||||||
|
|
||||||
# Button controller for grid scale
|
# Button controller for grid scale
|
||||||
buttonController = Gtk.GestureClick()
|
buttonController = Gtk.GestureClick()
|
||||||
buttonController.connect(
|
buttonController.connect('unpaired-release',
|
||||||
'unpaired-release',
|
self.on_grid_scale_released)
|
||||||
self.on_grid_scale_released
|
|
||||||
)
|
|
||||||
self.grid_scale.add_controller(buttonController)
|
self.grid_scale.add_controller(buttonController)
|
||||||
|
|
||||||
def get_headerbar_standalone(self):
|
def get_headerbar_standalone(self):
|
||||||
|
|
@ -146,15 +138,13 @@ class LibraryPanel(Adw.Bin):
|
||||||
self.library_grid.set_model(self._library_grid_selection_multi)
|
self.library_grid.set_model(self._library_grid_selection_multi)
|
||||||
self.library_grid.set_single_click_activate(False)
|
self.library_grid.set_single_click_activate(False)
|
||||||
self.library_grid.get_style_context().add_class(
|
self.library_grid.get_style_context().add_class(
|
||||||
Utils.CSS_SELECTION
|
Utils.CSS_SELECTION)
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
self.actionbar_revealer.set_reveal_child(False)
|
self.actionbar_revealer.set_reveal_child(False)
|
||||||
self.library_grid.set_model(self._library_grid_selection_single)
|
self.library_grid.set_model(self._library_grid_selection_single)
|
||||||
self.library_grid.set_single_click_activate(True)
|
self.library_grid.set_single_click_activate(True)
|
||||||
self.library_grid.get_style_context().remove_class(
|
self.library_grid.get_style_context().remove_class(
|
||||||
Utils.CSS_SELECTION
|
Utils.CSS_SELECTION)
|
||||||
)
|
|
||||||
|
|
||||||
@Gtk.Template.Callback()
|
@Gtk.Template.Callback()
|
||||||
def on_update_clicked(self, widget):
|
def on_update_clicked(self, widget):
|
||||||
|
|
@ -182,8 +172,7 @@ class LibraryPanel(Adw.Bin):
|
||||||
def on_sort_toggled(self, widget):
|
def on_sort_toggled(self, widget):
|
||||||
if widget.get_active():
|
if widget.get_active():
|
||||||
self._sort_order = [
|
self._sort_order = [
|
||||||
key
|
key for key, value in self._toolbar_sort_buttons.items()
|
||||||
for key, value in self._toolbar_sort_buttons.items()
|
|
||||||
if value is widget
|
if value is widget
|
||||||
][0]
|
][0]
|
||||||
self._sort_grid_model()
|
self._sort_grid_model()
|
||||||
|
|
@ -205,10 +194,7 @@ class LibraryPanel(Adw.Bin):
|
||||||
@Gtk.Template.Callback()
|
@Gtk.Template.Callback()
|
||||||
def on_filter_entry_changed(self, widget):
|
def on_filter_entry_changed(self, widget):
|
||||||
self._library_grid_filter.set_filter(
|
self._library_grid_filter.set_filter(
|
||||||
SearchFilter(
|
SearchFilter(self.filter_entry.get_text()))
|
||||||
self.filter_entry.get_text()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
@Gtk.Template.Callback()
|
@Gtk.Template.Callback()
|
||||||
def on_library_grid_clicked(self, widget, position):
|
def on_library_grid_clicked(self, widget, position):
|
||||||
|
|
@ -269,8 +255,7 @@ class LibraryPanel(Adw.Bin):
|
||||||
button = self._toolbar_sort_buttons[sort]
|
button = self._toolbar_sort_buttons[sort]
|
||||||
if button:
|
if button:
|
||||||
self._sort_order = [
|
self._sort_order = [
|
||||||
key
|
key for key, value in self._toolbar_sort_buttons.items()
|
||||||
for key, value in self._toolbar_sort_buttons.items()
|
|
||||||
if value is button
|
if value is button
|
||||||
][0]
|
][0]
|
||||||
if not button.get_active():
|
if not button.get_active():
|
||||||
|
|
@ -300,10 +285,12 @@ class LibraryPanel(Adw.Bin):
|
||||||
def set_albums(self, host, albums):
|
def set_albums(self, host, albums):
|
||||||
self._host = host
|
self._host = host
|
||||||
self._library_stop.set()
|
self._library_stop.set()
|
||||||
threading.Thread(
|
threading.Thread(target=self._set_albums,
|
||||||
target=self._set_albums,
|
args=(
|
||||||
args=(host, albums, self._item_size,)
|
host,
|
||||||
).start()
|
albums,
|
||||||
|
self._item_size,
|
||||||
|
)).start()
|
||||||
|
|
||||||
def set_albumart(self, album, data):
|
def set_albumart(self, album, data):
|
||||||
if album in self._selected_albums:
|
if album in self._selected_albums:
|
||||||
|
|
@ -320,20 +307,14 @@ class LibraryPanel(Adw.Bin):
|
||||||
GObject.idle_add(self._show_image)
|
GObject.idle_add(self._show_image)
|
||||||
|
|
||||||
def _sort_grid_model(self):
|
def _sort_grid_model(self):
|
||||||
GObject.idle_add(
|
GObject.idle_add(self._library_grid_model.sort,
|
||||||
self._library_grid_model.sort,
|
self._grid_model_compare_func, self._sort_order,
|
||||||
self._grid_model_compare_func,
|
self._sort_type)
|
||||||
self._sort_order,
|
|
||||||
self._sort_type
|
|
||||||
)
|
|
||||||
|
|
||||||
def _grid_model_compare_func(self, item1, item2, criterion, order):
|
def _grid_model_compare_func(self, item1, item2, criterion, order):
|
||||||
return client.MCGAlbum.compare(
|
return client.MCGAlbum.compare(item1.get_album(), item2.get_album(),
|
||||||
item1.get_album(),
|
criterion,
|
||||||
item2.get_album(),
|
(order == Gtk.SortType.DESCENDING))
|
||||||
criterion,
|
|
||||||
(order == Gtk.SortType.DESCENDING)
|
|
||||||
)
|
|
||||||
|
|
||||||
def stop_threads(self):
|
def stop_threads(self):
|
||||||
self._library_stop.set()
|
self._library_stop.set()
|
||||||
|
|
@ -342,10 +323,8 @@ class LibraryPanel(Adw.Bin):
|
||||||
self._library_lock.acquire()
|
self._library_lock.acquire()
|
||||||
self._albums = albums
|
self._albums = albums
|
||||||
stack_transition_type = self.stack.get_transition_type()
|
stack_transition_type = self.stack.get_transition_type()
|
||||||
GObject.idle_add(
|
GObject.idle_add(self.stack.set_transition_type,
|
||||||
self.stack.set_transition_type,
|
Gtk.StackTransitionType.NONE)
|
||||||
Gtk.StackTransitionType.NONE
|
|
||||||
)
|
|
||||||
GObject.idle_add(self.stack.set_visible_child, self.progress_box)
|
GObject.idle_add(self.stack.set_visible_child, self.progress_box)
|
||||||
GObject.idle_add(self.progress_bar.set_fraction, 0.0)
|
GObject.idle_add(self.progress_bar.set_fraction, 0.0)
|
||||||
GObject.idle_add(self.stack.set_transition_type, stack_transition_type)
|
GObject.idle_add(self.stack.set_transition_type, stack_transition_type)
|
||||||
|
|
@ -367,26 +346,18 @@ class LibraryPanel(Adw.Bin):
|
||||||
self._logger.exception("Failed to load albumart", e)
|
self._logger.exception("Failed to load albumart", e)
|
||||||
if pixbuf is None:
|
if pixbuf is None:
|
||||||
pixbuf = self._icon_theme.lookup_icon(
|
pixbuf = self._icon_theme.lookup_icon(
|
||||||
Utils.STOCK_ICON_DEFAULT,
|
Utils.STOCK_ICON_DEFAULT, None, self._item_size,
|
||||||
None,
|
self._item_size, Gtk.TextDirection.LTR,
|
||||||
self._item_size,
|
Gtk.IconLookupFlags.FORCE_SYMBOLIC)
|
||||||
self._item_size,
|
|
||||||
Gtk.TextDirection.LTR,
|
|
||||||
Gtk.IconLookupFlags.FORCE_SYMBOLIC
|
|
||||||
)
|
|
||||||
if pixbuf is not None:
|
if pixbuf is not None:
|
||||||
self._grid_pixbufs[album.get_id()] = pixbuf
|
self._grid_pixbufs[album.get_id()] = pixbuf
|
||||||
GObject.idle_add(
|
GObject.idle_add(self._library_grid_model.append,
|
||||||
self._library_grid_model.append,
|
GridItem(album, pixbuf))
|
||||||
GridItem(album, pixbuf)
|
|
||||||
)
|
|
||||||
|
|
||||||
i += 1
|
i += 1
|
||||||
GObject.idle_add(self.progress_bar.set_fraction, i/n)
|
GObject.idle_add(self.progress_bar.set_fraction, i / n)
|
||||||
GObject.idle_add(
|
GObject.idle_add(self.progress_bar.set_text,
|
||||||
self.progress_bar.set_text,
|
locale.gettext("Loading images"))
|
||||||
locale.gettext("Loading images")
|
|
||||||
)
|
|
||||||
|
|
||||||
self._library_lock.release()
|
self._library_lock.release()
|
||||||
GObject.idle_add(self.stack.set_visible_child, self.scroll)
|
GObject.idle_add(self.stack.set_visible_child, self.scroll)
|
||||||
|
|
@ -394,10 +365,12 @@ class LibraryPanel(Adw.Bin):
|
||||||
|
|
||||||
def _set_widget_grid_size(self, grid_widget, size, vertical):
|
def _set_widget_grid_size(self, grid_widget, size, vertical):
|
||||||
self._library_stop.set()
|
self._library_stop.set()
|
||||||
threading.Thread(
|
threading.Thread(target=self._set_widget_grid_size_thread,
|
||||||
target=self._set_widget_grid_size_thread,
|
args=(
|
||||||
args=(grid_widget, size, vertical,)
|
grid_widget,
|
||||||
).start()
|
size,
|
||||||
|
vertical,
|
||||||
|
)).start()
|
||||||
|
|
||||||
def _set_widget_grid_size_thread(self, grid_widget, size, vertical):
|
def _set_widget_grid_size_thread(self, grid_widget, size, vertical):
|
||||||
self._library_lock.acquire()
|
self._library_lock.acquire()
|
||||||
|
|
@ -411,20 +384,12 @@ class LibraryPanel(Adw.Bin):
|
||||||
|
|
||||||
pixbuf = self._grid_pixbufs[album_id]
|
pixbuf = self._grid_pixbufs[album_id]
|
||||||
if pixbuf is not None:
|
if pixbuf is not None:
|
||||||
pixbuf = pixbuf.scale_simple(
|
pixbuf = pixbuf.scale_simple(size, size,
|
||||||
size,
|
GdkPixbuf.InterpType.NEAREST)
|
||||||
size,
|
|
||||||
GdkPixbuf.InterpType.NEAREST
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
pixbuf = self._icon_theme.lookup_icon(
|
pixbuf = self._icon_theme.lookup_icon(
|
||||||
Utils.STOCK_ICON_DEFAULT,
|
Utils.STOCK_ICON_DEFAULT, None, size, size,
|
||||||
None,
|
Gtk.TextDirection.LTR, Gtk.IconLookupFlags.FORCE_SYMBOLIC)
|
||||||
size,
|
|
||||||
size,
|
|
||||||
Gtk.TextDirection.LTR,
|
|
||||||
Gtk.IconLookupFlags.FORCE_SYMBOLIC
|
|
||||||
)
|
|
||||||
GObject.idle_add(grid_item.set_cover, pixbuf)
|
GObject.idle_add(grid_item.set_cover, pixbuf)
|
||||||
|
|
||||||
if self._library_stop.is_set():
|
if self._library_stop.is_set():
|
||||||
|
|
@ -456,11 +421,7 @@ class LibraryPanel(Adw.Bin):
|
||||||
for index in range(countMin, countMax):
|
for index in range(countMin, countMax):
|
||||||
pixel = int(width / index)
|
pixel = int(width / index)
|
||||||
pixel = pixel - (2 * int(pixel / 100))
|
pixel = pixel - (2 * int(pixel / 100))
|
||||||
self.grid_scale.add_mark(
|
self.grid_scale.add_mark(pixel, Gtk.PositionType.BOTTOM, None)
|
||||||
pixel,
|
|
||||||
Gtk.PositionType.BOTTOM,
|
|
||||||
None
|
|
||||||
)
|
|
||||||
|
|
||||||
def _open_standalone(self):
|
def _open_standalone(self):
|
||||||
self.library_stack.set_visible_child(self.panel_standalone)
|
self.library_stack.set_visible_child(self.panel_standalone)
|
||||||
|
|
@ -491,38 +452,24 @@ class LibraryPanel(Adw.Bin):
|
||||||
ratio = min(ratioW, ratioH)
|
ratio = min(ratioW, ratioH)
|
||||||
ratio = min(ratio, 1)
|
ratio = min(ratio, 1)
|
||||||
# Neue Breite und Höhe berechnen
|
# Neue Breite und Höhe berechnen
|
||||||
width = int(math.floor(pixbuf.get_width()*ratio))
|
width = int(math.floor(pixbuf.get_width() * ratio))
|
||||||
height = int(math.floor(pixbuf.get_height()*ratio))
|
height = int(math.floor(pixbuf.get_height() * ratio))
|
||||||
if width <= 0 or height <= 0:
|
if width <= 0 or height <= 0:
|
||||||
return
|
return
|
||||||
# Pixelpuffer auf Oberfläche zeichnen
|
# Pixelpuffer auf Oberfläche zeichnen
|
||||||
self.standalone_image.set_from_pixbuf(
|
self.standalone_image.set_from_pixbuf(
|
||||||
pixbuf.scale_simple(
|
pixbuf.scale_simple(width, height, GdkPixbuf.InterpType.HYPER))
|
||||||
width,
|
|
||||||
height,
|
|
||||||
GdkPixbuf.InterpType.HYPER
|
|
||||||
)
|
|
||||||
)
|
|
||||||
self.standalone_image.show()
|
self.standalone_image.show()
|
||||||
|
|
||||||
def _get_default_image(self):
|
def _get_default_image(self):
|
||||||
return self._icon_theme.lookup_icon(
|
return self._icon_theme.lookup_icon(Utils.STOCK_ICON_DEFAULT, None,
|
||||||
Utils.STOCK_ICON_DEFAULT,
|
512, 512, Gtk.TextDirection.LTR,
|
||||||
None,
|
Gtk.IconLookupFlags.FORCE_SYMBOLIC)
|
||||||
512,
|
|
||||||
512,
|
|
||||||
Gtk.TextDirection.LTR,
|
|
||||||
Gtk.IconLookupFlags.FORCE_SYMBOLIC
|
|
||||||
)
|
|
||||||
|
|
||||||
def _get_selected_albums(self):
|
def _get_selected_albums(self):
|
||||||
albums = []
|
albums = []
|
||||||
for i in range(self.library_grid.get_model().get_n_items()):
|
for i in range(self.library_grid.get_model().get_n_items()):
|
||||||
if self.library_grid.get_model().is_selected(i):
|
if self.library_grid.get_model().is_selected(i):
|
||||||
albums.append(
|
albums.append(self.library_grid.get_model().get_item(
|
||||||
self.library_grid.get_model()
|
i).get_album().get_id())
|
||||||
.get_item(i)
|
|
||||||
.get_album()
|
|
||||||
.get_id()
|
|
||||||
)
|
|
||||||
return albums
|
return albums
|
||||||
|
|
|
||||||
|
|
@ -22,18 +22,12 @@ class PlaylistPanel(Adw.Bin):
|
||||||
'open-standalone': (GObject.SIGNAL_RUN_FIRST, None, ()),
|
'open-standalone': (GObject.SIGNAL_RUN_FIRST, None, ()),
|
||||||
'close-standalone': (GObject.SIGNAL_RUN_FIRST, None, ()),
|
'close-standalone': (GObject.SIGNAL_RUN_FIRST, None, ()),
|
||||||
'clear-playlist': (GObject.SIGNAL_RUN_FIRST, None, ()),
|
'clear-playlist': (GObject.SIGNAL_RUN_FIRST, None, ()),
|
||||||
'remove-album': (
|
'remove-album':
|
||||||
GObject.SIGNAL_RUN_FIRST,
|
(GObject.SIGNAL_RUN_FIRST, None, (GObject.TYPE_PYOBJECT, )),
|
||||||
None,
|
'remove-multiple-albums':
|
||||||
(GObject.TYPE_PYOBJECT,)
|
(GObject.SIGNAL_RUN_FIRST, None, (GObject.TYPE_PYOBJECT, )),
|
||||||
),
|
'play': (GObject.SIGNAL_RUN_FIRST, None, (GObject.TYPE_PYOBJECT, )),
|
||||||
'remove-multiple-albums': (
|
'albumart': (GObject.SIGNAL_RUN_FIRST, None, (str, )),
|
||||||
GObject.SIGNAL_RUN_FIRST,
|
|
||||||
None,
|
|
||||||
(GObject.TYPE_PYOBJECT,)
|
|
||||||
),
|
|
||||||
'play': (GObject.SIGNAL_RUN_FIRST, None, (GObject.TYPE_PYOBJECT,)),
|
|
||||||
'albumart': (GObject.SIGNAL_RUN_FIRST, None, (str,)),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Widgets
|
# Widgets
|
||||||
|
|
@ -66,8 +60,7 @@ class PlaylistPanel(Adw.Bin):
|
||||||
self._playlist_lock = threading.Lock()
|
self._playlist_lock = threading.Lock()
|
||||||
self._playlist_stop = threading.Event()
|
self._playlist_stop = threading.Event()
|
||||||
self._icon_theme = Gtk.IconTheme.get_for_display(
|
self._icon_theme = Gtk.IconTheme.get_for_display(
|
||||||
Gdk.Display.get_default()
|
Gdk.Display.get_default())
|
||||||
)
|
|
||||||
self._standalone_pixbuf = None
|
self._standalone_pixbuf = None
|
||||||
self._selected_albums = []
|
self._selected_albums = []
|
||||||
self._is_selected = False
|
self._is_selected = False
|
||||||
|
|
@ -75,18 +68,14 @@ class PlaylistPanel(Adw.Bin):
|
||||||
# Widgets
|
# Widgets
|
||||||
# Header bar
|
# Header bar
|
||||||
self._headerbar_standalone = AlbumHeaderbar()
|
self._headerbar_standalone = AlbumHeaderbar()
|
||||||
self._headerbar_standalone.connect(
|
self._headerbar_standalone.connect('close',
|
||||||
'close',
|
self.on_headerbar_close_clicked)
|
||||||
self.on_headerbar_close_clicked
|
|
||||||
)
|
|
||||||
# Playlist Grid: Model
|
# Playlist Grid: Model
|
||||||
self._playlist_grid_model = Gio.ListStore()
|
self._playlist_grid_model = Gio.ListStore()
|
||||||
self._playlist_grid_selection_multi = Gtk.MultiSelection.new(
|
self._playlist_grid_selection_multi = Gtk.MultiSelection.new(
|
||||||
self._playlist_grid_model
|
self._playlist_grid_model)
|
||||||
)
|
|
||||||
self._playlist_grid_selection_single = Gtk.SingleSelection.new(
|
self._playlist_grid_selection_single = Gtk.SingleSelection.new(
|
||||||
self._playlist_grid_model
|
self._playlist_grid_model)
|
||||||
)
|
|
||||||
# Playlist Grid
|
# Playlist Grid
|
||||||
self.playlist_grid.set_model(self._playlist_grid_selection_single)
|
self.playlist_grid.set_model(self._playlist_grid_selection_single)
|
||||||
|
|
||||||
|
|
@ -106,15 +95,13 @@ class PlaylistPanel(Adw.Bin):
|
||||||
self.playlist_grid.set_model(self._playlist_grid_selection_multi)
|
self.playlist_grid.set_model(self._playlist_grid_selection_multi)
|
||||||
self.playlist_grid.set_single_click_activate(False)
|
self.playlist_grid.set_single_click_activate(False)
|
||||||
self.playlist_grid.get_style_context().add_class(
|
self.playlist_grid.get_style_context().add_class(
|
||||||
Utils.CSS_SELECTION
|
Utils.CSS_SELECTION)
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
self.actionbar_revealer.set_reveal_child(False)
|
self.actionbar_revealer.set_reveal_child(False)
|
||||||
self.playlist_grid.set_model(self._playlist_grid_selection_single)
|
self.playlist_grid.set_model(self._playlist_grid_selection_single)
|
||||||
self.playlist_grid.set_single_click_activate(True)
|
self.playlist_grid.set_single_click_activate(True)
|
||||||
self.playlist_grid.get_style_context().remove_class(
|
self.playlist_grid.get_style_context().remove_class(
|
||||||
Utils.CSS_SELECTION
|
Utils.CSS_SELECTION)
|
||||||
)
|
|
||||||
|
|
||||||
@Gtk.Template.Callback()
|
@Gtk.Template.Callback()
|
||||||
def on_clear_clicked(self, widget):
|
def on_clear_clicked(self, widget):
|
||||||
|
|
@ -177,10 +164,12 @@ class PlaylistPanel(Adw.Bin):
|
||||||
def set_playlist(self, host, playlist):
|
def set_playlist(self, host, playlist):
|
||||||
self._host = host
|
self._host = host
|
||||||
self._playlist_stop.set()
|
self._playlist_stop.set()
|
||||||
threading.Thread(
|
threading.Thread(target=self._set_playlist,
|
||||||
target=self._set_playlist,
|
args=(
|
||||||
args=(host, playlist, self._item_size,)
|
host,
|
||||||
).start()
|
playlist,
|
||||||
|
self._item_size,
|
||||||
|
)).start()
|
||||||
|
|
||||||
def set_albumart(self, album, data):
|
def set_albumart(self, album, data):
|
||||||
if album in self._selected_albums:
|
if album in self._selected_albums:
|
||||||
|
|
@ -221,13 +210,9 @@ class PlaylistPanel(Adw.Bin):
|
||||||
self._logger.exception("Failed to load albumart")
|
self._logger.exception("Failed to load albumart")
|
||||||
if pixbuf is None:
|
if pixbuf is None:
|
||||||
pixbuf = self._icon_theme.lookup_icon(
|
pixbuf = self._icon_theme.lookup_icon(
|
||||||
Utils.STOCK_ICON_DEFAULT,
|
Utils.STOCK_ICON_DEFAULT, None, self._item_size,
|
||||||
None,
|
self._item_size, Gtk.TextDirection.LTR,
|
||||||
self._item_size,
|
Gtk.IconLookupFlags.FORCE_SYMBOLIC)
|
||||||
self._item_size,
|
|
||||||
Gtk.TextDirection.LTR,
|
|
||||||
Gtk.IconLookupFlags.FORCE_SYMBOLIC
|
|
||||||
)
|
|
||||||
if pixbuf is not None:
|
if pixbuf is not None:
|
||||||
self._playlist_grid_model.append(GridItem(album, pixbuf))
|
self._playlist_grid_model.append(GridItem(album, pixbuf))
|
||||||
|
|
||||||
|
|
@ -276,35 +261,24 @@ class PlaylistPanel(Adw.Bin):
|
||||||
ratio = min(ratioW, ratioH)
|
ratio = min(ratioW, ratioH)
|
||||||
ratio = min(ratio, 1)
|
ratio = min(ratio, 1)
|
||||||
# Neue Breite und Höhe berechnen
|
# Neue Breite und Höhe berechnen
|
||||||
width = int(math.floor(pixbuf.get_width()*ratio))
|
width = int(math.floor(pixbuf.get_width() * ratio))
|
||||||
height = int(math.floor(pixbuf.get_height()*ratio))
|
height = int(math.floor(pixbuf.get_height() * ratio))
|
||||||
if width <= 0 or height <= 0:
|
if width <= 0 or height <= 0:
|
||||||
return
|
return
|
||||||
# Pixelpuffer auf Oberfläche zeichnen
|
# Pixelpuffer auf Oberfläche zeichnen
|
||||||
self.standalone_image.set_from_pixbuf(
|
self.standalone_image.set_from_pixbuf(
|
||||||
pixbuf.scale_simple(
|
pixbuf.scale_simple(width, height, GdkPixbuf.InterpType.HYPER))
|
||||||
width,
|
|
||||||
height,
|
|
||||||
GdkPixbuf.InterpType.HYPER
|
|
||||||
)
|
|
||||||
)
|
|
||||||
self.standalone_image.show()
|
self.standalone_image.show()
|
||||||
|
|
||||||
def _get_default_image(self):
|
def _get_default_image(self):
|
||||||
return self._icon_theme.lookup_icon(
|
return self._icon_theme.lookup_icon(Utils.STOCK_ICON_DEFAULT, None,
|
||||||
Utils.STOCK_ICON_DEFAULT,
|
512, 512, Gtk.TextDirection.LTR,
|
||||||
None,
|
Gtk.IconLookupFlags.FORCE_SYMBOLIC)
|
||||||
512,
|
|
||||||
512,
|
|
||||||
Gtk.TextDirection.LTR,
|
|
||||||
Gtk.IconLookupFlags.FORCE_SYMBOLIC
|
|
||||||
)
|
|
||||||
|
|
||||||
def _get_selected_albums(self):
|
def _get_selected_albums(self):
|
||||||
albums = []
|
albums = []
|
||||||
for i in range(self.playlist_grid.get_model().get_n_items()):
|
for i in range(self.playlist_grid.get_model().get_n_items()):
|
||||||
if self.playlist_grid.get_model().is_selected(i):
|
if self.playlist_grid.get_model().is_selected(i):
|
||||||
albums.append(
|
albums.append(
|
||||||
self.playlist_grid.get_model().get_item(i).get_album()
|
self.playlist_grid.get_model().get_item(i).get_album())
|
||||||
)
|
|
||||||
return albums
|
return albums
|
||||||
|
|
|
||||||
|
|
@ -12,11 +12,10 @@ from gi.repository import Gtk, Adw, GObject
|
||||||
class ServerPanel(Adw.Bin):
|
class ServerPanel(Adw.Bin):
|
||||||
__gtype_name__ = 'McgServerPanel'
|
__gtype_name__ = 'McgServerPanel'
|
||||||
__gsignals__ = {
|
__gsignals__ = {
|
||||||
'change-output-device': (
|
'change-output-device': (GObject.SIGNAL_RUN_FIRST, None, (
|
||||||
GObject.SIGNAL_RUN_FIRST,
|
GObject.TYPE_PYOBJECT,
|
||||||
None,
|
bool,
|
||||||
(GObject.TYPE_PYOBJECT,bool,)
|
)),
|
||||||
),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Widgets
|
# Widgets
|
||||||
|
|
@ -61,14 +60,11 @@ class ServerPanel(Adw.Bin):
|
||||||
file = self._none_label
|
file = self._none_label
|
||||||
self.status_file.set_markup(file)
|
self.status_file.set_markup(file)
|
||||||
# Audio information
|
# Audio information
|
||||||
if audio:
|
if audio:
|
||||||
parts = audio.split(":")
|
parts = audio.split(":")
|
||||||
if len(parts) == 3:
|
if len(parts) == 3:
|
||||||
audio = "{} Hz, {} bit, {} channels".format(
|
audio = "{} Hz, {} bit, {} channels".format(
|
||||||
parts[0],
|
parts[0], parts[1], parts[2])
|
||||||
parts[1],
|
|
||||||
parts[2]
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
audio = self._none_label
|
audio = self._none_label
|
||||||
self.status_audio.set_markup(audio)
|
self.status_audio.set_markup(audio)
|
||||||
|
|
@ -102,18 +98,14 @@ class ServerPanel(Adw.Bin):
|
||||||
if device.get_id() in self._output_buttons.keys():
|
if device.get_id() in self._output_buttons.keys():
|
||||||
self._output_buttons[device.get_id()].freeze_notify()
|
self._output_buttons[device.get_id()].freeze_notify()
|
||||||
self._output_buttons[device.get_id()].set_active(
|
self._output_buttons[device.get_id()].set_active(
|
||||||
device.is_enabled()
|
device.is_enabled())
|
||||||
)
|
|
||||||
self._output_buttons[device.get_id()].thaw_notify()
|
self._output_buttons[device.get_id()].thaw_notify()
|
||||||
else:
|
else:
|
||||||
button = Gtk.CheckButton.new_with_label(device.get_name())
|
button = Gtk.CheckButton.new_with_label(device.get_name())
|
||||||
if device.is_enabled():
|
if device.is_enabled():
|
||||||
button.set_active(True)
|
button.set_active(True)
|
||||||
handler = button.connect(
|
handler = button.connect('toggled',
|
||||||
'toggled',
|
self.on_output_device_toggled, device)
|
||||||
self.on_output_device_toggled,
|
|
||||||
device
|
|
||||||
)
|
|
||||||
self.output_devices.insert(button, -1)
|
self.output_devices.insert(button, -1)
|
||||||
self._output_buttons[device.get_id()] = button
|
self._output_buttons[device.get_id()] = button
|
||||||
|
|
||||||
|
|
@ -121,5 +113,5 @@ class ServerPanel(Adw.Bin):
|
||||||
for id in self._output_buttons.keys():
|
for id in self._output_buttons.keys():
|
||||||
if id not in device_ids:
|
if id not in device_ids:
|
||||||
self.output_devices.remove(
|
self.output_devices.remove(
|
||||||
self._output_buttons[id].get_parent()
|
self._output_buttons[id].get_parent())
|
||||||
)
|
|
||||||
|
|
|
||||||
18
src/utils.py
18
src/utils.py
|
|
@ -35,11 +35,8 @@ class Utils:
|
||||||
if albumart:
|
if albumart:
|
||||||
pixbuf = Utils.load_pixbuf(albumart)
|
pixbuf = Utils.load_pixbuf(albumart)
|
||||||
if pixbuf is not None:
|
if pixbuf is not None:
|
||||||
pixbuf = pixbuf.scale_simple(
|
pixbuf = pixbuf.scale_simple(size, size,
|
||||||
size,
|
GdkPixbuf.InterpType.HYPER)
|
||||||
size,
|
|
||||||
GdkPixbuf.InterpType.HYPER
|
|
||||||
)
|
|
||||||
pixbuf.savev(cache_url, 'jpeg', [], [])
|
pixbuf.savev(cache_url, 'jpeg', [], [])
|
||||||
return pixbuf
|
return pixbuf
|
||||||
|
|
||||||
|
|
@ -47,9 +44,7 @@ class Utils:
|
||||||
label = ', '.join(album.get_albumartists())
|
label = ', '.join(album.get_albumartists())
|
||||||
if album.get_artists():
|
if album.get_artists():
|
||||||
label = locale.gettext("{} feat. {}").format(
|
label = locale.gettext("{} feat. {}").format(
|
||||||
label,
|
label, ", ".join(album.get_artists()))
|
||||||
", ".join(album.get_artists())
|
|
||||||
)
|
|
||||||
return label
|
return label
|
||||||
|
|
||||||
def create_length_label(album):
|
def create_length_label(album):
|
||||||
|
|
@ -62,9 +57,7 @@ class Utils:
|
||||||
title = track.get_title()
|
title = track.get_title()
|
||||||
if track.get_artists():
|
if track.get_artists():
|
||||||
title = locale.gettext("{} feat. {}").format(
|
title = locale.gettext("{} feat. {}").format(
|
||||||
title,
|
title, ", ".join(track.get_artists()))
|
||||||
", ".join(track.get_artists())
|
|
||||||
)
|
|
||||||
return title
|
return title
|
||||||
|
|
||||||
def generate_id(values):
|
def generate_id(values):
|
||||||
|
|
@ -95,8 +88,7 @@ class GridItem(GObject.GObject):
|
||||||
if cover:
|
if cover:
|
||||||
self.cover = Gdk.Texture.new_for_pixbuf(cover)
|
self.cover = Gdk.Texture.new_for_pixbuf(cover)
|
||||||
self.tooltip = GObject.markup_escape_text("\n".join([
|
self.tooltip = GObject.markup_escape_text("\n".join([
|
||||||
album.get_title(),
|
album.get_title(), ', '.join(album.get_dates()),
|
||||||
', '.join(album.get_dates()),
|
|
||||||
Utils.create_artists_label(album),
|
Utils.create_artists_label(album),
|
||||||
Utils.create_length_label(album)
|
Utils.create_length_label(album)
|
||||||
]))
|
]))
|
||||||
|
|
|
||||||
424
src/window.py
424
src/window.py
|
|
@ -92,52 +92,35 @@ class Window(Adw.ApplicationWindow):
|
||||||
self._panels.append(self._cover_panel)
|
self._panels.append(self._cover_panel)
|
||||||
# Playlist panel
|
# Playlist panel
|
||||||
self._playlist_panel = PlaylistPanel(self._mcg)
|
self._playlist_panel = PlaylistPanel(self._mcg)
|
||||||
self._playlist_panel.connect(
|
self._playlist_panel.connect('open-standalone',
|
||||||
'open-standalone',
|
self.on_panel_open_standalone)
|
||||||
self.on_panel_open_standalone
|
self._playlist_panel.connect('close-standalone',
|
||||||
)
|
self.on_panel_close_standalone)
|
||||||
self._playlist_panel.connect(
|
|
||||||
'close-standalone',
|
|
||||||
self.on_panel_close_standalone
|
|
||||||
)
|
|
||||||
self._panels.append(self._playlist_panel)
|
self._panels.append(self._playlist_panel)
|
||||||
# Library panel
|
# Library panel
|
||||||
self._library_panel = LibraryPanel(self._mcg)
|
self._library_panel = LibraryPanel(self._mcg)
|
||||||
self._library_panel.connect(
|
self._library_panel.connect('open-standalone',
|
||||||
'open-standalone',
|
self.on_panel_open_standalone)
|
||||||
self.on_panel_open_standalone
|
self._library_panel.connect('close-standalone',
|
||||||
)
|
self.on_panel_close_standalone)
|
||||||
self._library_panel.connect(
|
|
||||||
'close-standalone',
|
|
||||||
self.on_panel_close_standalone
|
|
||||||
)
|
|
||||||
self._panels.append(self._library_panel)
|
self._panels.append(self._library_panel)
|
||||||
# Stack
|
# Stack
|
||||||
self.content_stack.add_child(self._connection_panel)
|
self.content_stack.add_child(self._connection_panel)
|
||||||
self.panel_stack.add_titled_with_icon(
|
self.panel_stack.add_titled_with_icon(self._server_panel,
|
||||||
self._server_panel,
|
'server-panel',
|
||||||
'server-panel',
|
locale.gettext("Server"),
|
||||||
locale.gettext("Server"),
|
"network-wired-symbolic")
|
||||||
"network-wired-symbolic"
|
self.panel_stack.add_titled_with_icon(self._cover_panel, 'cover-panel',
|
||||||
)
|
locale.gettext("Cover"),
|
||||||
self.panel_stack.add_titled_with_icon(
|
"image-x-generic-symbolic")
|
||||||
self._cover_panel,
|
self.panel_stack.add_titled_with_icon(self._playlist_panel,
|
||||||
'cover-panel',
|
'playlist-panel',
|
||||||
locale.gettext("Cover"),
|
locale.gettext("Playlist"),
|
||||||
"image-x-generic-symbolic"
|
"view-list-symbolic")
|
||||||
)
|
self.panel_stack.add_titled_with_icon(self._library_panel,
|
||||||
self.panel_stack.add_titled_with_icon(
|
'library-panel',
|
||||||
self._playlist_panel,
|
locale.gettext("Library"),
|
||||||
'playlist-panel',
|
"emblem-music-symbolic")
|
||||||
locale.gettext("Playlist"),
|
|
||||||
"view-list-symbolic"
|
|
||||||
)
|
|
||||||
self.panel_stack.add_titled_with_icon(
|
|
||||||
self._library_panel,
|
|
||||||
'library-panel',
|
|
||||||
locale.gettext("Library"),
|
|
||||||
"emblem-music-symbolic"
|
|
||||||
)
|
|
||||||
# Toolbar stack
|
# Toolbar stack
|
||||||
self.toolbar_stack.add_child(self._server_panel.get_toolbar())
|
self.toolbar_stack.add_child(self._server_panel.get_toolbar())
|
||||||
self.toolbar_stack.add_child(self._cover_panel.get_toolbar())
|
self.toolbar_stack.add_child(self._cover_panel.get_toolbar())
|
||||||
|
|
@ -147,30 +130,21 @@ class Window(Adw.ApplicationWindow):
|
||||||
# Properties
|
# Properties
|
||||||
self._set_headerbar_sensitive(False, False)
|
self._set_headerbar_sensitive(False, False)
|
||||||
self._connection_panel.set_host(
|
self._connection_panel.set_host(
|
||||||
self._settings.get_string(Window.SETTING_HOST)
|
self._settings.get_string(Window.SETTING_HOST))
|
||||||
)
|
|
||||||
self._connection_panel.set_port(
|
self._connection_panel.set_port(
|
||||||
self._settings.get_int(Window.SETTING_PORT)
|
self._settings.get_int(Window.SETTING_PORT))
|
||||||
)
|
|
||||||
if use_keyring:
|
if use_keyring:
|
||||||
self._connection_panel.set_password(
|
self._connection_panel.set_password(
|
||||||
keyring.get_password(
|
keyring.get_password(ZeroconfProvider.KEYRING_SYSTEM,
|
||||||
ZeroconfProvider.KEYRING_SYSTEM,
|
ZeroconfProvider.KEYRING_USERNAME))
|
||||||
ZeroconfProvider.KEYRING_USERNAME
|
|
||||||
)
|
|
||||||
)
|
|
||||||
self._playlist_panel.set_item_size(
|
self._playlist_panel.set_item_size(
|
||||||
self._settings.get_int(Window.SETTING_ITEM_SIZE)
|
self._settings.get_int(Window.SETTING_ITEM_SIZE))
|
||||||
)
|
|
||||||
self._library_panel.set_item_size(
|
self._library_panel.set_item_size(
|
||||||
self._settings.get_int(Window.SETTING_ITEM_SIZE)
|
self._settings.get_int(Window.SETTING_ITEM_SIZE))
|
||||||
)
|
|
||||||
self._library_panel.set_sort_order(
|
self._library_panel.set_sort_order(
|
||||||
self._settings.get_enum(Window.SETTING_SORT_ORDER)
|
self._settings.get_enum(Window.SETTING_SORT_ORDER))
|
||||||
)
|
|
||||||
self._library_panel.set_sort_type(
|
self._library_panel.set_sort_type(
|
||||||
self._settings.get_boolean(Window.SETTING_SORT_TYPE)
|
self._settings.get_boolean(Window.SETTING_SORT_TYPE))
|
||||||
)
|
|
||||||
|
|
||||||
# Signals
|
# Signals
|
||||||
self.connect("notify::default-width", self.on_resize)
|
self.connect("notify::default-width", self.on_resize)
|
||||||
|
|
@ -178,131 +152,69 @@ class Window(Adw.ApplicationWindow):
|
||||||
self.connect("notify::maximized", self.on_maximized)
|
self.connect("notify::maximized", self.on_maximized)
|
||||||
self.connect("notify::fullscreened", self.on_fullscreened)
|
self.connect("notify::fullscreened", self.on_fullscreened)
|
||||||
self._connection_panel.connect(
|
self._connection_panel.connect(
|
||||||
'connection-changed',
|
'connection-changed', self.on_connection_panel_connection_changed)
|
||||||
self.on_connection_panel_connection_changed
|
self.panel_stack.connect('notify::visible-child',
|
||||||
)
|
self.on_stack_switched)
|
||||||
self.panel_stack.connect(
|
self._server_panel.connect('change-output-device',
|
||||||
'notify::visible-child',
|
self.on_server_panel_output_device_changed)
|
||||||
self.on_stack_switched
|
self._cover_panel.connect('toggle-fullscreen',
|
||||||
)
|
self.on_cover_panel_toggle_fullscreen)
|
||||||
self._server_panel.connect(
|
|
||||||
'change-output-device',
|
|
||||||
self.on_server_panel_output_device_changed
|
|
||||||
)
|
|
||||||
self._cover_panel.connect(
|
|
||||||
'toggle-fullscreen',
|
|
||||||
self.on_cover_panel_toggle_fullscreen
|
|
||||||
)
|
|
||||||
self._cover_panel.connect('set-song', self.on_cover_panel_set_song)
|
self._cover_panel.connect('set-song', self.on_cover_panel_set_song)
|
||||||
self._cover_panel.connect('albumart', self.on_cover_panel_albumart)
|
self._cover_panel.connect('albumart', self.on_cover_panel_albumart)
|
||||||
self._playlist_panel.connect(
|
self._playlist_panel.connect('clear-playlist',
|
||||||
'clear-playlist',
|
self.on_playlist_panel_clear_playlist)
|
||||||
self.on_playlist_panel_clear_playlist
|
self._playlist_panel.connect('remove-album',
|
||||||
)
|
self.on_playlist_panel_remove)
|
||||||
self._playlist_panel.connect(
|
self._playlist_panel.connect('remove-multiple-albums',
|
||||||
'remove-album',
|
self.on_playlist_panel_remove_multiple)
|
||||||
self.on_playlist_panel_remove
|
|
||||||
)
|
|
||||||
self._playlist_panel.connect(
|
|
||||||
'remove-multiple-albums',
|
|
||||||
self.on_playlist_panel_remove_multiple
|
|
||||||
)
|
|
||||||
self._playlist_panel.connect('play', self.on_playlist_panel_play)
|
self._playlist_panel.connect('play', self.on_playlist_panel_play)
|
||||||
self._playlist_panel.connect(
|
self._playlist_panel.connect('albumart',
|
||||||
'albumart',
|
self.on_playlist_panel_albumart)
|
||||||
self.on_playlist_panel_albumart
|
|
||||||
)
|
|
||||||
self._library_panel.connect('update', self.on_library_panel_update)
|
self._library_panel.connect('update', self.on_library_panel_update)
|
||||||
self._library_panel.connect('play', self.on_library_panel_play)
|
self._library_panel.connect('play', self.on_library_panel_play)
|
||||||
self._library_panel.connect('queue', self.on_library_panel_queue)
|
self._library_panel.connect('queue', self.on_library_panel_queue)
|
||||||
self._library_panel.connect(
|
self._library_panel.connect('queue-multiple',
|
||||||
'queue-multiple',
|
self.on_library_panel_queue_multiple)
|
||||||
self.on_library_panel_queue_multiple
|
self._library_panel.connect('item-size-changed',
|
||||||
)
|
self.on_library_panel_item_size_changed)
|
||||||
self._library_panel.connect(
|
self._library_panel.connect('sort-order-changed',
|
||||||
'item-size-changed',
|
self.on_library_panel_sort_order_changed)
|
||||||
self.on_library_panel_item_size_changed
|
self._library_panel.connect('sort-type-changed',
|
||||||
)
|
self.on_library_panel_sort_type_changed)
|
||||||
self._library_panel.connect(
|
|
||||||
'sort-order-changed',
|
|
||||||
self.on_library_panel_sort_order_changed
|
|
||||||
)
|
|
||||||
self._library_panel.connect(
|
|
||||||
'sort-type-changed',
|
|
||||||
self.on_library_panel_sort_type_changed
|
|
||||||
)
|
|
||||||
self._library_panel.connect('albumart', self.on_library_panel_albumart)
|
self._library_panel.connect('albumart', self.on_library_panel_albumart)
|
||||||
self._mcg.connect_signal(
|
self._mcg.connect_signal(client.Client.SIGNAL_CONNECTION,
|
||||||
client.Client.SIGNAL_CONNECTION,
|
self.on_mcg_connect)
|
||||||
self.on_mcg_connect
|
self._mcg.connect_signal(client.Client.SIGNAL_STATUS,
|
||||||
)
|
self.on_mcg_status)
|
||||||
self._mcg.connect_signal(
|
|
||||||
client.Client.SIGNAL_STATUS,
|
|
||||||
self.on_mcg_status
|
|
||||||
)
|
|
||||||
self._mcg.connect_signal(client.Client.SIGNAL_STATS, self.on_mcg_stats)
|
self._mcg.connect_signal(client.Client.SIGNAL_STATS, self.on_mcg_stats)
|
||||||
self._mcg.connect_signal(
|
self._mcg.connect_signal(client.Client.SIGNAL_LOAD_OUTPUT_DEVICES,
|
||||||
client.Client.SIGNAL_LOAD_OUTPUT_DEVICES,
|
self.on_mcg_load_output_devices)
|
||||||
self.on_mcg_load_output_devices
|
self._mcg.connect_signal(client.Client.SIGNAL_LOAD_PLAYLIST,
|
||||||
)
|
self.on_mcg_load_playlist)
|
||||||
self._mcg.connect_signal(
|
self._mcg.connect_signal(client.Client.SIGNAL_PULSE_ALBUMS,
|
||||||
client.Client.SIGNAL_LOAD_PLAYLIST,
|
self.on_mcg_pulse_albums)
|
||||||
self.on_mcg_load_playlist
|
self._mcg.connect_signal(client.Client.SIGNAL_INIT_ALBUMS,
|
||||||
)
|
self.on_mcg_init_albums)
|
||||||
self._mcg.connect_signal(
|
self._mcg.connect_signal(client.Client.SIGNAL_LOAD_ALBUMS,
|
||||||
client.Client.SIGNAL_PULSE_ALBUMS,
|
self.on_mcg_load_albums)
|
||||||
self.on_mcg_pulse_albums
|
self._mcg.connect_signal(client.Client.SIGNAL_LOAD_ALBUMART,
|
||||||
)
|
self.on_mcg_load_albumart)
|
||||||
self._mcg.connect_signal(
|
self._mcg.connect_signal(client.Client.SIGNAL_ERROR, self.on_mcg_error)
|
||||||
client.Client.SIGNAL_INIT_ALBUMS,
|
self._settings.connect('changed::' + Window.SETTING_PANEL,
|
||||||
self.on_mcg_init_albums
|
self.on_settings_panel_changed)
|
||||||
)
|
self._settings.connect('changed::' + Window.SETTING_ITEM_SIZE,
|
||||||
self._mcg.connect_signal(
|
self.on_settings_item_size_changed)
|
||||||
client.Client.SIGNAL_LOAD_ALBUMS,
|
self._settings.connect('changed::' + Window.SETTING_SORT_ORDER,
|
||||||
self.on_mcg_load_albums
|
self.on_settings_sort_order_changed)
|
||||||
)
|
self._settings.connect('changed::' + Window.SETTING_SORT_TYPE,
|
||||||
self._mcg.connect_signal(
|
self.on_settings_sort_type_changed)
|
||||||
client.Client.SIGNAL_LOAD_ALBUMART,
|
self._settings.bind(Window.SETTING_WINDOW_WIDTH, self._state,
|
||||||
self.on_mcg_load_albumart
|
WindowState.WIDTH, Gio.SettingsBindFlags.DEFAULT)
|
||||||
)
|
self._settings.bind(Window.SETTING_WINDOW_HEIGHT, self._state,
|
||||||
self._mcg.connect_signal(
|
WindowState.HEIGHT, Gio.SettingsBindFlags.DEFAULT)
|
||||||
client.Client.SIGNAL_ERROR,
|
self._settings.bind(Window.SETTING_WINDOW_MAXIMIZED, self._state,
|
||||||
self.on_mcg_error
|
WindowState.IS_MAXIMIZED,
|
||||||
)
|
Gio.SettingsBindFlags.DEFAULT)
|
||||||
self._settings.connect(
|
|
||||||
'changed::'+Window.SETTING_PANEL,
|
|
||||||
self.on_settings_panel_changed
|
|
||||||
)
|
|
||||||
self._settings.connect(
|
|
||||||
'changed::'+Window.SETTING_ITEM_SIZE,
|
|
||||||
self.on_settings_item_size_changed
|
|
||||||
)
|
|
||||||
self._settings.connect(
|
|
||||||
'changed::'+Window.SETTING_SORT_ORDER,
|
|
||||||
self.on_settings_sort_order_changed
|
|
||||||
)
|
|
||||||
self._settings.connect(
|
|
||||||
'changed::'+Window.SETTING_SORT_TYPE,
|
|
||||||
self.on_settings_sort_type_changed
|
|
||||||
)
|
|
||||||
self._settings.bind(
|
|
||||||
Window.SETTING_WINDOW_WIDTH,
|
|
||||||
self._state,
|
|
||||||
WindowState.WIDTH,
|
|
||||||
Gio.SettingsBindFlags.DEFAULT
|
|
||||||
)
|
|
||||||
self._settings.bind(
|
|
||||||
Window.SETTING_WINDOW_HEIGHT,
|
|
||||||
self._state,
|
|
||||||
WindowState.HEIGHT,
|
|
||||||
Gio.SettingsBindFlags.DEFAULT
|
|
||||||
)
|
|
||||||
self._settings.bind(
|
|
||||||
Window.SETTING_WINDOW_MAXIMIZED,
|
|
||||||
self._state,
|
|
||||||
WindowState.IS_MAXIMIZED,
|
|
||||||
Gio.SettingsBindFlags.DEFAULT
|
|
||||||
)
|
|
||||||
|
|
||||||
# Actions
|
# Actions
|
||||||
self.set_default_size(self._state.width, self._state.height)
|
self.set_default_size(self._state.width, self._state.height)
|
||||||
|
|
@ -314,58 +226,37 @@ class Window(Adw.ApplicationWindow):
|
||||||
|
|
||||||
# Menu actions
|
# Menu actions
|
||||||
self._connect_action = Gio.SimpleAction.new_stateful(
|
self._connect_action = Gio.SimpleAction.new_stateful(
|
||||||
"connect",
|
"connect", None, GLib.Variant.new_boolean(False))
|
||||||
None,
|
|
||||||
GLib.Variant.new_boolean(False)
|
|
||||||
)
|
|
||||||
self._connect_action.connect('change-state', self.on_menu_connect)
|
self._connect_action.connect('change-state', self.on_menu_connect)
|
||||||
self.add_action(self._connect_action)
|
self.add_action(self._connect_action)
|
||||||
self._play_action = Gio.SimpleAction.new_stateful(
|
self._play_action = Gio.SimpleAction.new_stateful(
|
||||||
"play",
|
"play", None, GLib.Variant.new_boolean(False))
|
||||||
None,
|
|
||||||
GLib.Variant.new_boolean(False)
|
|
||||||
)
|
|
||||||
self._play_action.set_enabled(False)
|
self._play_action.set_enabled(False)
|
||||||
self._play_action.connect('change-state', self.on_menu_play)
|
self._play_action.connect('change-state', self.on_menu_play)
|
||||||
self.add_action(self._play_action)
|
self.add_action(self._play_action)
|
||||||
self._clear_playlist_action = Gio.SimpleAction.new(
|
self._clear_playlist_action = Gio.SimpleAction.new(
|
||||||
"clear-playlist",
|
"clear-playlist", None)
|
||||||
None
|
|
||||||
)
|
|
||||||
self._clear_playlist_action.set_enabled(False)
|
self._clear_playlist_action.set_enabled(False)
|
||||||
self._clear_playlist_action.connect(
|
self._clear_playlist_action.connect('activate',
|
||||||
'activate',
|
self.on_menu_clear_playlist)
|
||||||
self.on_menu_clear_playlist
|
|
||||||
)
|
|
||||||
self.add_action(self._clear_playlist_action)
|
self.add_action(self._clear_playlist_action)
|
||||||
panel_variant = GLib.Variant.new_string("0")
|
panel_variant = GLib.Variant.new_string("0")
|
||||||
self._panel_action = Gio.SimpleAction.new_stateful(
|
self._panel_action = Gio.SimpleAction.new_stateful(
|
||||||
"panel",
|
"panel", panel_variant.get_type(), panel_variant)
|
||||||
panel_variant.get_type(),
|
|
||||||
panel_variant
|
|
||||||
)
|
|
||||||
self._panel_action.set_enabled(False)
|
self._panel_action.set_enabled(False)
|
||||||
self._panel_action.connect('change-state', self.on_menu_panel)
|
self._panel_action.connect('change-state', self.on_menu_panel)
|
||||||
self.add_action(self._panel_action)
|
self.add_action(self._panel_action)
|
||||||
self._toggle_fullscreen_action = Gio.SimpleAction.new(
|
self._toggle_fullscreen_action = Gio.SimpleAction.new(
|
||||||
"toggle-fullscreen",
|
"toggle-fullscreen", None)
|
||||||
None
|
|
||||||
)
|
|
||||||
self._toggle_fullscreen_action.set_enabled(True)
|
self._toggle_fullscreen_action.set_enabled(True)
|
||||||
self._toggle_fullscreen_action.connect(
|
self._toggle_fullscreen_action.connect('activate',
|
||||||
'activate',
|
self.on_menu_toggle_fullscreen)
|
||||||
self.on_menu_toggle_fullscreen
|
|
||||||
)
|
|
||||||
self.add_action(self._toggle_fullscreen_action)
|
self.add_action(self._toggle_fullscreen_action)
|
||||||
self._search_library_action = Gio.SimpleAction.new(
|
self._search_library_action = Gio.SimpleAction.new(
|
||||||
"search-library",
|
"search-library", None)
|
||||||
None
|
|
||||||
)
|
|
||||||
self._search_library_action.set_enabled(True)
|
self._search_library_action.set_enabled(True)
|
||||||
self._search_library_action.connect(
|
self._search_library_action.connect('activate',
|
||||||
'activate',
|
self.on_menu_search_library)
|
||||||
self.on_menu_search_library
|
|
||||||
)
|
|
||||||
self.add_action(self._search_library_action)
|
self.add_action(self._search_library_action)
|
||||||
|
|
||||||
# Menu callbacks
|
# Menu callbacks
|
||||||
|
|
@ -381,9 +272,8 @@ class Window(Adw.ApplicationWindow):
|
||||||
|
|
||||||
def on_menu_panel(self, action, value):
|
def on_menu_panel(self, action, value):
|
||||||
action.set_state(value)
|
action.set_state(value)
|
||||||
self.panel_stack.set_visible_child(
|
self.panel_stack.set_visible_child(self._panels[int(
|
||||||
self._panels[int(value.get_string())]
|
value.get_string())])
|
||||||
)
|
|
||||||
|
|
||||||
def on_menu_toggle_fullscreen(self, action, value):
|
def on_menu_toggle_fullscreen(self, action, value):
|
||||||
self.panel_stack.set_visible_child(self._cover_panel)
|
self.panel_stack.set_visible_child(self._cover_panel)
|
||||||
|
|
@ -425,7 +315,7 @@ class Window(Adw.ApplicationWindow):
|
||||||
@Gtk.Template.Callback()
|
@Gtk.Template.Callback()
|
||||||
def on_headerbar_volume_changed(self, widget, value):
|
def on_headerbar_volume_changed(self, widget, value):
|
||||||
if not self._setting_volume:
|
if not self._setting_volume:
|
||||||
self._mcg.set_volume(int(value*100))
|
self._mcg.set_volume(int(value * 100))
|
||||||
|
|
||||||
@Gtk.Template.Callback()
|
@Gtk.Template.Callback()
|
||||||
def on_headerbar_playpause_toggled(self, widget):
|
def on_headerbar_playpause_toggled(self, widget):
|
||||||
|
|
@ -450,31 +340,20 @@ class Window(Adw.ApplicationWindow):
|
||||||
self.toolbar_view.add_top_bar(self.headerbar)
|
self.toolbar_view.add_top_bar(self.headerbar)
|
||||||
self.toolbar_view.remove(panel.get_headerbar_standalone())
|
self.toolbar_view.remove(panel.get_headerbar_standalone())
|
||||||
|
|
||||||
def on_connection_panel_connection_changed(
|
def on_connection_panel_connection_changed(self, widget, host, port,
|
||||||
self,
|
password):
|
||||||
widget,
|
|
||||||
host,
|
|
||||||
port,
|
|
||||||
password
|
|
||||||
):
|
|
||||||
self._settings.set_string(Window.SETTING_HOST, host)
|
self._settings.set_string(Window.SETTING_HOST, host)
|
||||||
self._settings.set_int(Window.SETTING_PORT, port)
|
self._settings.set_int(Window.SETTING_PORT, port)
|
||||||
if use_keyring:
|
if use_keyring:
|
||||||
if password:
|
if password:
|
||||||
keyring.set_password(
|
keyring.set_password(ZeroconfProvider.KEYRING_SYSTEM,
|
||||||
ZeroconfProvider.KEYRING_SYSTEM,
|
ZeroconfProvider.KEYRING_USERNAME,
|
||||||
ZeroconfProvider.KEYRING_USERNAME,
|
password)
|
||||||
password
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
if keyring.get_password(
|
if keyring.get_password(ZeroconfProvider.KEYRING_SYSTEM,
|
||||||
ZeroconfProvider.KEYRING_SYSTEM,
|
ZeroconfProvider.KEYRING_USERNAME):
|
||||||
ZeroconfProvider.KEYRING_USERNAME
|
keyring.delete_password(ZeroconfProvider.KEYRING_SYSTEM,
|
||||||
):
|
ZeroconfProvider.KEYRING_USERNAME)
|
||||||
keyring.delete_password(
|
|
||||||
ZeroconfProvider.KEYRING_SYSTEM,
|
|
||||||
ZeroconfProvider.KEYRING_USERNAME
|
|
||||||
)
|
|
||||||
|
|
||||||
def on_playlist_panel_clear_playlist(self, widget):
|
def on_playlist_panel_clear_playlist(self, widget):
|
||||||
self._mcg.clear_playlist()
|
self._mcg.clear_playlist()
|
||||||
|
|
@ -520,10 +399,8 @@ class Window(Adw.ApplicationWindow):
|
||||||
|
|
||||||
def on_library_panel_item_size_changed(self, widget, size):
|
def on_library_panel_item_size_changed(self, widget, size):
|
||||||
self._playlist_panel.set_item_size(size)
|
self._playlist_panel.set_item_size(size)
|
||||||
self._settings.set_int(
|
self._settings.set_int(Window.SETTING_ITEM_SIZE,
|
||||||
Window.SETTING_ITEM_SIZE,
|
self._library_panel.get_item_size())
|
||||||
self._library_panel.get_item_size()
|
|
||||||
)
|
|
||||||
|
|
||||||
def on_library_panel_sort_order_changed(self, widget, sort_order):
|
def on_library_panel_sort_order_changed(self, widget, sort_order):
|
||||||
self._settings.set_enum(Window.SETTING_SORT_ORDER, sort_order)
|
self._settings.set_enum(Window.SETTING_SORT_ORDER, sort_order)
|
||||||
|
|
@ -555,18 +432,8 @@ class Window(Adw.ApplicationWindow):
|
||||||
self._clear_playlist_action.set_enabled(False)
|
self._clear_playlist_action.set_enabled(False)
|
||||||
self._panel_action.set_enabled(False)
|
self._panel_action.set_enabled(False)
|
||||||
|
|
||||||
def on_mcg_status(
|
def on_mcg_status(self, state, album, pos, time, volume, file, audio,
|
||||||
self,
|
bitrate, error):
|
||||||
state,
|
|
||||||
album,
|
|
||||||
pos,
|
|
||||||
time,
|
|
||||||
volume,
|
|
||||||
file,
|
|
||||||
audio,
|
|
||||||
bitrate,
|
|
||||||
error
|
|
||||||
):
|
|
||||||
# Album
|
# Album
|
||||||
GObject.idle_add(self._cover_panel.set_album, album)
|
GObject.idle_add(self._cover_panel.set_album, album)
|
||||||
if not album and self._state.get_property(WindowState.IS_FULLSCREENED):
|
if not album and self._state.get_property(WindowState.IS_FULLSCREENED):
|
||||||
|
|
@ -588,32 +455,17 @@ class Window(Adw.ApplicationWindow):
|
||||||
if error:
|
if error:
|
||||||
self._show_error(error)
|
self._show_error(error)
|
||||||
|
|
||||||
def on_mcg_stats(
|
def on_mcg_stats(self, artists, albums, songs, dbplaytime, playtime,
|
||||||
self,
|
uptime):
|
||||||
artists,
|
self._server_panel.set_stats(artists, albums, songs, dbplaytime,
|
||||||
albums,
|
playtime, uptime)
|
||||||
songs,
|
|
||||||
dbplaytime,
|
|
||||||
playtime,
|
|
||||||
uptime
|
|
||||||
):
|
|
||||||
self._server_panel.set_stats(
|
|
||||||
artists,
|
|
||||||
albums,
|
|
||||||
songs,
|
|
||||||
dbplaytime,
|
|
||||||
playtime,
|
|
||||||
uptime
|
|
||||||
)
|
|
||||||
|
|
||||||
def on_mcg_load_output_devices(self, devices):
|
def on_mcg_load_output_devices(self, devices):
|
||||||
self._server_panel.set_output_devices(devices)
|
self._server_panel.set_output_devices(devices)
|
||||||
|
|
||||||
def on_mcg_load_playlist(self, playlist):
|
def on_mcg_load_playlist(self, playlist):
|
||||||
self._playlist_panel.set_playlist(
|
self._playlist_panel.set_playlist(self._connection_panel.get_host(),
|
||||||
self._connection_panel.get_host(),
|
playlist)
|
||||||
playlist
|
|
||||||
)
|
|
||||||
|
|
||||||
def on_mcg_init_albums(self):
|
def on_mcg_init_albums(self):
|
||||||
GObject.idle_add(self._library_panel.init_albums)
|
GObject.idle_add(self._library_panel.init_albums)
|
||||||
|
|
@ -622,10 +474,8 @@ class Window(Adw.ApplicationWindow):
|
||||||
GObject.idle_add(self._library_panel.load_albums)
|
GObject.idle_add(self._library_panel.load_albums)
|
||||||
|
|
||||||
def on_mcg_load_albums(self, albums):
|
def on_mcg_load_albums(self, albums):
|
||||||
self._library_panel.set_albums(
|
self._library_panel.set_albums(self._connection_panel.get_host(),
|
||||||
self._connection_panel.get_host(),
|
albums)
|
||||||
albums
|
|
||||||
)
|
|
||||||
|
|
||||||
def on_mcg_load_albumart(self, album, data):
|
def on_mcg_load_albumart(self, album, data):
|
||||||
self._cover_panel.set_albumart(album, data)
|
self._cover_panel.set_albumart(album, data)
|
||||||
|
|
@ -673,13 +523,12 @@ class Window(Adw.ApplicationWindow):
|
||||||
self._headerbar_connected()
|
self._headerbar_connected()
|
||||||
self._set_headerbar_sensitive(True, False)
|
self._set_headerbar_sensitive(True, False)
|
||||||
self.content_stack.set_visible_child(self.panel_stack)
|
self.content_stack.set_visible_child(self.panel_stack)
|
||||||
self.panel_stack.set_visible_child(
|
self.panel_stack.set_visible_child(self._panels[self._settings.get_int(
|
||||||
self._panels[self._settings.get_int(Window.SETTING_PANEL)]
|
Window.SETTING_PANEL)])
|
||||||
)
|
|
||||||
|
|
||||||
def _connect_disconnected(self):
|
def _connect_disconnected(self):
|
||||||
self._playlist_panel.stop_threads();
|
self._playlist_panel.stop_threads()
|
||||||
self._library_panel.stop_threads();
|
self._library_panel.stop_threads()
|
||||||
self._headerbar_disconnected()
|
self._headerbar_disconnected()
|
||||||
self._set_headerbar_sensitive(False, False)
|
self._set_headerbar_sensitive(False, False)
|
||||||
self._save_visible_panel()
|
self._save_visible_panel()
|
||||||
|
|
@ -688,12 +537,9 @@ class Window(Adw.ApplicationWindow):
|
||||||
|
|
||||||
def _fullscreen(self, fullscreened_new):
|
def _fullscreen(self, fullscreened_new):
|
||||||
if fullscreened_new != self._state.get_property(
|
if fullscreened_new != self._state.get_property(
|
||||||
WindowState.IS_FULLSCREENED
|
WindowState.IS_FULLSCREENED):
|
||||||
):
|
self._state.set_property(WindowState.IS_FULLSCREENED,
|
||||||
self._state.set_property(
|
fullscreened_new)
|
||||||
WindowState.IS_FULLSCREENED,
|
|
||||||
fullscreened_new
|
|
||||||
)
|
|
||||||
if self._state.get_property(WindowState.IS_FULLSCREENED):
|
if self._state.get_property(WindowState.IS_FULLSCREENED):
|
||||||
self.headerbar.hide()
|
self.headerbar.hide()
|
||||||
self._cover_panel.set_fullscreen(True)
|
self._cover_panel.set_fullscreen(True)
|
||||||
|
|
@ -705,22 +551,18 @@ class Window(Adw.ApplicationWindow):
|
||||||
|
|
||||||
def _save_visible_panel(self):
|
def _save_visible_panel(self):
|
||||||
panel_index_selected = self._panels.index(
|
panel_index_selected = self._panels.index(
|
||||||
self.panel_stack.get_visible_child()
|
self.panel_stack.get_visible_child())
|
||||||
)
|
|
||||||
self._settings.set_int(Window.SETTING_PANEL, panel_index_selected)
|
self._settings.set_int(Window.SETTING_PANEL, panel_index_selected)
|
||||||
|
|
||||||
def _set_menu_visible_panel(self):
|
def _set_menu_visible_panel(self):
|
||||||
panel_index_selected = self._panels.index(
|
panel_index_selected = self._panels.index(
|
||||||
self.panel_stack.get_visible_child()
|
self.panel_stack.get_visible_child())
|
||||||
)
|
|
||||||
self._panel_action.set_state(
|
self._panel_action.set_state(
|
||||||
GLib.Variant.new_string(str(panel_index_selected))
|
GLib.Variant.new_string(str(panel_index_selected)))
|
||||||
)
|
|
||||||
|
|
||||||
def _set_visible_toolbar(self):
|
def _set_visible_toolbar(self):
|
||||||
panel_index_selected = self._panels.index(
|
panel_index_selected = self._panels.index(
|
||||||
self.panel_stack.get_visible_child()
|
self.panel_stack.get_visible_child())
|
||||||
)
|
|
||||||
toolbar = self._panels[panel_index_selected].get_toolbar()
|
toolbar = self._panels[panel_index_selected].get_toolbar()
|
||||||
self.toolbar_stack.set_visible_child(toolbar)
|
self.toolbar_stack.set_visible_child(toolbar)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,16 +27,8 @@ class ZeroconfProvider(client.Base):
|
||||||
if use_avahi:
|
if use_avahi:
|
||||||
self._start_client()
|
self._start_client()
|
||||||
|
|
||||||
def on_new_service(
|
def on_new_service(self, browser, interface, protocol, name, type, domain,
|
||||||
self,
|
flags):
|
||||||
browser,
|
|
||||||
interface,
|
|
||||||
protocol,
|
|
||||||
name,
|
|
||||||
type,
|
|
||||||
domain,
|
|
||||||
flags
|
|
||||||
):
|
|
||||||
#if not (flags & Avahi.LookupResultFlags.GA_LOOKUP_RESULT_LOCAL):
|
#if not (flags & Avahi.LookupResultFlags.GA_LOOKUP_RESULT_LOCAL):
|
||||||
service_resolver = Avahi.ServiceResolver(
|
service_resolver = Avahi.ServiceResolver(
|
||||||
interface=interface,
|
interface=interface,
|
||||||
|
|
@ -52,22 +44,11 @@ class ZeroconfProvider(client.Base):
|
||||||
service_resolver.attach(self._client)
|
service_resolver.attach(self._client)
|
||||||
self._service_resolvers.append(service_resolver)
|
self._service_resolvers.append(service_resolver)
|
||||||
|
|
||||||
def on_found(
|
def on_found(self, resolver, interface, protocol, name, type, domain, host,
|
||||||
self,
|
date, port, *args):
|
||||||
resolver,
|
|
||||||
interface,
|
|
||||||
protocol,
|
|
||||||
name,
|
|
||||||
type,
|
|
||||||
domain,
|
|
||||||
host,
|
|
||||||
date,
|
|
||||||
port,
|
|
||||||
*args
|
|
||||||
):
|
|
||||||
if (host, port) not in self._services.keys():
|
if (host, port) not in self._services.keys():
|
||||||
service = (name,host,port)
|
service = (name, host, port)
|
||||||
self._services[(host,port)] = service
|
self._services[(host, port)] = service
|
||||||
self._callback(ZeroconfProvider.SIGNAL_SERVICE_NEW, service)
|
self._callback(ZeroconfProvider.SIGNAL_SERVICE_NEW, service)
|
||||||
|
|
||||||
def on_failure(self, resolver, date):
|
def on_failure(self, resolver, date):
|
||||||
|
|
@ -76,16 +57,16 @@ class ZeroconfProvider(client.Base):
|
||||||
|
|
||||||
def _start_client(self):
|
def _start_client(self):
|
||||||
self._logger.info("Starting Avahi client")
|
self._logger.info("Starting Avahi client")
|
||||||
self._client = Avahi.Client(flags=0,)
|
self._client = Avahi.Client(flags=0, )
|
||||||
try:
|
try:
|
||||||
self._client.start()
|
self._client.start()
|
||||||
# Browser
|
# Browser
|
||||||
self._service_browser = Avahi.ServiceBrowser(
|
self._service_browser = Avahi.ServiceBrowser(
|
||||||
domain='local',
|
domain='local',
|
||||||
flags=0, interface=-1,
|
flags=0,
|
||||||
|
interface=-1,
|
||||||
protocol=Avahi.Protocol.GA_PROTOCOL_UNSPEC,
|
protocol=Avahi.Protocol.GA_PROTOCOL_UNSPEC,
|
||||||
type=ZeroconfProvider.TYPE
|
type=ZeroconfProvider.TYPE)
|
||||||
)
|
|
||||||
self._service_browser.connect('new_service', self.on_new_service)
|
self._service_browser.connect('new_service', self.on_new_service)
|
||||||
self._service_browser.attach(self._client)
|
self._service_browser.attach(self._client)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue