Adjust blank lines to match Code Style Guide (see #103)

This commit is contained in:
coderkun 2024-05-26 18:29:10 +02:00
commit 6706695d61
14 changed files with 0 additions and 393 deletions

View file

@ -5,8 +5,6 @@
import os import os
# Set environment # Set environment
srcdir = os.path.abspath(os.path.dirname(__file__)) srcdir = os.path.abspath(os.path.dirname(__file__))
datadir = os.path.join(srcdir, 'data') datadir = os.path.join(srcdir, 'data')
@ -23,19 +21,14 @@ if not os.environ.get('GSETTINGS_SCHEMA_DIR'):
os.environ['GSETTINGS_SCHEMA_DIR'] = datadirdev os.environ['GSETTINGS_SCHEMA_DIR'] = datadirdev
class Environment: class Environment:
"""Wrapper class to access environment settings.""" """Wrapper class to access environment settings."""
def get_srcdir(): def get_srcdir():
return srcdir return srcdir
def get_data(subdir): def get_data(subdir):
return os.path.join(datadir, subdir) return os.path.join(datadir, subdir)
def get_locale(): def get_locale():
return localedir return localedir

View file

@ -8,8 +8,6 @@ gi.require_version('Adw', '1')
from gi.repository import Gtk, GObject, Adw 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'
@ -21,16 +19,13 @@ class AlbumHeaderbar(Adw.Bin):
standalone_title = Gtk.Template.Child() standalone_title = Gtk.Template.Child()
standalone_artist = Gtk.Template.Child() standalone_artist = Gtk.Template.Child()
def __init__(self): def __init__(self):
super().__init__() super().__init__()
@Gtk.Template.Callback() @Gtk.Template.Callback()
def on_close_clicked(self, widget): def on_close_clicked(self, widget):
self.emit('close') self.emit('close')
def set_album(self, album): def set_album(self, album):
self.standalone_title.set_text(album.get_title()) self.standalone_title.set_text(album.get_title())
self.standalone_artist.set_text(", ".join(album.get_albumartists())) self.standalone_artist.set_text(", ".join(album.get_albumartists()))

View file

@ -12,14 +12,11 @@ from gi.repository import Gio, Gtk, Gdk, GLib, Adw
from .window import Window from .window import Window
class Application(Gtk.Application): class Application(Gtk.Application):
TITLE = "CoverGrid" TITLE = "CoverGrid"
ID = 'xyz.suruatoel.mcg' ID = 'xyz.suruatoel.mcg'
DOMAIN = 'mcg' DOMAIN = 'mcg'
def __init__(self): def __init__(self):
super().__init__(application_id=Application.ID, flags=Gio.ApplicationFlags.FLAGS_NONE) super().__init__(application_id=Application.ID, flags=Gio.ApplicationFlags.FLAGS_NONE)
self._window = None self._window = None
@ -38,7 +35,6 @@ class Application(Gtk.Application):
self.set_accels_for_action('win.panel("2")', ['<primary>KP_3']) self.set_accels_for_action('win.panel("2")', ['<primary>KP_3'])
self.set_accels_for_action('win.panel("3")', ['<primary>KP_4']) self.set_accels_for_action('win.panel("3")', ['<primary>KP_4'])
def do_startup(self): def do_startup(self):
Gtk.Application.do_startup(self) Gtk.Application.do_startup(self)
self._setup_logging() self._setup_logging()
@ -48,14 +44,12 @@ class Application(Gtk.Application):
self._setup_actions() self._setup_actions()
self._setup_adw() self._setup_adw()
def do_activate(self): def do_activate(self):
Gtk.Application.do_activate(self) Gtk.Application.do_activate(self)
if not self._window: if not self._window:
self._window = Window(self, Application.TITLE, self._settings) self._window = Window(self, Application.TITLE, self._settings)
self._window.present() self._window.present()
def on_menu_info(self, action, value): def on_menu_info(self, action, value):
self._info_dialog = Adw.AboutDialog() self._info_dialog = Adw.AboutDialog()
self._info_dialog.set_application_icon("xyz.suruatoel.mcg") self._info_dialog.set_application_icon("xyz.suruatoel.mcg")
@ -67,27 +61,22 @@ class Application(Gtk.Application):
self._info_dialog.set_issue_url("https://git.suruatoel.xyz/coderkun/mcg") self._info_dialog.set_issue_url("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)
def _set_default_settings(self): def _set_default_settings(self):
style_manager = Adw.StyleManager.get_default() style_manager = Adw.StyleManager.get_default()
style_manager.set_color_scheme(Adw.ColorScheme.PREFER_DARK) style_manager.set_color_scheme(Adw.ColorScheme.PREFER_DARK)
def _load_css(self): def _load_css(self):
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'))
@ -97,7 +86,6 @@ class Application(Gtk.Application):
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)
action.connect('activate', self.on_menu_info) action.connect('activate', self.on_menu_info)
@ -106,11 +94,9 @@ class Application(Gtk.Application):
action.connect('activate', self.on_menu_quit) action.connect('activate', self.on_menu_quit)
self.add_action(action) self.add_action(action)
def _get_resource_path(self, path): def _get_resource_path(self, path):
return "/{}/{}".format(Application.ID.replace('.', '/'), path) return "/{}/{}".format(Application.ID.replace('.', '/'), path)
def _setup_adw(self): def _setup_adw(self):
Adw.HeaderBar() Adw.HeaderBar()
Adw.ToolbarView() Adw.ToolbarView()

View file

@ -15,14 +15,11 @@ from mcg.utils import SortOrder
from mcg.utils import Utils from mcg.utils import Utils
class MPDException(Exception): class MPDException(Exception):
def __init__(self, error): def __init__(self, error):
super(MPDException, self).__init__(self._parse_error(error)) super(MPDException, self).__init__(self._parse_error(error))
self._error = error self._error = error
def _parse_error(self, error): def _parse_error(self, error):
if error: if error:
parts = re.match("\[(\d+)@(\d+)\]\s\{(\w+)\}\s(.*)", error) parts = re.match("\[(\d+)@(\d+)\]\s\{(\w+)\}\s(.*)", error)
@ -33,19 +30,15 @@ class MPDException(Exception):
return parts.group(4) return parts.group(4)
return error return error
def get_error(self): def get_error(self):
return self._error return self._error
def get_error_number(self): def get_error_number(self):
return self._error_number return self._error_number
def get_command_number(self): def get_command_number(self):
return self._command_number return self._command_number
def get_command_name(self): def get_command_name(self):
return self._command_name return self._command_name
@ -62,53 +55,41 @@ class CommandException(MPDException):
pass pass
class Future(concurrent.futures.Future): class Future(concurrent.futures.Future):
def __init__(self, signal): def __init__(self, signal):
concurrent.futures.Future.__init__(self) concurrent.futures.Future.__init__(self)
self._signal = signal self._signal = signal
def get_signal(self): def get_signal(self):
return self._signal return self._signal
class Base(): class Base():
def __init__(self): def __init__(self):
self._callbacks = {} self._callbacks = {}
def connect_signal(self, signal, callback): def connect_signal(self, signal, callback):
"""Connect a callback function to a signal (event).""" """Connect a callback function to a signal (event)."""
self._callbacks[signal] = callback self._callbacks[signal] = callback
def disconnect_signal(self, signal): def disconnect_signal(self, signal):
"""Disconnect a callback function from a signal (event).""" """Disconnect a callback function from a signal (event)."""
if self._has_callback(signal): if self._has_callback(signal):
del self._callbacks[signal] del self._callbacks[signal]
def _has_callback(self, signal): def _has_callback(self, signal):
"""Check if there is a registered callback function for a signal.""" """Check if there is a registered callback function for a signal."""
return signal in self._callbacks return signal in self._callbacks
def _callback(self, signal, *data): def _callback(self, signal, *data):
if signal in self._callbacks: if signal in self._callbacks:
callback = self._callbacks[signal] callback = self._callbacks[signal]
callback(*data) callback(*data)
def _callback_future(self, future): def _callback_future(self, future):
self._callback(future.get_signal(), *future.result()) self._callback(future.get_signal(), *future.result())
class Client(Base): class Client(Base):
"""Client library for handling the connection to the Music Player Daemon. """Client library for handling the connection to the Music Player Daemon.
@ -148,8 +129,6 @@ class Client(Base):
# Buffer size for reading from socket # Buffer size for reading from socket
SOCKET_BUFSIZE = 4096 SOCKET_BUFSIZE = 4096
def __init__(self): def __init__(self):
"""Set class variables and instantiates the Client.""" """Set class variables and instantiates the Client."""
Base.__init__(self) Base.__init__(self)
@ -166,11 +145,9 @@ class Client(Base):
self._playlist = [] self._playlist = []
self._state = None self._state = None
def get_logger(self): def get_logger(self):
return self._logger return self._logger
# Client commands # Client commands
def connect(self, host, port, password=None): def connect(self, host, port, password=None):
@ -183,132 +160,108 @@ class Client(Base):
self._stop.clear() self._stop.clear()
self._start_worker() self._start_worker()
def is_connected(self): def is_connected(self):
"""Return the connection status.""" """Return the connection status."""
return self._worker is not None and self._worker.is_alive() return self._worker is not None and self._worker.is_alive()
def disconnect(self): def disconnect(self):
"""Disconnect from the connected MPD.""" """Disconnect from the connected MPD."""
self._logger.info("disconnect") self._logger.info("disconnect")
self._stop.set() self._stop.set()
self._add_action(self._disconnect) self._add_action(self._disconnect)
def join(self): def join(self):
self._actions.join() self._actions.join()
def get_status(self): def get_status(self):
"""Determine the current status.""" """Determine the current status."""
self._logger.info("get status") self._logger.info("get status")
self._add_action_signal(Client.SIGNAL_STATUS, self._get_status) self._add_action_signal(Client.SIGNAL_STATUS, self._get_status)
def get_stats(self): def get_stats(self):
"""Load statistics.""" """Load statistics."""
self._logger.info("get stats") self._logger.info("get stats")
self._add_action_signal(Client.SIGNAL_STATS, self._get_stats) self._add_action_signal(Client.SIGNAL_STATS, self._get_stats)
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(Client.SIGNAL_LOAD_OUTPUT_DEVICES, self._get_output_devices) self._add_action_signal(Client.SIGNAL_LOAD_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."""
self._logger.info("enable output device") self._logger.info("enable output device")
self._add_action(self._enable_output_device, device, enabled) self._add_action(self._enable_output_device, device, enabled)
def load_albums(self): def load_albums(self):
self._logger.info("load albums") self._logger.info("load albums")
self._add_action_signal(Client.SIGNAL_LOAD_ALBUMS, self._load_albums) self._add_action_signal(Client.SIGNAL_LOAD_ALBUMS, self._load_albums)
def update(self): def update(self):
self._logger.info("update") self._logger.info("update")
self._add_action(self._update) self._add_action(self._update)
def load_playlist(self): def load_playlist(self):
self._logger.info("load playlist") self._logger.info("load playlist")
self._add_action_signal(Client.SIGNAL_LOAD_PLAYLIST, self._load_playlist) self._add_action_signal(Client.SIGNAL_LOAD_PLAYLIST, self._load_playlist)
def clear_playlist(self): def clear_playlist(self):
"""Clear the current playlist""" """Clear the current playlist"""
self._logger.info("clear playlist") self._logger.info("clear playlist")
self._add_action(self._clear_playlist) self._add_action(self._clear_playlist)
def remove_album_from_playlist(self, album): def remove_album_from_playlist(self, album):
"""Remove the given album from the playlist.""" """Remove the given album from the playlist."""
self._logger.info("remove album from playlist") self._logger.info("remove album from playlist")
self._add_action(self._remove_album_from_playlist, album) self._add_action(self._remove_album_from_playlist, album)
def remove_albums_from_playlist(self, albums): def remove_albums_from_playlist(self, albums):
"""Remove multiple albums from the playlist in one step.""" """Remove multiple albums from the playlist in one step."""
self._logger.info("remove multiple albums from playlist") self._logger.info("remove multiple albums from playlist")
self._add_action(self._remove_albums_from_playlist, albums) self._add_action(self._remove_albums_from_playlist, albums)
def play_album_from_playlist(self, album): def play_album_from_playlist(self, album):
"""Play the given album from the playlist.""" """Play the given album from the playlist."""
self._logger.info("play album from playlist") self._logger.info("play album from playlist")
self._add_action(self._play_album_from_playlist, album) self._add_action(self._play_album_from_playlist, album)
def playpause(self): def playpause(self):
"""Play or pauses the current state.""" """Play or pauses the current state."""
self._logger.info("playpause") self._logger.info("playpause")
self._add_action(self._playpause) self._add_action(self._playpause)
def play_album(self, album): def play_album(self, album):
"""Add the given album to the queue and play it immediately.""" """Add the given album to the queue and play it immediately."""
self._logger.info("play album") self._logger.info("play album")
self._add_action(self._play_album, album) self._add_action(self._play_album, album)
def queue_album(self, album): def queue_album(self, album):
"""Add the given album to the queue.""" """Add the given album to the queue."""
self._logger.info("play album") self._logger.info("play album")
self._add_action(self._queue_album, album) self._add_action(self._queue_album, album)
def queue_albums(self, albums): def queue_albums(self, albums):
"""Add the given albums to the queue.""" """Add the given albums to the queue."""
self._logger.info("play albums") self._logger.info("play albums")
self._add_action(self._queue_albums, albums) self._add_action(self._queue_albums, albums)
def seek(self, pos, time): def seek(self, pos, time):
"""Seeks to a song at a position""" """Seeks to a song at a position"""
self._logger.info("seek") self._logger.info("seek")
self._add_action(self._seek, pos, time) self._add_action(self._seek, pos, time)
def stop(self): def stop(self):
self._logger.info("stop") self._logger.info("stop")
self._add_action(self._stop) self._add_action(self._stop)
def set_volume(self, volume): def set_volume(self, volume):
self._logger.info("set volume") self._logger.info("set volume")
self._add_action(self._set_volume, volume) self._add_action(self._set_volume, volume)
def get_albumart(self, album): def get_albumart(self, album):
self._logger.info("get albumart") self._logger.info("get albumart")
self._add_action_signal(Client.SIGNAL_LOAD_ALBUMART, self._get_albumart, album) self._add_action_signal(Client.SIGNAL_LOAD_ALBUMART, 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")
future = concurrent.futures.Future() future = concurrent.futures.Future()
@ -316,7 +269,6 @@ class Client(Base):
(_, albumart) = future.result() (_, albumart) = future.result()
return albumart return albumart
# Private methods # Private methods
def _connect(self, host, port, password): def _connect(self, host, port, password):
@ -335,7 +287,6 @@ class Client(Base):
except OSError as e: except OSError as e:
raise ConnectionException("connection failed: {}".format(e)) raise ConnectionException("connection failed: {}".format(e))
def _connect_socket(self, host, port): def _connect_socket(self, host, port):
sock = None sock = None
error = None error = None
@ -356,7 +307,6 @@ class Client(Base):
else: else:
raise ConnectionException("no suitable socket") raise ConnectionException("no suitable socket")
def _greet(self): def _greet(self):
greeting = self._read_line() greeting = self._read_line()
self._logger.debug("greeting: %s", greeting.strip()) self._logger.debug("greeting: %s", greeting.strip())
@ -366,12 +316,10 @@ class Client(Base):
self._protocol_version = greeting[len(Client.PROTOCOL_GREETING):].strip() self._protocol_version = greeting[len(Client.PROTOCOL_GREETING):].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):
self._logger.info("disconnecting") self._logger.info("disconnecting")
self._disconnect_socket() self._disconnect_socket()
def _disconnect_socket(self): def _disconnect_socket(self):
if self._sock_write is not None: if self._sock_write is not None:
self._sock_write.close() self._sock_write.close()
@ -382,7 +330,6 @@ class Client(Base):
self._logger.info("disconnected") self._logger.info("disconnected")
self._set_connection_status(False) self._set_connection_status(False)
def _idle(self): def _idle(self):
"""React to idle events from MPD.""" """React to idle events from MPD."""
self._logger.info("idle") self._logger.info("idle")
@ -410,13 +357,11 @@ class Client(Base):
self.get_output_devices() self.get_output_devices()
self.get_status() self.get_status()
def _noidle(self): def _noidle(self):
if self._idling: if self._idling:
self._logger.debug("noidle") self._logger.debug("noidle")
self._write("noidle") self._write("noidle")
def _get_status(self): def _get_status(self):
"""Action: Perform the real status determination.""" """Action: Perform the real status determination."""
self._logger.info("getting status") self._logger.info("getting status")
@ -471,7 +416,6 @@ class Client(Base):
bitrate = status['bitrate'] bitrate = status['bitrate']
return (state, album, pos, time, volume, file, audio, bitrate, error) return (state, album, pos, time, volume, file, audio, bitrate, error)
def _get_stats(self): def _get_stats(self):
"""Action: Perform the real statistics gathering.""" """Action: Perform the real statistics gathering."""
self._logger.info("getting statistics") self._logger.info("getting statistics")
@ -504,7 +448,6 @@ class Client(Base):
uptime = stats['uptime'] uptime = stats['uptime']
return (artists, albums, songs, dbplaytime, playtime, uptime) return (artists, albums, songs, dbplaytime, playtime, uptime)
def _get_output_devices(self): def _get_output_devices(self):
"""Action: Perform the real loading of output devices.""" """Action: Perform the real loading of output devices."""
devices = [] devices = []
@ -514,7 +457,6 @@ class Client(Base):
devices.append(device) devices.append(device)
return (devices, ) return (devices, )
def _enable_output_device(self, device, enabled): def _enable_output_device(self, device, enabled):
"""Action: Perform the real enabling/disabling of an output device.""" """Action: Perform the real enabling/disabling of an output device."""
if enabled: if enabled:
@ -522,7 +464,6 @@ class Client(Base):
else: else:
self._call('disableoutput ', device.get_id()) self._call('disableoutput ', device.get_id())
def _load_albums(self): def _load_albums(self):
"""Action: Perform the real update.""" """Action: Perform the real update."""
self._callback(Client.SIGNAL_INIT_ALBUMS) self._callback(Client.SIGNAL_INIT_ALBUMS)
@ -542,11 +483,9 @@ class Client(Base):
album.add_track(track) album.add_track(track)
return (self._albums, ) return (self._albums, )
def _update(self): def _update(self):
self._call('update') self._call('update')
def _load_playlist(self): def _load_playlist(self):
self._playlist = [] self._playlist = []
for song in self._parse_list(self._call('playlistinfo'), ['file', 'playlist']): for song in self._parse_list(self._call('playlistinfo'), ['file', 'playlist']):
@ -565,19 +504,16 @@ class Client(Base):
album.add_track(track) album.add_track(track)
return (self._playlist, ) return (self._playlist, )
def _clear_playlist(self): def _clear_playlist(self):
"""Action: Perform the real clearing of the current playlist.""" """Action: Perform the real clearing of the current playlist."""
self._call('clear') self._call('clear')
def _remove_album_from_playlist(self, album): def _remove_album_from_playlist(self, album):
self._call_list('command_list_begin') self._call_list('command_list_begin')
for track in album.get_tracks(): for track in album.get_tracks():
self._call_list('deleteid', track.get_id()) self._call_list('deleteid', track.get_id())
self._call('command_list_end') self._call('command_list_end')
def _remove_albums_from_playlist(self, albums): def _remove_albums_from_playlist(self, albums):
self._call_list('command_list_begin') self._call_list('command_list_begin')
for album in albums: for album in albums:
@ -585,12 +521,10 @@ class Client(Base):
self._call_list('deleteid', track.get_id()) self._call_list('deleteid', track.get_id())
self._call('command_list_end') self._call('command_list_end')
def _play_album_from_playlist(self, album): def _play_album_from_playlist(self, album):
if album.get_tracks(): if album.get_tracks():
self._call('playid', album.get_tracks()[0].get_id()) self._call('playid', album.get_tracks()[0].get_id())
def _playpause(self): def _playpause(self):
"""Action: Perform the real play/pause command.""" """Action: Perform the real play/pause command."""
#status = self._parse_dict(self._call('status')) #status = self._parse_dict(self._call('status'))
@ -600,14 +534,12 @@ class Client(Base):
else: else:
self._call('play') self._call('play')
def _play_album(self, album): def _play_album(self, album):
track_ids = self._queue_album(album) track_ids = self._queue_album(album)
if track_ids: if track_ids:
self._logger.info("play track %d", track_ids[0]) self._logger.info("play track %d", track_ids[0])
self._call('playid', track_ids[0]) self._call('playid', track_ids[0])
def _queue_album(self, album): def _queue_album(self, album):
track_ids = [] track_ids = []
if album in self._albums: if album in self._albums:
@ -623,25 +555,20 @@ class Client(Base):
track_ids.append(track_id) track_ids.append(track_id)
return track_ids return track_ids
def _queue_albums(self, albums): def _queue_albums(self, albums):
track_ids = [] track_ids = []
for album in albums: for album in albums:
track_ids.extend(self._queue_album(album)) track_ids.extend(self._queue_album(album))
def _seek(self, pos, time): def _seek(self, pos, time):
self._call('seek', pos, time) self._call('seek', pos, time)
def _stop(self): def _stop(self):
self._call('stop') self._call('stop')
def _set_volume(self, volume): def _set_volume(self, volume):
self._call('setvol', volume) self._call('setvol', volume)
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]
@ -663,7 +590,6 @@ class Client(Base):
return (album, None) return (album, None)
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")
@ -672,7 +598,6 @@ class Client(Base):
self._worker.start() self._worker.start()
self._logger.debug("worker started") self._logger.debug("worker started")
def _run(self): def _run(self):
while not self._stop.is_set() or not self._actions.empty(): while not self._stop.is_set() or not self._actions.empty():
if self._sock is not None and self._actions.empty(): if self._sock is not None and self._actions.empty():
@ -684,7 +609,6 @@ class Client(Base):
self._logger.debug("action done") self._logger.debug("action done")
self._logger.debug("worker finished") self._logger.debug("worker finished")
def _add_action(self, method, *args): def _add_action(self, method, *args):
"""Add an action to the action list.""" """Add an action to the action list."""
self._logger.debug("add action %r (%r)", method.__name__, args) self._logger.debug("add action %r (%r)", method.__name__, args)
@ -695,7 +619,6 @@ class Client(Base):
return future return future
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("add action signal %r: %r (%r)", signal, method.__name__, args) self._logger.debug("add action signal %r: %r (%r)", signal, method.__name__, args)
@ -705,7 +628,6 @@ class Client(Base):
return future return future
def _add_action_future(self, future, method, *args): def _add_action_future(self, future, method, *args):
"""Add an action to the action list based on a futre.""" """Add an action to the action list based on a futre."""
self._logger.debug("add action future %r (%r)", method.__name__, args) self._logger.debug("add action future %r (%r)", method.__name__, args)
@ -713,7 +635,6 @@ class Client(Base):
self._actions.put(action) self._actions.put(action)
self._noidle() self._noidle()
def _work(self, action): def _work(self, action):
(future, method, args) = action (future, method, args) = action
self._logger.debug("work: %r", method.__name__) self._logger.debug("work: %r", method.__name__)
@ -730,7 +651,6 @@ class Client(Base):
future.set_exception(e) future.set_exception(e)
self._callback(Client.SIGNAL_ERROR, e) self._callback(Client.SIGNAL_ERROR, e)
def _call(self, command, *args): def _call(self, command, *args):
try: try:
self._write(command, args) self._write(command, args)
@ -740,7 +660,6 @@ class Client(Base):
self.disconnect() self.disconnect()
self._callback(Client.SIGNAL_ERROR, e) self._callback(Client.SIGNAL_ERROR, e)
def _call_list(self, command, *args): def _call_list(self, command, *args):
try: try:
self._write(command, args) self._write(command, args)
@ -749,7 +668,6 @@ class Client(Base):
self.disconnect() self.disconnect()
self._callback(Client.SIGNAL_ERROR, e) self._callback(Client.SIGNAL_ERROR, e)
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(command, '" "'.join(str(x).replace('"', '\\\"') for x in args)) line = '{} "{}"\n'.format(command, '" "'.join(str(x).replace('"', '\\\"') for x in args))
@ -759,7 +677,6 @@ class Client(Base):
self._sock_write.write(line) self._sock_write.write(line)
self._sock_write.flush() self._sock_write.flush()
def _read(self): def _read(self):
self._logger.debug("reading response") self._logger.debug("reading response")
response = [] response = []
@ -776,7 +693,6 @@ class Client(Base):
self._logger.debug("response: %r", response) self._logger.debug("response: %r", response)
return response return response
def _read_line(self): def _read_line(self):
self._logger.debug("reading line") self._logger.debug("reading line")
@ -800,7 +716,6 @@ class Client(Base):
return data.decode('utf-8') return data.decode('utf-8')
return None return None
def _read_binary(self, command, filename, has_mimetype): def _read_binary(self, command, filename, has_mimetype):
data = None data = None
size = 1 size = 1
@ -849,7 +764,6 @@ class Client(Base):
break break
return data return data
def _read_bytes(self, buf, nbytes): def _read_bytes(self, buf, nbytes):
self._logger.debug("reading bytes") self._logger.debug("reading bytes")
# Use already buffered data # Use already buffered data
@ -863,7 +777,6 @@ class Client(Base):
nbytes_read += self._sock.recv_into(buf_view, nbytes) nbytes_read += self._sock.recv_into(buf_view, nbytes)
return nbytes_read return nbytes_read
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:
@ -872,7 +785,6 @@ class Client(Base):
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):
buf = self._buffer[0:size] buf = self._buffer[0:size]
self._logger.debug("get %d bytes from buffer", len(buf)) self._logger.debug("get %d bytes from buffer", len(buf))
@ -880,12 +792,10 @@ class Client(Base):
self._logger.debug("leaving %d in the buffer", len(self._buffer)) self._logger.debug("leaving %d in the buffer", len(self._buffer))
return buf return buf
def _buffer_set(self, buf): def _buffer_set(self, buf):
self._logger.debug("set %d %s as buffer", len(buf), type(buf)) self._logger.debug("set %d %s as buffer", len(buf), type(buf))
self._buffer = buf self._buffer = buf
def _parse_dict(self, response): def _parse_dict(self, response):
dict = {} dict = {}
if response: if response:
@ -894,7 +804,6 @@ class Client(Base):
dict[key] = value dict[key] = value
return dict return dict
def _parse_list(self, response, delimiters): def _parse_list(self, response, delimiters):
entry = {} entry = {}
if response: if response:
@ -912,12 +821,10 @@ class Client(Base):
if entry: if entry:
yield entry yield entry
def _split_line(self, line): def _split_line(self, line):
parts = line.split(':') parts = line.split(':')
return parts[0].lower(), ':'.join(parts[1:]).lstrip() return parts[0].lower(), ':'.join(parts[1:]).lstrip()
def _extract_album(self, song, lookup=True): def _extract_album(self, song, lookup=True):
album = None album = None
if 'album' not in song: if 'album' not in song:
@ -931,7 +838,6 @@ class Client(Base):
self._albums[id] = album self._albums[id] = album
return album return album
def _extract_track(self, song): def _extract_track(self, song):
track = None track = None
if 'artist' in song and 'title' in song and 'file' in song: if 'artist' in song and 'title' in song and 'file' in song:
@ -948,54 +854,42 @@ class Client(Base):
track.set_last_modified(song['last-modified']) track.set_last_modified(song['last-modified'])
return track return track
def _extract_playlist_track(self, song): def _extract_playlist_track(self, song):
track = self._extract_track(song) track = self._extract_track(song)
if track and 'id' in song and 'pos' in song: if track and 'id' in song and 'pos' in song:
track = MCGPlaylistTrack(track, song['id'], song['pos']) track = MCGPlaylistTrack(track, song['id'], song['pos'])
return track return track
def _set_connection_status(self, status): def _set_connection_status(self, status):
self._callback(Client.SIGNAL_CONNECTION, status) self._callback(Client.SIGNAL_CONNECTION, status)
class OutputDevice: class OutputDevice:
def __init__(self, id, name): def __init__(self, id, name):
self._id = id self._id = id
self._name = name self._name = name
self._enabled = None self._enabled = None
def get_id(self): def get_id(self):
return self._id return self._id
def get_name(self): def get_name(self):
return self._name return self._name
def set_enabled(self, enabled): def set_enabled(self, enabled):
self._enabled = enabled self._enabled = enabled
def is_enabled(self): def is_enabled(self):
return self._enabled return self._enabled
class MCGAlbum: class MCGAlbum:
DEFAULT_ALBUM = 'Various' DEFAULT_ALBUM = 'Various'
_FILE_NAMES = ['cover', 'folder'] _FILE_NAMES = ['cover', 'folder']
_FILE_EXTS = ['jpg', 'png', 'jpeg'] _FILE_EXTS = ['jpg', 'png', 'jpeg']
_FILTER_DELIMITER = ' ' _FILTER_DELIMITER = ' '
def __init__(self, title, host): def __init__(self, title, host):
self._artists = [] self._artists = []
self._albumartists = [] self._albumartists = []
@ -1010,49 +904,39 @@ class MCGAlbum:
self._last_modified = None self._last_modified = None
self._id = Utils.generate_id(title) self._id = Utils.generate_id(title)
def __eq__(self, other): def __eq__(self, other):
return (other and self.get_id() == other.get_id()) return (other and self.get_id() == other.get_id())
def __hash__(self): def __hash__(self):
return hash(self._title) return hash(self._title)
def get_id(self): def get_id(self):
return self._id return self._id
def get_artists(self): def get_artists(self):
if self._albumartists: if self._albumartists:
return [artist for artist in self._artists if artist not in self._albumartists] return [artist for artist in self._artists if artist not in self._albumartists]
return self._artists return self._artists
def get_albumartists(self): def get_albumartists(self):
if self._albumartists: if self._albumartists:
return self._albumartists return self._albumartists
return self._artists return self._artists
def get_title(self): def get_title(self):
return self._title return self._title
def get_dates(self): def get_dates(self):
return self._dates return self._dates
def get_date(self): def get_date(self):
if len(self._dates) == 0: if len(self._dates) == 0:
return None return None
return self._dates[0] return self._dates[0]
def get_path(self): def get_path(self):
return self._path return self._path
def add_track(self, track): def add_track(self, track):
self._tracks.append(track) self._tracks.append(track)
self._length = self._length + track.get_length() self._length = self._length + track.get_length()
@ -1071,19 +955,15 @@ class MCGAlbum:
if not self._last_modified or track.get_last_modified() > self._last_modified: if not self._last_modified or track.get_last_modified() > self._last_modified:
self._last_modified = track.get_last_modified() self._last_modified = track.get_last_modified()
def get_tracks(self): def get_tracks(self):
return self._tracks return self._tracks
def get_length(self): def get_length(self):
return self._length return self._length
def get_last_modified(self): def get_last_modified(self):
return self._last_modified return self._last_modified
def filter(self, filter_string): def filter(self, filter_string):
if len(filter_string) == 0: if len(filter_string) == 0:
return True return True
@ -1109,7 +989,6 @@ class MCGAlbum:
return False return False
return True return True
def compare(album1, album2, criterion=None, reverse=False): def compare(album1, album2, criterion=None, reverse=False):
if criterion == None: if criterion == None:
criterion = SortOrder.TITLE criterion = SortOrder.TITLE
@ -1140,8 +1019,6 @@ class MCGAlbum:
return 1 * reverseMultiplier return 1 * reverseMultiplier
class MCGTrack: class MCGTrack:
def __init__(self, artists, title, file): def __init__(self, artists, title, file):
if type(artists) is not list: if type(artists) is not list:
@ -1160,41 +1037,33 @@ class MCGTrack:
self._date = None self._date = None
self._last_modified = None self._last_modified = None
def __eq__(self, other): def __eq__(self, other):
return self._file == other.get_file() return self._file == other.get_file()
def __hash__(self): def __hash__(self):
return hash(self._file) return hash(self._file)
def get_artists(self): def get_artists(self):
if self._albumartists: if self._albumartists:
return [artist for artist in self._artists if artist not in self._albumartists] return [artist for artist in self._artists if artist not in self._albumartists]
return self._artists return self._artists
def set_albumartists(self, artists): def set_albumartists(self, artists):
if type(artists) is not list: if type(artists) is not list:
artists = [artists] artists = [artists]
self._albumartists = artists self._albumartists = artists
def get_albumartists(self): def get_albumartists(self):
if self._albumartists: if self._albumartists:
return self._albumartists return self._albumartists
return self._artists return self._artists
def get_title(self): def get_title(self):
return self._title return self._title
def get_track(self): def get_track(self):
return self._track return self._track
def set_track(self, track): def set_track(self, track):
if type(track) is list: if type(track) is list:
track = track[0] track = track[0]
@ -1207,29 +1076,23 @@ class MCGTrack:
track = 0 track = 0
self._track = track self._track = track
def get_length(self): def get_length(self):
return self._length return self._length
def set_length(self, length): def set_length(self, length):
self._length = int(length) self._length = int(length)
def get_date(self): def get_date(self):
return self._date return self._date
def set_date(self, date): def set_date(self, date):
if type(date) is list: if type(date) is list:
date = date[0] date = date[0]
self._date = date self._date = date
def get_file(self): def get_file(self):
return self._file return self._file
def set_last_modified(self, date_string): def set_last_modified(self, date_string):
if date_string: if date_string:
try: try:
@ -1237,13 +1100,10 @@ class MCGTrack:
except ValueError as e: except ValueError as e:
self._logger.debug("Invalid date format: %s", date_string) self._logger.debug("Invalid date format: %s", date_string)
def get_last_modified(self): def get_last_modified(self):
return self._last_modified return self._last_modified
class MCGPlaylistTrack(MCGTrack): class MCGPlaylistTrack(MCGTrack):
def __init__(self, track, id, pos): def __init__(self, track, id, pos):
MCGTrack.__init__( MCGTrack.__init__(
@ -1259,51 +1119,40 @@ class MCGPlaylistTrack(MCGTrack):
self._id = int(id) self._id = int(id)
self._pos = int(pos) self._pos = int(pos)
def get_id(self): def get_id(self):
return self._id return self._id
def get_pos(self): def get_pos(self):
return self._pos return self._pos
class MCGConfig(configparser.ConfigParser): class MCGConfig(configparser.ConfigParser):
CONFIG_DIR = '~/.config/mcg/' CONFIG_DIR = '~/.config/mcg/'
def __init__(self, filename): def __init__(self, filename):
configparser.ConfigParser.__init__(self) configparser.ConfigParser.__init__(self)
self._filename = os.path.expanduser(os.path.join(MCGConfig.CONFIG_DIR, filename)) self._filename = os.path.expanduser(os.path.join(MCGConfig.CONFIG_DIR, filename))
self._create_dir() self._create_dir()
def load(self): def load(self):
if os.path.isfile(self._filename): if os.path.isfile(self._filename):
self.read(self._filename) self.read(self._filename)
def save(self): def save(self):
with open(self._filename, 'w') as configfile: with open(self._filename, 'w') as configfile:
self.write(configfile) self.write(configfile)
def _create_dir(self): def _create_dir(self):
dirname = os.path.dirname(self._filename) dirname = os.path.dirname(self._filename)
if not os.path.exists(dirname): if not os.path.exists(dirname):
os.makedirs(dirname) os.makedirs(dirname)
class MCGCache(): class MCGCache():
DIRNAME = '~/.cache/mcg/' DIRNAME = '~/.cache/mcg/'
SIZE_FILENAME = 'size' SIZE_FILENAME = 'size'
_lock = threading.Lock() _lock = threading.Lock()
def __init__(self, host, size): def __init__(self, host, size):
self._logger = logging.getLogger(__name__) self._logger = logging.getLogger(__name__)
self._host = host self._host = host
@ -1313,11 +1162,9 @@ class MCGCache():
os.makedirs(self._dirname) os.makedirs(self._dirname)
self._read_size() self._read_size()
def create_filename(self, album): def create_filename(self, album):
return os.path.join(self._dirname, '-'.join([album.get_id()])) return os.path.join(self._dirname, '-'.join([album.get_id()]))
def _read_size(self): def _read_size(self):
size = 100 size = 100
MCGCache._lock.acquire() MCGCache._lock.acquire()
@ -1338,7 +1185,6 @@ class MCGCache():
f.write(str(self._size)) f.write(str(self._size))
MCGCache._lock.release() MCGCache._lock.release()
def _clear(self): def _clear(self):
for filename in os.listdir(self._dirname): for filename in os.listdir(self._dirname):
path = os.path.join(self._dirname, filename) path = os.path.join(self._dirname, filename)

View file

@ -11,8 +11,6 @@ from gi.repository import Gtk, Gio, GObject, Adw
from mcg.zeroconf import ZeroconfProvider from mcg.zeroconf import ZeroconfProvider
@Gtk.Template(resource_path='/xyz/suruatoel/mcg/ui/connection-panel.ui') @Gtk.Template(resource_path='/xyz/suruatoel/mcg/ui/connection-panel.ui')
class ConnectionPanel(Adw.Bin): class ConnectionPanel(Adw.Bin):
__gtype_name__ = 'McgConnectionPanel' __gtype_name__ = 'McgConnectionPanel'
@ -27,7 +25,6 @@ class ConnectionPanel(Adw.Bin):
port_spinner = Gtk.Template.Child() port_spinner = Gtk.Template.Child()
password_row = Gtk.Template.Child() password_row = Gtk.Template.Child()
def __init__(self, **kwargs): def __init__(self, **kwargs):
super().__init__(**kwargs) super().__init__(**kwargs)
@ -35,7 +32,6 @@ class ConnectionPanel(Adw.Bin):
self._zeroconf_provider = ZeroconfProvider() self._zeroconf_provider = ZeroconfProvider()
self._zeroconf_provider.connect_signal(ZeroconfProvider.SIGNAL_SERVICE_NEW, self.on_new_service) self._zeroconf_provider.connect_signal(ZeroconfProvider.SIGNAL_SERVICE_NEW, self.on_new_service)
def on_new_service(self, service): def on_new_service(self, service):
name, host, port = service name, host, port = service
@ -50,50 +46,40 @@ class ConnectionPanel(Adw.Bin):
self.zeroconf_list.insert(row, -1) self.zeroconf_list.insert(row, -1)
def on_service_selected(self, widget, host, port): def on_service_selected(self, widget, host, port):
self.set_host(host) self.set_host(host)
self.set_port(port) self.set_port(port)
@Gtk.Template.Callback() @Gtk.Template.Callback()
def on_host_entry_apply(self, widget): def on_host_entry_apply(self, widget):
self._call_back() self._call_back()
@Gtk.Template.Callback() @Gtk.Template.Callback()
def on_port_spinner_value_changed(self, widget): def on_port_spinner_value_changed(self, widget):
self._call_back() self._call_back()
def set_host(self, host): def set_host(self, host):
self.host_row.set_text(host) self.host_row.set_text(host)
def get_host(self): def get_host(self):
return self.host_row.get_text() return self.host_row.get_text()
def set_port(self, port): def set_port(self, port):
self.port_spinner.set_value(port) self.port_spinner.set_value(port)
def get_port(self): def get_port(self):
return self.port_spinner.get_value_as_int() return self.port_spinner.get_value_as_int()
def set_password(self, password): def set_password(self, password):
if password is None: if password is None:
password = "" password = ""
self.password_row.set_text(password) self.password_row.set_text(password)
def get_password(self): def get_password(self):
if self.password_row.get_text() == "": if self.password_row.get_text() == "":
return None return None
else: else:
return self.password_entry.get_text() return self.password_entry.get_text()
def _call_back(self): def _call_back(self):
self.emit('connection-changed', self.get_host(), self.get_port(), self.get_password(),) self.emit('connection-changed', self.get_host(), self.get_port(), self.get_password(),)

View file

@ -11,8 +11,6 @@ from gi.repository import Gtk, Gdk, GObject, GdkPixbuf
from mcg.utils import Utils from mcg.utils import Utils
@Gtk.Template(resource_path='/xyz/suruatoel/mcg/ui/cover-panel.ui') @Gtk.Template(resource_path='/xyz/suruatoel/mcg/ui/cover-panel.ui')
class CoverPanel(Gtk.Overlay): class CoverPanel(Gtk.Overlay):
__gtype_name__ = 'McgCoverPanel' __gtype_name__ = 'McgCoverPanel'
@ -42,8 +40,6 @@ class CoverPanel(Gtk.Overlay):
# Songs # Songs
songs_scale = Gtk.Template.Child() songs_scale = Gtk.Template.Child()
def __init__(self, **kwargs): def __init__(self, **kwargs):
super().__init__(**kwargs) super().__init__(**kwargs)
@ -70,25 +66,20 @@ class CoverPanel(Gtk.Overlay):
buttonController.connect('unpaired-release', self.on_songs_scale_released) buttonController.connect('unpaired-release', 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):
return self.toolbar return self.toolbar
def set_selected(self, selected): def set_selected(self, selected):
pass pass
def on_cover_box_pressed(self, widget, npress, x, y): def on_cover_box_pressed(self, widget, npress, x, y):
if self._current_album and npress == 2: if self._current_album and npress == 2:
self.emit('toggle-fullscreen') self.emit('toggle-fullscreen')
def set_width(self, width): def set_width(self, width):
GObject.idle_add(self._resize_image) GObject.idle_add(self._resize_image)
self.cover_info_scroll.set_max_content_width(width // 2) self.cover_info_scroll.set_max_content_width(width // 2)
def on_songs_scale_pressed(self, widget, npress, x, y): def on_songs_scale_pressed(self, widget, npress, x, y):
if self._timer: if self._timer:
GObject.source_remove(self._timer) GObject.source_remove(self._timer)
@ -107,7 +98,6 @@ class CoverPanel(Gtk.Overlay):
time = max(value - time - 1, 0) time = max(value - time - 1, 0)
self.emit('set-song', pos, time) self.emit('set-song', pos, time)
def set_album(self, album): def set_album(self, album):
if album: if album:
# Set labels # Set labels
@ -129,7 +119,6 @@ class CoverPanel(Gtk.Overlay):
self._enable_tracklist() self._enable_tracklist()
self.fullscreen_button.set_sensitive(self._current_album is not None) self.fullscreen_button.set_sensitive(self._current_album is not None)
def set_play(self, pos, time): def set_play(self, pos, time):
if self._timer is not None: if self._timer is not None:
GObject.source_remove(self._timer) GObject.source_remove(self._timer)
@ -141,13 +130,11 @@ class CoverPanel(Gtk.Overlay):
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):
if self._timer is not None: if self._timer is not None:
GObject.source_remove(self._timer) GObject.source_remove(self._timer)
self._timer = None self._timer = None
def set_fullscreen(self, active): def set_fullscreen(self, active):
if active: if active:
self.info_revealer.set_reveal_child(False) self.info_revealer.set_reveal_child(False)
@ -159,7 +146,6 @@ class CoverPanel(Gtk.Overlay):
self.info_revealer.set_reveal_child(True) self.info_revealer.set_reveal_child(True)
GObject.idle_add(self._resize_image) GObject.idle_add(self._resize_image)
def set_albumart(self, album, data): def set_albumart(self, album, data):
if album == self._current_album: if album == self._current_album:
if data: if data:
@ -177,7 +163,6 @@ class CoverPanel(Gtk.Overlay):
# Show image # Show image
GObject.idle_add(self._show_image) GObject.idle_add(self._show_image)
def _set_tracks(self, album): def _set_tracks(self, album):
self.songs_scale.clear_marks() self.songs_scale.clear_marks()
self.songs_scale.set_range(0, album.get_length()) self.songs_scale.set_range(0, album.get_length())
@ -200,7 +185,6 @@ class CoverPanel(Gtk.Overlay):
"{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:
# enable # enable
@ -210,14 +194,12 @@ class CoverPanel(Gtk.Overlay):
# disable # disable
self.info_revealer.set_reveal_child(False) self.info_revealer.set_reveal_child(False)
def _playing(self): def _playing(self):
value = self.songs_scale.get_value() + 1 value = self.songs_scale.get_value() + 1
self.songs_scale.set_value(value) self.songs_scale.set_value(value)
return True return True
def _show_image(self): def _show_image(self):
if self._cover_pixbuf: if self._cover_pixbuf:
self._resize_image() self._resize_image()
@ -226,7 +208,6 @@ class CoverPanel(Gtk.Overlay):
self.cover_stack.set_visible_child(self.cover_default) self.cover_stack.set_visible_child(self.cover_default)
self.cover_spinner.stop() self.cover_spinner.stop()
def _resize_image(self): def _resize_image(self):
"""Diese Methode skaliert das geladene Bild aus dem Pixelpuffer """Diese Methode skaliert das geladene Bild aus dem Pixelpuffer
auf die Größe des Fensters unter Beibehalt der Seitenverhältnisse auf die Größe des Fensters unter Beibehalt der Seitenverhältnisse

View file

@ -19,8 +19,6 @@ from mcg.utils import GridItem
from mcg.utils import SearchFilter from mcg.utils import SearchFilter
@Gtk.Template(resource_path='/xyz/suruatoel/mcg/ui/library-panel.ui') @Gtk.Template(resource_path='/xyz/suruatoel/mcg/ui/library-panel.ui')
class LibraryPanel(Adw.Bin): class LibraryPanel(Adw.Bin):
__gtype_name__ = 'McgLibraryPanel' __gtype_name__ = 'McgLibraryPanel'
@ -37,7 +35,6 @@ class LibraryPanel(Adw.Bin):
'albumart': (GObject.SIGNAL_RUN_FIRST, None, (str,)), 'albumart': (GObject.SIGNAL_RUN_FIRST, None, (str,)),
} }
# Widgets # Widgets
library_stack = Gtk.Template.Child() library_stack = Gtk.Template.Child()
panel_normal = Gtk.Template.Child() panel_normal = Gtk.Template.Child()
@ -74,7 +71,6 @@ class LibraryPanel(Adw.Bin):
standalone_scroll = Gtk.Template.Child() standalone_scroll = Gtk.Template.Child()
standalone_image = Gtk.Template.Child() standalone_image = Gtk.Template.Child()
def __init__(self, client, **kwargs): def __init__(self, client, **kwargs):
super().__init__(**kwargs) super().__init__(**kwargs)
self._logger = logging.getLogger(__name__) self._logger = logging.getLogger(__name__)
@ -121,19 +117,15 @@ class LibraryPanel(Adw.Bin):
buttonController.connect('unpaired-release', self.on_grid_scale_released) buttonController.connect('unpaired-release', 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):
return self._headerbar_standalone return self._headerbar_standalone
def get_toolbar(self): def get_toolbar(self):
return self.toolbar return self.toolbar
def set_selected(self, selected): def set_selected(self, selected):
self._is_selected = selected self._is_selected = selected
@Gtk.Template.Callback() @Gtk.Template.Callback()
def on_select_toggled(self, widget): def on_select_toggled(self, widget):
if self.select_button.get_active(): if self.select_button.get_active():
@ -147,12 +139,10 @@ class LibraryPanel(Adw.Bin):
self.library_grid.set_single_click_activate(True) self.library_grid.set_single_click_activate(True)
self.library_grid.get_style_context().remove_class(Utils.CSS_SELECTION) self.library_grid.get_style_context().remove_class(Utils.CSS_SELECTION)
@Gtk.Template.Callback() @Gtk.Template.Callback()
def on_update_clicked(self, widget): def on_update_clicked(self, widget):
self.emit('update') self.emit('update')
def on_grid_scale_released(self, widget, x, y, npress, sequence): def on_grid_scale_released(self, widget, x, y, npress, sequence):
size = math.floor(self.grid_scale.get_value()) size = math.floor(self.grid_scale.get_value())
range = self.grid_scale.get_adjustment() range = self.grid_scale.get_adjustment()
@ -163,7 +153,6 @@ class LibraryPanel(Adw.Bin):
self._redraw() self._redraw()
GObject.idle_add(self.toolbar_popover.popdown) GObject.idle_add(self.toolbar_popover.popdown)
@Gtk.Template.Callback() @Gtk.Template.Callback()
def on_grid_scale_changed(self, widget): def on_grid_scale_changed(self, widget):
size = math.floor(self.grid_scale.get_value()) size = math.floor(self.grid_scale.get_value())
@ -172,7 +161,6 @@ class LibraryPanel(Adw.Bin):
return return
self._set_widget_grid_size(self.library_grid, size, True) self._set_widget_grid_size(self.library_grid, size, True)
@Gtk.Template.Callback() @Gtk.Template.Callback()
def on_sort_toggled(self, widget): def on_sort_toggled(self, widget):
if widget.get_active(): if widget.get_active():
@ -180,7 +168,6 @@ class LibraryPanel(Adw.Bin):
self._sort_grid_model() self._sort_grid_model()
self.emit('sort-order-changed', self._sort_order) self.emit('sort-order-changed', self._sort_order)
@Gtk.Template.Callback() @Gtk.Template.Callback()
def on_sort_order_toggled(self, button): def on_sort_order_toggled(self, button):
if button.get_active(): if button.get_active():
@ -190,17 +177,14 @@ class LibraryPanel(Adw.Bin):
self._sort_grid_model() self._sort_grid_model()
self.emit('sort-type-changed', button.get_active()) self.emit('sort-type-changed', button.get_active())
def set_size(self, width, height): def set_size(self, width, height):
self._set_marks() self._set_marks()
self._resize_standalone_image() self._resize_standalone_image()
@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(SearchFilter(self.filter_entry.get_text())) self._library_grid_filter.set_filter(SearchFilter(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):
# Get selected album # Get selected album
@ -222,49 +206,40 @@ class LibraryPanel(Adw.Bin):
self.standalone_stack.set_visible_child(self.standalone_spinner) self.standalone_stack.set_visible_child(self.standalone_spinner)
self.standalone_spinner.start() self.standalone_spinner.start()
@Gtk.Template.Callback() @Gtk.Template.Callback()
def on_selection_cancel_clicked(self, widget): def on_selection_cancel_clicked(self, widget):
self.select_button.set_active(False) self.select_button.set_active(False)
@Gtk.Template.Callback() @Gtk.Template.Callback()
def on_selection_add_clicked(self, widget): def on_selection_add_clicked(self, widget):
self.emit('queue-multiple', self._get_selected_albums()) self.emit('queue-multiple', self._get_selected_albums())
self.select_button.set_active(False) self.select_button.set_active(False)
@Gtk.Template.Callback() @Gtk.Template.Callback()
def on_standalone_play_clicked(self, widget): def on_standalone_play_clicked(self, widget):
self.emit('play', self._selected_albums[0].get_id()) self.emit('play', self._selected_albums[0].get_id())
self._close_standalone() self._close_standalone()
@Gtk.Template.Callback() @Gtk.Template.Callback()
def on_standalone_queue_clicked(self, widget): def on_standalone_queue_clicked(self, widget):
self.emit('queue', self._selected_albums[0].get_id()) self.emit('queue', self._selected_albums[0].get_id())
self._close_standalone() self._close_standalone()
def on_standalone_close_clicked(self, widget): def on_standalone_close_clicked(self, widget):
self._close_standalone() self._close_standalone()
def show_search(self): def show_search(self):
self.filter_bar.set_search_mode(True) self.filter_bar.set_search_mode(True)
def set_item_size(self, item_size): def set_item_size(self, item_size):
if self._item_size != item_size: if self._item_size != item_size:
self._item_size = item_size self._item_size = item_size
self.grid_scale.set_value(item_size) self.grid_scale.set_value(item_size)
self._redraw() self._redraw()
def get_item_size(self): def get_item_size(self):
return self._item_size return self._item_size
def set_sort_order(self, sort): def set_sort_order(self, sort):
button = self._toolbar_sort_buttons[sort] button = self._toolbar_sort_buttons[sort]
if button: if button:
@ -273,7 +248,6 @@ class LibraryPanel(Adw.Bin):
button.set_active(True) button.set_active(True)
self._sort_grid_model() self._sort_grid_model()
def set_sort_type(self, sort_type): def set_sort_type(self, sort_type):
sort_type_gtk = Gtk.SortType.DESCENDING if sort_type else Gtk.SortType.ASCENDING sort_type_gtk = Gtk.SortType.DESCENDING if sort_type else Gtk.SortType.ASCENDING
@ -282,25 +256,20 @@ class LibraryPanel(Adw.Bin):
self.toolbar_sort_order_button.set_active(sort_type) self.toolbar_sort_order_button.set_active(sort_type)
self._sort_grid_model() self._sort_grid_model()
def get_sort_type(self): def get_sort_type(self):
return (self._sort_type != Gtk.SortType.ASCENDING) return (self._sort_type != Gtk.SortType.ASCENDING)
def init_albums(self): def init_albums(self):
self.progress_bar.set_text(locale.gettext("Loading albums")) self.progress_bar.set_text(locale.gettext("Loading albums"))
def load_albums(self): def load_albums(self):
self.progress_bar.pulse() self.progress_bar.pulse()
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(target=self._set_albums, args=(host, albums, self._item_size,)).start() threading.Thread(target=self._set_albums, args=(host, 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:
if data: if data:
@ -315,19 +284,15 @@ class LibraryPanel(Adw.Bin):
# Show image # Show image
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(self._library_grid_model.sort, self._grid_model_compare_func, self._sort_order, self._sort_type) GObject.idle_add(self._library_grid_model.sort, self._grid_model_compare_func, 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(item1.get_album(), item2.get_album(), criterion, (order == Gtk.SortType.DESCENDING)) return client.MCGAlbum.compare(item1.get_album(), item2.get_album(), criterion, (order == Gtk.SortType.DESCENDING))
def stop_threads(self): def stop_threads(self):
self._library_stop.set() self._library_stop.set()
def _set_albums(self, host, albums, size): def _set_albums(self, host, albums, size):
self._library_lock.acquire() self._library_lock.acquire()
self._albums = albums self._albums = albums
@ -373,12 +338,10 @@ class LibraryPanel(Adw.Bin):
GObject.idle_add(self.stack.set_visible_child, self.scroll) GObject.idle_add(self.stack.set_visible_child, self.scroll)
self._sort_grid_model() self._sort_grid_model()
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(target=self._set_widget_grid_size_thread, args=(grid_widget, size, vertical,)).start() threading.Thread(target=self._set_widget_grid_size_thread, args=(grid_widget, 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()
self._library_stop.clear() self._library_stop.clear()
@ -409,18 +372,15 @@ class LibraryPanel(Adw.Bin):
self._library_lock.release() self._library_lock.release()
def _show_image(self): def _show_image(self):
self._resize_standalone_image() self._resize_standalone_image()
self.standalone_stack.set_visible_child(self.standalone_scroll) self.standalone_stack.set_visible_child(self.standalone_scroll)
self.standalone_spinner.stop() self.standalone_spinner.stop()
def _redraw(self): def _redraw(self):
if self._albums is not None: if self._albums is not None:
self.set_albums(self._host, self._albums) self.set_albums(self._host, self._albums)
def _set_marks(self): def _set_marks(self):
width = self.scroll.get_width() width = self.scroll.get_width()
if width == self._grid_width: if width == self._grid_width:
@ -441,17 +401,14 @@ class LibraryPanel(Adw.Bin):
None 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)
self.emit('open-standalone') self.emit('open-standalone')
def _close_standalone(self): def _close_standalone(self):
self.library_stack.set_visible_child(self.panel_normal) self.library_stack.set_visible_child(self.panel_normal)
self.emit('close-standalone') self.emit('close-standalone')
def _resize_standalone_image(self): def _resize_standalone_image(self):
"""Diese Methode skaliert das geladene Bild aus dem Pixelpuffer """Diese Methode skaliert das geladene Bild aus dem Pixelpuffer
auf die Größe des Fensters unter Beibehalt der Seitenverhältnisse auf die Größe des Fensters unter Beibehalt der Seitenverhältnisse
@ -481,7 +438,6 @@ class LibraryPanel(Adw.Bin):
self.standalone_image.set_from_pixbuf(pixbuf.scale_simple(width, height, GdkPixbuf.InterpType.HYPER)) self.standalone_image.set_from_pixbuf(pixbuf.scale_simple(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, Utils.STOCK_ICON_DEFAULT,
@ -492,7 +448,6 @@ class LibraryPanel(Adw.Bin):
Gtk.IconLookupFlags.FORCE_SYMBOLIC 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()):

View file

@ -3,7 +3,6 @@ import sys
from .application import Application from .application import Application
def main(version): def main(version):
app = Application() app = Application()
return app.run(sys.argv) return app.run(sys.argv)

View file

@ -16,8 +16,6 @@ from mcg.utils import Utils
from mcg.utils import GridItem from mcg.utils import GridItem
@Gtk.Template(resource_path='/xyz/suruatoel/mcg/ui/playlist-panel.ui') @Gtk.Template(resource_path='/xyz/suruatoel/mcg/ui/playlist-panel.ui')
class PlaylistPanel(Adw.Bin): class PlaylistPanel(Adw.Bin):
__gtype_name__ = 'McgPlaylistPanel' __gtype_name__ = 'McgPlaylistPanel'
@ -31,7 +29,6 @@ class PlaylistPanel(Adw.Bin):
'albumart': (GObject.SIGNAL_RUN_FIRST, None, (str,)), 'albumart': (GObject.SIGNAL_RUN_FIRST, None, (str,)),
} }
# Widgets # Widgets
playlist_stack = Gtk.Template.Child() playlist_stack = Gtk.Template.Child()
panel_normal = Gtk.Template.Child() panel_normal = Gtk.Template.Child()
@ -52,7 +49,6 @@ class PlaylistPanel(Adw.Bin):
standalone_scroll = Gtk.Template.Child() standalone_scroll = Gtk.Template.Child()
standalone_image = Gtk.Template.Child() standalone_image = Gtk.Template.Child()
def __init__(self, client, **kwargs): def __init__(self, client, **kwargs):
super().__init__(**kwargs) super().__init__(**kwargs)
self._client = client self._client = client
@ -78,19 +74,15 @@ class PlaylistPanel(Adw.Bin):
# Playlist Grid # Playlist Grid
self.playlist_grid.set_model(self._playlist_grid_selection_single) self.playlist_grid.set_model(self._playlist_grid_selection_single)
def get_headerbar_standalone(self): def get_headerbar_standalone(self):
return self._headerbar_standalone return self._headerbar_standalone
def get_toolbar(self): def get_toolbar(self):
return self.toolbar return self.toolbar
def set_selected(self, selected): def set_selected(self, selected):
self._is_selected = selected self._is_selected = selected
@Gtk.Template.Callback() @Gtk.Template.Callback()
def on_select_toggled(self, widget): def on_select_toggled(self, widget):
if self.select_button.get_active(): if self.select_button.get_active():
@ -104,12 +96,10 @@ class PlaylistPanel(Adw.Bin):
self.playlist_grid.set_single_click_activate(True) self.playlist_grid.set_single_click_activate(True)
self.playlist_grid.get_style_context().remove_class(Utils.CSS_SELECTION) self.playlist_grid.get_style_context().remove_class(Utils.CSS_SELECTION)
@Gtk.Template.Callback() @Gtk.Template.Callback()
def on_clear_clicked(self, widget): def on_clear_clicked(self, widget):
self.emit('clear-playlist') self.emit('clear-playlist')
@Gtk.Template.Callback() @Gtk.Template.Callback()
def on_playlist_grid_clicked(self, widget, position): def on_playlist_grid_clicked(self, widget, position):
# Get selected album # Get selected album
@ -131,54 +121,44 @@ class PlaylistPanel(Adw.Bin):
self.standalone_stack.set_visible_child(self.standalone_spinner) self.standalone_stack.set_visible_child(self.standalone_spinner)
self.standalone_spinner.start() self.standalone_spinner.start()
@Gtk.Template.Callback() @Gtk.Template.Callback()
def on_selection_cancel_clicked(self, widget): def on_selection_cancel_clicked(self, widget):
self.select_button.set_active(False) self.select_button.set_active(False)
@Gtk.Template.Callback() @Gtk.Template.Callback()
def on_selection_remove_clicked(self, widget): def on_selection_remove_clicked(self, widget):
self.emit('remove-multiple-albums', self._get_selected_albums()) self.emit('remove-multiple-albums', self._get_selected_albums())
self.select_button.set_active(False) self.select_button.set_active(False)
def on_headerbar_close_clicked(self, widget): def on_headerbar_close_clicked(self, widget):
self._close_standalone() self._close_standalone()
@Gtk.Template.Callback() @Gtk.Template.Callback()
def on_standalone_remove_clicked(self, widget): def on_standalone_remove_clicked(self, widget):
self.emit('remove-album', self._get_selected_albums()[0]) self.emit('remove-album', self._get_selected_albums()[0])
self._close_standalone() self._close_standalone()
@Gtk.Template.Callback() @Gtk.Template.Callback()
def on_standalone_play_clicked(self, widget): def on_standalone_play_clicked(self, widget):
self.emit('play', self._get_selected_albums()[0]) self.emit('play', self._get_selected_albums()[0])
self._close_standalone() self._close_standalone()
def set_size(self, width, height): def set_size(self, width, height):
self._resize_standalone_image() self._resize_standalone_image()
def set_item_size(self, item_size): def set_item_size(self, item_size):
if self._item_size != item_size: if self._item_size != item_size:
self._item_size = item_size self._item_size = item_size
self._redraw() self._redraw()
def get_item_size(self): def get_item_size(self):
return self._item_size return self._item_size
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(target=self._set_playlist, args=(host, playlist, self._item_size,)).start() threading.Thread(target=self._set_playlist, args=(host, 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:
if data: if data:
@ -193,11 +173,9 @@ class PlaylistPanel(Adw.Bin):
# Show image # Show image
GObject.idle_add(self._show_image) GObject.idle_add(self._show_image)
def stop_threads(self): def stop_threads(self):
self._playlist_stop.set() self._playlist_stop.set()
def _set_playlist(self, host, playlist, size): def _set_playlist(self, host, playlist, size):
self._playlist_lock.acquire() self._playlist_lock.acquire()
self._playlist_stop.clear() self._playlist_stop.clear()
@ -237,28 +215,23 @@ class PlaylistPanel(Adw.Bin):
self.playlist_grid.set_model(self._playlist_grid_selection_single) self.playlist_grid.set_model(self._playlist_grid_selection_single)
self._playlist_lock.release() self._playlist_lock.release()
def _show_image(self): def _show_image(self):
self._resize_standalone_image() self._resize_standalone_image()
self.standalone_stack.set_visible_child(self.standalone_scroll) self.standalone_stack.set_visible_child(self.standalone_scroll)
self.standalone_spinner.stop() self.standalone_spinner.stop()
def _redraw(self): def _redraw(self):
if self._playlist is not None: if self._playlist is not None:
self.set_playlist(self._host, self._playlist) self.set_playlist(self._host, self._playlist)
def _open_standalone(self): def _open_standalone(self):
self.playlist_stack.set_visible_child(self.panel_standalone) self.playlist_stack.set_visible_child(self.panel_standalone)
self.emit('open-standalone') self.emit('open-standalone')
def _close_standalone(self): def _close_standalone(self):
self.playlist_stack.set_visible_child(self.panel_normal) self.playlist_stack.set_visible_child(self.panel_normal)
self.emit('close-standalone') self.emit('close-standalone')
def _resize_standalone_image(self): def _resize_standalone_image(self):
"""Diese Methode skaliert das geladene Bild aus dem Pixelpuffer """Diese Methode skaliert das geladene Bild aus dem Pixelpuffer
auf die Größe des Fensters unter Beibehalt der Seitenverhältnisse auf die Größe des Fensters unter Beibehalt der Seitenverhältnisse
@ -288,7 +261,6 @@ class PlaylistPanel(Adw.Bin):
self.standalone_image.set_from_pixbuf(pixbuf.scale_simple(width, height, GdkPixbuf.InterpType.HYPER)) self.standalone_image.set_from_pixbuf(pixbuf.scale_simple(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, Utils.STOCK_ICON_DEFAULT,
@ -299,7 +271,6 @@ class PlaylistPanel(Adw.Bin):
Gtk.IconLookupFlags.FORCE_SYMBOLIC 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()):

View file

@ -8,8 +8,6 @@ gi.require_version('Adw', '1')
from gi.repository import Gtk, Adw, GObject from gi.repository import Gtk, Adw, GObject
@Gtk.Template(resource_path='/xyz/suruatoel/mcg/ui/server-panel.ui') @Gtk.Template(resource_path='/xyz/suruatoel/mcg/ui/server-panel.ui')
class ServerPanel(Adw.Bin): class ServerPanel(Adw.Bin):
__gtype_name__ = 'McgServerPanel' __gtype_name__ = 'McgServerPanel'
@ -34,7 +32,6 @@ class ServerPanel(Adw.Bin):
# Audio ouptut devices widgets # Audio ouptut devices widgets
output_devices = Gtk.Template.Child() output_devices = Gtk.Template.Child()
def __init__(self, **kwargs): def __init__(self, **kwargs):
super().__init__(**kwargs) super().__init__(**kwargs)
self._none_label = "" self._none_label = ""
@ -44,19 +41,15 @@ class ServerPanel(Adw.Bin):
# Widgets # Widgets
self._none_label = self.status_file.get_label() self._none_label = self.status_file.get_label()
def set_selected(self, selected): def set_selected(self, selected):
self._is_selected = selected self._is_selected = selected
def get_toolbar(self): def get_toolbar(self):
return self.toolbar return self.toolbar
def on_output_device_toggled(self, widget, device): def on_output_device_toggled(self, widget, device):
self.emit('change-output-device', device, widget.get_active()) self.emit('change-output-device', device, widget.get_active())
def set_status(self, file, audio, bitrate, error): def set_status(self, file, audio, bitrate, error):
if file: if file:
file = GObject.markup_escape_text(file) file = GObject.markup_escape_text(file)
@ -84,7 +77,6 @@ class ServerPanel(Adw.Bin):
error = self._none_label error = self._none_label
self.status_error.set_markup(error) self.status_error.set_markup(error)
def set_stats(self, artists, albums, songs, dbplaytime, playtime, uptime): def set_stats(self, artists, albums, songs, dbplaytime, playtime, uptime):
self.stats_artists.set_text(str(artists)) self.stats_artists.set_text(str(artists))
self.stats_albums.set_text(str(albums)) self.stats_albums.set_text(str(albums))
@ -93,7 +85,6 @@ class ServerPanel(Adw.Bin):
self.stats_playtime.set_text(str(playtime)) self.stats_playtime.set_text(str(playtime))
self.stats_uptime.set_text(str(uptime)) self.stats_uptime.set_text(str(uptime))
def set_output_devices(self, devices): def set_output_devices(self, devices):
device_ids = [] device_ids = []

View file

@ -7,12 +7,9 @@ gi.require_version('Adw', '1')
from gi.repository import Gtk from gi.repository import Gtk
@Gtk.Template(resource_path='/xyz/suruatoel/mcg/ui/shortcuts-dialog.ui') @Gtk.Template(resource_path='/xyz/suruatoel/mcg/ui/shortcuts-dialog.ui')
class ShortcutsDialog(Gtk.ShortcutsWindow): class ShortcutsDialog(Gtk.ShortcutsWindow):
__gtype_name__ = 'McgShortcutsDialog' __gtype_name__ = 'McgShortcutsDialog'
def __init__(self): def __init__(self):
super().__init__() super().__init__()

View file

@ -11,13 +11,10 @@ import urllib
from gi.repository import Gdk, GdkPixbuf, GObject, Gtk from gi.repository import Gdk, GdkPixbuf, GObject, Gtk
class Utils: class Utils:
CSS_SELECTION = 'selection' CSS_SELECTION = 'selection'
STOCK_ICON_DEFAULT = 'image-x-generic-symbolic' STOCK_ICON_DEFAULT = 'image-x-generic-symbolic'
def load_pixbuf(data): def load_pixbuf(data):
loader = GdkPixbuf.PixbufLoader() loader = GdkPixbuf.PixbufLoader()
try: try:
@ -26,7 +23,6 @@ class Utils:
loader.close() loader.close()
return loader.get_pixbuf() return loader.get_pixbuf()
def load_thumbnail(cache, client, album, size): def load_thumbnail(cache, client, album, size):
cache_url = cache.create_filename(album) cache_url = cache.create_filename(album)
pixbuf = None pixbuf = None
@ -43,7 +39,6 @@ class Utils:
pixbuf.savev(cache_url, 'jpeg', [], []) pixbuf.savev(cache_url, 'jpeg', [], [])
return pixbuf return pixbuf
def create_artists_label(album): def create_artists_label(album):
label = ', '.join(album.get_albumartists()) label = ', '.join(album.get_albumartists())
if album.get_artists(): if album.get_artists():
@ -53,14 +48,12 @@ class Utils:
) )
return label return label
def create_length_label(album): def create_length_label(album):
minutes = album.get_length() // 60 minutes = album.get_length() // 60
seconds = album.get_length() - minutes * 60 seconds = album.get_length() - minutes * 60
return locale.gettext("{}:{} minutes").format(minutes, seconds) return locale.gettext("{}:{} minutes").format(minutes, seconds)
def create_track_title(track): def create_track_title(track):
title = track.get_title() title = track.get_title()
if track.get_artists(): if track.get_artists():
@ -70,7 +63,6 @@ class Utils:
) )
return title return title
def generate_id(values): def generate_id(values):
if type(values) is not list: if type(values) is not list:
values = [values] values = [values]
@ -80,8 +72,6 @@ class Utils:
return m.hexdigest() return m.hexdigest()
class SortOrder: class SortOrder:
ARTIST = 0 ARTIST = 0
TITLE = 1 TITLE = 1
@ -89,15 +79,12 @@ class SortOrder:
MODIFIED = 3 MODIFIED = 3
class GridItem(GObject.GObject): class GridItem(GObject.GObject):
__gtype_name__ = "GridItem" __gtype_name__ = "GridItem"
tooltip = GObject.Property(type=str, default=None) tooltip = GObject.Property(type=str, default=None)
cover = GObject.Property(type=Gdk.Paintable, default=None) cover = GObject.Property(type=Gdk.Paintable, default=None)
def __init__(self, album, cover): def __init__(self, album, cover):
super().__init__() super().__init__()
self._album = album self._album = album
@ -110,24 +97,18 @@ class GridItem(GObject.GObject):
Utils.create_length_label(album) Utils.create_length_label(album)
])) ]))
def get_album(self): def get_album(self):
return self._album return self._album
def set_cover(self, cover): def set_cover(self, cover):
self.cover = Gdk.Texture.new_for_pixbuf(cover) self.cover = Gdk.Texture.new_for_pixbuf(cover)
class SearchFilter(Gtk.Filter): class SearchFilter(Gtk.Filter):
def __init__(self, search_string): def __init__(self, search_string):
super().__init__() super().__init__()
self._search_string = search_string self._search_string = search_string
def do_match(self, grid_item): def do_match(self, grid_item):
return grid_item.get_album().filter(self._search_string) return grid_item.get_album().filter(self._search_string)

View file

@ -25,8 +25,6 @@ from .librarypanel import LibraryPanel
from .zeroconf import ZeroconfProvider from .zeroconf import ZeroconfProvider
class WindowState(GObject.Object): class WindowState(GObject.Object):
WIDTH = 'width' WIDTH = 'width'
HEIGHT = 'height' HEIGHT = 'height'
@ -37,13 +35,10 @@ class WindowState(GObject.Object):
is_maximized = GObject.Property(type=bool, default=False) is_maximized = GObject.Property(type=bool, default=False)
is_fullscreened = GObject.Property(type=bool, default=False) is_fullscreened = GObject.Property(type=bool, default=False)
def __init__(self): def __init__(self):
super().__init__() super().__init__()
@Gtk.Template(resource_path='/xyz/suruatoel/mcg/ui/window.ui') @Gtk.Template(resource_path='/xyz/suruatoel/mcg/ui/window.ui')
class Window(Adw.ApplicationWindow): class Window(Adw.ApplicationWindow):
__gtype_name__ = 'McgAppWindow' __gtype_name__ = 'McgAppWindow'
@ -72,7 +67,6 @@ class Window(Adw.ApplicationWindow):
# Infobar # Infobar
info_toast = Gtk.Template.Child() info_toast = Gtk.Template.Child()
def __init__(self, app, title, settings, **kwargs): def __init__(self, app, title, settings, **kwargs):
super().__init__(**kwargs) super().__init__(**kwargs)
self.set_application(app) self.set_application(app)
@ -205,26 +199,21 @@ class Window(Adw.ApplicationWindow):
self._search_library_action.connect('activate', self.on_menu_search_library) self._search_library_action.connect('activate', self.on_menu_search_library)
self.add_action(self._search_library_action) self.add_action(self._search_library_action)
# Menu callbacks # Menu callbacks
def on_menu_connect(self, action, value): def on_menu_connect(self, action, value):
self._connect() self._connect()
def on_menu_play(self, action, value): def on_menu_play(self, action, value):
self._mcg.playpause() self._mcg.playpause()
def on_menu_clear_playlist(self, action, value): def on_menu_clear_playlist(self, action, value):
self._mcg.clear_playlist() self._mcg.clear_playlist()
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._panels[int(value.get_string())]) self.panel_stack.set_visible_child(self._panels[int(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)
if not self._state.get_property(WindowState.IS_FULLSCREENED): if not self._state.get_property(WindowState.IS_FULLSCREENED):
@ -232,12 +221,10 @@ class Window(Adw.ApplicationWindow):
else: else:
self.unfullscreen() self.unfullscreen()
def on_menu_search_library(self, action, value): def on_menu_search_library(self, action, value):
self.panel_stack.set_visible_child(self.library_panel_page) self.panel_stack.set_visible_child(self.library_panel_page)
self._library_panel.show_search() self._library_panel.show_search()
# Window callbacks # Window callbacks
def on_resize(self, widget, event): def on_resize(self, widget, event):
@ -251,15 +238,12 @@ class Window(Adw.ApplicationWindow):
GObject.idle_add(self._playlist_panel.set_size, width, height) GObject.idle_add(self._playlist_panel.set_size, width, height)
GObject.idle_add(self._library_panel.set_size, width, height) GObject.idle_add(self._library_panel.set_size, width, height)
def on_maximized(self, widget, maximized): def on_maximized(self, widget, maximized):
self._state.set_property(WindowState.IS_MAXIMIZED, maximized is True) self._state.set_property(WindowState.IS_MAXIMIZED, maximized is True)
def on_fullscreened(self, widget, fullscreened): def on_fullscreened(self, widget, fullscreened):
self._fullscreen(self.is_fullscreen()) self._fullscreen(self.is_fullscreen())
# HeaderBar callbacks # HeaderBar callbacks
@Gtk.Template.Callback() @Gtk.Template.Callback()
@ -267,20 +251,17 @@ class Window(Adw.ApplicationWindow):
if self._headerbar_connection_button_active: if self._headerbar_connection_button_active:
self._connect() self._connect()
@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):
if self._headerbar_playpause_button_active: if self._headerbar_playpause_button_active:
self._mcg.playpause() self._mcg.playpause()
self._mcg.get_status() self._mcg.get_status()
# Panel callbacks # Panel callbacks
def on_stack_switched(self, widget, prop): def on_stack_switched(self, widget, prop):
@ -290,17 +271,14 @@ class Window(Adw.ApplicationWindow):
for panel in self._panels: for panel in self._panels:
panel.set_selected(panel == self.panel_stack.get_visible_child()) panel.set_selected(panel == self.panel_stack.get_visible_child())
def on_panel_open_standalone(self, panel): def on_panel_open_standalone(self, panel):
self.toolbar_view.add_top_bar(panel.get_headerbar_standalone()) self.toolbar_view.add_top_bar(panel.get_headerbar_standalone())
self.toolbar_view.remove(self.headerbar) self.toolbar_view.remove(self.headerbar)
def on_panel_close_standalone(self, panel): def on_panel_close_standalone(self, panel):
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(self, widget, host, port, password): def on_connection_panel_connection_changed(self, 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)
@ -311,79 +289,61 @@ class Window(Adw.ApplicationWindow):
if keyring.get_password(ZeroconfProvider.KEYRING_SYSTEM, ZeroconfProvider.KEYRING_USERNAME): if keyring.get_password(ZeroconfProvider.KEYRING_SYSTEM, 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()
def on_playlist_panel_remove(self, widget, album): def on_playlist_panel_remove(self, widget, album):
self._mcg.remove_album_from_playlist(album) self._mcg.remove_album_from_playlist(album)
def on_playlist_panel_remove_multiple(self, widget, albums): def on_playlist_panel_remove_multiple(self, widget, albums):
self._mcg.remove_albums_from_playlist(albums) self._mcg.remove_albums_from_playlist(albums)
def on_playlist_panel_play(self, widget, album): def on_playlist_panel_play(self, widget, album):
self._mcg.play_album_from_playlist(album) self._mcg.play_album_from_playlist(album)
def on_playlist_panel_albumart(self, widget, album): def on_playlist_panel_albumart(self, widget, album):
self._mcg.get_albumart(album) self._mcg.get_albumart(album)
def on_server_panel_output_device_changed(self, widget, device, enabled): def on_server_panel_output_device_changed(self, widget, device, enabled):
self._mcg.enable_output_device(device, enabled) self._mcg.enable_output_device(device, enabled)
def on_cover_panel_toggle_fullscreen(self, widget): def on_cover_panel_toggle_fullscreen(self, widget):
if not self._state.get_property(WindowState.IS_FULLSCREENED): if not self._state.get_property(WindowState.IS_FULLSCREENED):
self.fullscreen() self.fullscreen()
else: else:
self.unfullscreen() self.unfullscreen()
def on_cover_panel_set_song(self, widget, pos, time): def on_cover_panel_set_song(self, widget, pos, time):
self._mcg.seek(pos, time) self._mcg.seek(pos, time)
def on_cover_panel_albumart(self, widget, album): def on_cover_panel_albumart(self, widget, album):
self._mcg.get_albumart(album) self._mcg.get_albumart(album)
def on_library_panel_update(self, widget): def on_library_panel_update(self, widget):
self._mcg.update() self._mcg.update()
def on_library_panel_play(self, widget, album): def on_library_panel_play(self, widget, album):
self._mcg.play_album(album) self._mcg.play_album(album)
def on_library_panel_queue(self, widget, album): def on_library_panel_queue(self, widget, album):
self._mcg.queue_album(album) self._mcg.queue_album(album)
def on_library_panel_queue_multiple(self, widget, albums): def on_library_panel_queue_multiple(self, widget, albums):
self._mcg.queue_albums(albums) self._mcg.queue_albums(albums)
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(Window.SETTING_ITEM_SIZE, self._library_panel.get_item_size()) self._settings.set_int(Window.SETTING_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)
def on_library_panel_sort_type_changed(self, widget, sort_type): def on_library_panel_sort_type_changed(self, widget, sort_type):
self._settings.set_boolean(Window.SETTING_SORT_TYPE, sort_type) self._settings.set_boolean(Window.SETTING_SORT_TYPE, sort_type)
def on_library_panel_albumart(self, widget, album): def on_library_panel_albumart(self, widget, album):
self._mcg.get_albumart(album) self._mcg.get_albumart(album)
# MCG callbacks # MCG callbacks
def on_mcg_connect(self, connected): def on_mcg_connect(self, connected):
@ -405,7 +365,6 @@ 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(self, state, album, pos, time, volume, file, audio, bitrate, error): def on_mcg_status(self, 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)
@ -428,64 +387,51 @@ class Window(Adw.ApplicationWindow):
if error: if error:
self._show_error(error) self._show_error(error)
def on_mcg_stats(self, artists, albums, songs, dbplaytime, playtime, uptime): def on_mcg_stats(self, artists, albums, songs, dbplaytime, playtime, uptime):
self._server_panel.set_stats(artists, albums, 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._connection_panel.get_host(), playlist) self._playlist_panel.set_playlist(self._connection_panel.get_host(), 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)
def on_mcg_pulse_albums(self): def on_mcg_pulse_albums(self):
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._connection_panel.get_host(), albums) self._library_panel.set_albums(self._connection_panel.get_host(), 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)
self._playlist_panel.set_albumart(album, data) self._playlist_panel.set_albumart(album, data)
self._library_panel.set_albumart(album, data) self._library_panel.set_albumart(album, data)
def on_mcg_error(self, error): def on_mcg_error(self, error):
GObject.idle_add(self._show_error, str(error)) GObject.idle_add(self._show_error, str(error))
# Settings callbacks # Settings callbacks
def on_settings_panel_changed(self, settings, key): def on_settings_panel_changed(self, settings, key):
panel_index = settings.get_int(key) panel_index = settings.get_int(key)
self.panel_stack.set_visible_child(self._panels[panel_index]) self.panel_stack.set_visible_child(self._panels[panel_index])
def on_settings_item_size_changed(self, settings, key): def on_settings_item_size_changed(self, settings, key):
size = settings.get_int(key) size = settings.get_int(key)
self._playlist_panel.set_item_size(size) self._playlist_panel.set_item_size(size)
self._library_panel.set_item_size(size) self._library_panel.set_item_size(size)
def on_settings_sort_order_changed(self, settings, key): def on_settings_sort_order_changed(self, settings, key):
sort_order = settings.get_enum(key) sort_order = settings.get_enum(key)
self._library_panel.set_sort_order(sort_order) self._library_panel.set_sort_order(sort_order)
def on_settings_sort_type_changed(self, settings, key): def on_settings_sort_type_changed(self, settings, key):
sort_type = settings.get_boolean(key) sort_type = settings.get_boolean(key)
self._library_panel.set_sort_type(sort_type) self._library_panel.set_sort_type(sort_type)
# Private methods # Private methods
def _connect(self): def _connect(self):
@ -501,14 +447,12 @@ class Window(Adw.ApplicationWindow):
self._mcg.connect(host, port, password) self._mcg.connect(host, port, password)
self._settings.set_boolean(Window.SETTING_CONNECTED, True) self._settings.set_boolean(Window.SETTING_CONNECTED, True)
def _connect_connected(self): def _connect_connected(self):
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._panels[self._settings.get_int(Window.SETTING_PANEL)]) self.panel_stack.set_visible_child(self._panels[self._settings.get_int(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();
@ -518,7 +462,6 @@ class Window(Adw.ApplicationWindow):
self.content_stack.set_visible_child(self._connection_panel) self.content_stack.set_visible_child(self._connection_panel)
self._connection_panel.set_sensitive(True) self._connection_panel.set_sensitive(True)
def _fullscreen(self, fullscreened_new): def _fullscreen(self, fullscreened_new):
if fullscreened_new != self._state.get_property(WindowState.IS_FULLSCREENED): if fullscreened_new != self._state.get_property(WindowState.IS_FULLSCREENED):
self._state.set_property(WindowState.IS_FULLSCREENED, fullscreened_new) self._state.set_property(WindowState.IS_FULLSCREENED, fullscreened_new)
@ -531,35 +474,29 @@ class Window(Adw.ApplicationWindow):
self._cover_panel.set_fullscreen(False) self._cover_panel.set_fullscreen(False)
self.set_cursor(Gdk.Cursor.new_from_name("default", None)) self.set_cursor(Gdk.Cursor.new_from_name("default", None))
def _save_visible_panel(self): def _save_visible_panel(self):
panel_index_selected = self._panels.index(self.panel_stack.get_visible_child()) panel_index_selected = self._panels.index(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(self.panel_stack.get_visible_child()) panel_index_selected = self._panels.index(self.panel_stack.get_visible_child())
self._panel_action.set_state(GLib.Variant.new_string(str(panel_index_selected))) self._panel_action.set_state(GLib.Variant.new_string(str(panel_index_selected)))
def _set_visible_toolbar(self): def _set_visible_toolbar(self):
panel_index_selected = self._panels.index(self.panel_stack.get_visible_child()) panel_index_selected = self._panels.index(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)
def _set_play(self): def _set_play(self):
self._headerbar_playpause_button_active = False self._headerbar_playpause_button_active = False
self.headerbar_button_playpause.set_active(True) self.headerbar_button_playpause.set_active(True)
self._headerbar_playpause_button_active = True self._headerbar_playpause_button_active = True
def _set_pause(self): def _set_pause(self):
self._headerbar_playpause_button_active = False self._headerbar_playpause_button_active = False
self.headerbar_button_playpause.set_active(False) self.headerbar_button_playpause.set_active(False)
self._headerbar_playpause_button_active = True self._headerbar_playpause_button_active = True
def _set_volume(self, volume): def _set_volume(self, volume):
if volume >= 0: if volume >= 0:
self.headerbar_button_volume.set_visible(True) self.headerbar_button_volume.set_visible(True)
@ -569,27 +506,23 @@ class Window(Adw.ApplicationWindow):
else: else:
self.headerbar_button_volume.set_visible(False) self.headerbar_button_volume.set_visible(False)
def _headerbar_connected(self): def _headerbar_connected(self):
self._headerbar_connection_button_active = False self._headerbar_connection_button_active = False
self.headerbar_button_connect.set_active(True) self.headerbar_button_connect.set_active(True)
self.headerbar_button_connect.set_state(True) self.headerbar_button_connect.set_state(True)
self._headerbar_connection_button_active = True self._headerbar_connection_button_active = True
def _headerbar_disconnected(self): def _headerbar_disconnected(self):
self._headerbar_connection_button_active = False self._headerbar_connection_button_active = False
self.headerbar_button_connect.set_active(False) self.headerbar_button_connect.set_active(False)
self.headerbar_button_connect.set_state(False) self.headerbar_button_connect.set_state(False)
self._headerbar_connection_button_active = True self._headerbar_connection_button_active = True
def _set_headerbar_sensitive(self, sensitive, connecting): def _set_headerbar_sensitive(self, sensitive, connecting):
self.headerbar_button_playpause.set_sensitive(sensitive) self.headerbar_button_playpause.set_sensitive(sensitive)
self.headerbar_button_volume.set_sensitive(sensitive) self.headerbar_button_volume.set_sensitive(sensitive)
self.headerbar_panel_switcher.set_sensitive(sensitive) self.headerbar_panel_switcher.set_sensitive(sensitive)
self.headerbar_button_connect.set_sensitive(not connecting) self.headerbar_button_connect.set_sensitive(not connecting)
def _show_error(self, message): def _show_error(self, message):
self.info_toast.add_toast(Adw.Toast.new(message)) self.info_toast.add_toast(Adw.Toast.new(message))

View file

@ -13,15 +13,12 @@ import logging
from mcg import client from mcg import client
class ZeroconfProvider(client.Base): class ZeroconfProvider(client.Base):
KEYRING_SYSTEM = 'mcg' KEYRING_SYSTEM = 'mcg'
KEYRING_USERNAME = 'mpd' KEYRING_USERNAME = 'mpd'
SIGNAL_SERVICE_NEW = 'service-new' SIGNAL_SERVICE_NEW = 'service-new'
TYPE = '_mpd._tcp' TYPE = '_mpd._tcp'
def __init__(self): def __init__(self):
client.Base.__init__(self) client.Base.__init__(self)
self._service_resolvers = [] self._service_resolvers = []
@ -31,7 +28,6 @@ class ZeroconfProvider(client.Base):
if use_avahi: if use_avahi:
self._start_client() self._start_client()
def on_new_service(self, browser, interface, protocol, name, type, domain, flags): def on_new_service(self, 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(interface=interface, protocol=protocol, name=name, type=type, domain=domain, aprotocol=Avahi.Protocol.GA_PROTOCOL_UNSPEC, flags=0,) service_resolver = Avahi.ServiceResolver(interface=interface, protocol=protocol, name=name, type=type, domain=domain, aprotocol=Avahi.Protocol.GA_PROTOCOL_UNSPEC, flags=0,)
@ -40,19 +36,16 @@ 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(self, resolver, interface, protocol, name, type, domain, host, date, port, *args): def on_found(self, 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):
if resolver in self._service_resolvers: if resolver in self._service_resolvers:
self._service_resolvers.remove(resolver) self._service_resolvers.remove(resolver)
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,)