mirror of
https://github.com/SoongNoonien/mpdevil.git
synced 2023-08-10 21:12:44 +03:00
reworked "AlbumWindow" to use "threading"
This commit is contained in:
parent
52d2eebede
commit
4245b40b3d
356
bin/mpdevil
356
bin/mpdevil
@ -25,6 +25,7 @@ from mpd import MPDClient, base as MPDBase
|
|||||||
import requests
|
import requests
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
import threading
|
import threading
|
||||||
|
import functools
|
||||||
import datetime
|
import datetime
|
||||||
import collections
|
import collections
|
||||||
import os
|
import os
|
||||||
@ -46,6 +47,29 @@ VERSION="1.3.0" # sync with setup.py
|
|||||||
COVER_REGEX=r"^\.?(album|cover|folder|front).*\.(gif|jpeg|jpg|png)$"
|
COVER_REGEX=r"^\.?(album|cover|folder|front).*\.(gif|jpeg|jpg|png)$"
|
||||||
FALLBACK_COVER=Gtk.IconTheme.get_default().lookup_icon("media-optical", 128, Gtk.IconLookupFlags.FORCE_SVG).get_filename()
|
FALLBACK_COVER=Gtk.IconTheme.get_default().lookup_icon("media-optical", 128, Gtk.IconLookupFlags.FORCE_SVG).get_filename()
|
||||||
|
|
||||||
|
##############
|
||||||
|
# Decorators #
|
||||||
|
##############
|
||||||
|
|
||||||
|
def main_thread_function(func):
|
||||||
|
@functools.wraps(func)
|
||||||
|
def wrapper_decorator(*args, **kwargs):
|
||||||
|
def glib_callback(event, result, *args, **kwargs):
|
||||||
|
try:
|
||||||
|
result.append(func(*args, **kwargs))
|
||||||
|
except Exception as e: # handle exceptions to avoid deadlocks
|
||||||
|
result.append(e)
|
||||||
|
event.set()
|
||||||
|
return False
|
||||||
|
event=threading.Event()
|
||||||
|
result=[]
|
||||||
|
GLib.idle_add(glib_callback, event, result, *args, **kwargs)
|
||||||
|
event.wait()
|
||||||
|
if isinstance(result[0], Exception):
|
||||||
|
raise result[0]
|
||||||
|
else:
|
||||||
|
return result[0]
|
||||||
|
return wrapper_decorator
|
||||||
|
|
||||||
#########
|
#########
|
||||||
# MPRIS #
|
# MPRIS #
|
||||||
@ -808,27 +832,6 @@ class Client(MPDClient):
|
|||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_albums(self, artist, genre):
|
|
||||||
self.restrict_tagtypes("albumartist", "album")
|
|
||||||
albums=[]
|
|
||||||
artist_type=self._settings.get_artist_type()
|
|
||||||
if genre is None:
|
|
||||||
genre_filter=()
|
|
||||||
else:
|
|
||||||
genre_filter=("genre", genre)
|
|
||||||
album_candidates=self.comp_list("album", artist_type, artist, *genre_filter)
|
|
||||||
for album in album_candidates:
|
|
||||||
years=self.comp_list("date", "album", album, artist_type, artist, *genre_filter)
|
|
||||||
for year in years:
|
|
||||||
count=self.count(artist_type, artist, "album", album, "date", year, *genre_filter)
|
|
||||||
duration=Duration(count["playtime"])
|
|
||||||
song=self.find("album", album, "date", year, artist_type, artist, *genre_filter, "window", "0:1")[0]
|
|
||||||
cover=self.get_cover(song)
|
|
||||||
albums.append({"artist": artist,"album": album,"year": year,
|
|
||||||
"length": count["songs"], "duration": duration, "cover": cover})
|
|
||||||
self.tagtypes("all")
|
|
||||||
return albums
|
|
||||||
|
|
||||||
def toggle_play(self):
|
def toggle_play(self):
|
||||||
status=self.status()
|
status=self.status()
|
||||||
if status["state"] == "play":
|
if status["state"] == "play":
|
||||||
@ -1666,7 +1669,6 @@ class AlbumPopover(Gtk.Popover):
|
|||||||
|
|
||||||
# songs view
|
# songs view
|
||||||
self._songs_view=songs_window.get_treeview()
|
self._songs_view=songs_window.get_treeview()
|
||||||
self._songs_view.set_property("headers-visible", False)
|
|
||||||
self._songs_view.set_property("search-column", 4)
|
self._songs_view.set_property("search-column", 4)
|
||||||
|
|
||||||
# columns
|
# columns
|
||||||
@ -1675,9 +1677,10 @@ class AlbumPopover(Gtk.Popover):
|
|||||||
column_track=Gtk.TreeViewColumn(_("No"), renderer_text_ralign, text=0)
|
column_track=Gtk.TreeViewColumn(_("No"), renderer_text_ralign, text=0)
|
||||||
column_track.set_property("resizable", False)
|
column_track.set_property("resizable", False)
|
||||||
self._songs_view.append_column(column_track)
|
self._songs_view.append_column(column_track)
|
||||||
column_title=Gtk.TreeViewColumn(_("Title"), renderer_text, markup=1)
|
self._column_title=Gtk.TreeViewColumn(_("Title"), renderer_text, markup=1)
|
||||||
column_title.set_property("resizable", False)
|
self._column_title.set_property("resizable", False)
|
||||||
self._songs_view.append_column(column_title)
|
self._column_title.set_property("expand", True)
|
||||||
|
self._songs_view.append_column(self._column_title)
|
||||||
column_time=Gtk.TreeViewColumn(_("Length"), renderer_text_ralign, text=2)
|
column_time=Gtk.TreeViewColumn(_("Length"), renderer_text_ralign, text=2)
|
||||||
column_time.set_property("resizable", False)
|
column_time.set_property("resizable", False)
|
||||||
self._songs_view.append_column(column_time)
|
self._songs_view.append_column(column_time)
|
||||||
@ -1700,8 +1703,14 @@ class AlbumPopover(Gtk.Popover):
|
|||||||
genre_filter=()
|
genre_filter=()
|
||||||
else:
|
else:
|
||||||
genre_filter=("genre", genre)
|
genre_filter=("genre", genre)
|
||||||
|
artist_type=self._settings.get_artist_type()
|
||||||
|
count=self._client.count(artist_type, album_artist, "album", album, "date", date, *genre_filter)
|
||||||
|
duration=str(Duration(float(count["playtime"])))
|
||||||
|
length=int(count["songs"])
|
||||||
|
text=ngettext("{number} song ({duration})", "{number} songs ({duration})", length).format(number=length, duration=duration)
|
||||||
|
self._column_title.set_title(" • ".join([_("Title"), text]))
|
||||||
self._client.restrict_tagtypes("track", "title", "artist")
|
self._client.restrict_tagtypes("track", "title", "artist")
|
||||||
songs=self._client.find("album", album, "date", date, self._settings.get_artist_type(), album_artist, *genre_filter)
|
songs=self._client.find("album", album, "date", date, artist_type, album_artist, *genre_filter)
|
||||||
self._client.tagtypes("all")
|
self._client.tagtypes("all")
|
||||||
for song in songs:
|
for song in songs:
|
||||||
track=song["track"][0]
|
track=song["track"][0]
|
||||||
@ -2058,7 +2067,7 @@ class GenreSelect(SelectionList):
|
|||||||
|
|
||||||
# connect
|
# connect
|
||||||
self._client.emitter.connect("disconnected", self._on_disconnected)
|
self._client.emitter.connect("disconnected", self._on_disconnected)
|
||||||
self._client.emitter.connect("reconnected", self._on_reconnected)
|
self._client.emitter.connect_after("reconnected", self._on_reconnected)
|
||||||
self._client.emitter.connect("update", self._refresh)
|
self._client.emitter.connect("update", self._refresh)
|
||||||
|
|
||||||
def deactivate(self):
|
def deactivate(self):
|
||||||
@ -2160,23 +2169,139 @@ class ArtistWindow(SelectionList):
|
|||||||
def _on_reconnected(self, *args):
|
def _on_reconnected(self, *args):
|
||||||
self.set_sensitive(True)
|
self.set_sensitive(True)
|
||||||
|
|
||||||
|
class AlbumLoadingThread(threading.Thread):
|
||||||
|
def __init__(self, client, settings, progress_bar, iconview, store, artist, genre):
|
||||||
|
super().__init__(daemon=True)
|
||||||
|
self._client=client
|
||||||
|
self._settings=settings
|
||||||
|
self._progress_bar=progress_bar
|
||||||
|
self._iconview=iconview
|
||||||
|
self._store=store
|
||||||
|
self._artist=artist
|
||||||
|
self._genre=genre
|
||||||
|
|
||||||
|
def set_callback(self, callback):
|
||||||
|
self._callback=callback
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
self._stop_flag=True
|
||||||
|
|
||||||
|
def _album_generator(self):
|
||||||
|
for artist in self._artists:
|
||||||
|
try: # client cloud meanwhile disconnect
|
||||||
|
grouped_albums=main_thread_function(self._client.list)(
|
||||||
|
"album", self._artist_type, artist, *self._genre_filter, "group", "date")
|
||||||
|
except (MPDBase.ConnectionError, ConnectionResetError) as e:
|
||||||
|
return
|
||||||
|
for album_group in grouped_albums:
|
||||||
|
date=album_group["date"]
|
||||||
|
if isinstance(album_group["album"], str):
|
||||||
|
albums=[album_group["album"]]
|
||||||
|
else:
|
||||||
|
albums=album_group["album"]
|
||||||
|
for album in albums:
|
||||||
|
yield {"name": album, "artist": artist, "date": date}
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
self._callback=None
|
||||||
|
self._stop_flag=False
|
||||||
|
self._iconview.set_model(None)
|
||||||
|
self._store.clear()
|
||||||
|
self._cover_size=self._settings.get_int("album-cover")
|
||||||
|
self._artist_type=self._settings.get_artist_type()
|
||||||
|
if self._genre is None:
|
||||||
|
self._genre_filter=()
|
||||||
|
else:
|
||||||
|
self._genre_filter=("genre", self._genre)
|
||||||
|
if self._artist is None:
|
||||||
|
self._iconview.set_markup_column(2) # show artist names
|
||||||
|
self._artists=self._client.comp_list(self._artist_type, *self._genre_filter)
|
||||||
|
else:
|
||||||
|
self._iconview.set_markup_column(1) # hide artist names
|
||||||
|
self._artists=[self._artist]
|
||||||
|
super().start()
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
GLib.idle_add(self._settings.set_property, "cursor-watch", True)
|
||||||
|
GLib.idle_add(self._progress_bar.show)
|
||||||
|
# temporarily display all albums with fallback cover
|
||||||
|
fallback_cover=GdkPixbuf.Pixbuf.new_from_file_at_size(FALLBACK_COVER, self._cover_size, self._cover_size)
|
||||||
|
add=main_thread_function(self._store.append)
|
||||||
|
for i, album in enumerate(self._album_generator()):
|
||||||
|
# album label
|
||||||
|
if album["date"]:
|
||||||
|
display_label=f"<b>{GLib.markup_escape_text(album['name'])}</b> ({GLib.markup_escape_text(album['date'])})"
|
||||||
|
else:
|
||||||
|
display_label=f"<b>{GLib.markup_escape_text(album['name'])}</b>"
|
||||||
|
display_label_artist=f"{display_label}\n{GLib.markup_escape_text(album['artist'])}"
|
||||||
|
# add album
|
||||||
|
add([fallback_cover,display_label,display_label_artist,album["name"],album["date"],album["artist"]])
|
||||||
|
if i%10 == 0:
|
||||||
|
if self._stop_flag:
|
||||||
|
self._exit()
|
||||||
|
return
|
||||||
|
GLib.idle_add(self._progress_bar.pulse)
|
||||||
|
if main_thread_function(self._settings.get_boolean)("sort-albums-by-year"):
|
||||||
|
main_thread_function(self._store.set_sort_column_id)(4, Gtk.SortType.ASCENDING)
|
||||||
|
else:
|
||||||
|
main_thread_function(self._store.set_sort_column_id)(1, Gtk.SortType.ASCENDING)
|
||||||
|
GLib.idle_add(self._iconview.set_model, self._store)
|
||||||
|
# load covers
|
||||||
|
total=2*len(self._store)
|
||||||
|
@main_thread_function
|
||||||
|
def get_cover(row):
|
||||||
|
if self._stop_flag:
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
self._client.restrict_tagtypes("albumartist", "album")
|
||||||
|
song=self._client.find("album",row[3],"date",row[4],self._artist_type,row[5],*self._genre_filter,"window","0:1")[0]
|
||||||
|
self._client.tagtypes("all")
|
||||||
|
return self._client.get_cover(song)
|
||||||
|
covers=[]
|
||||||
|
for i, row in enumerate(self._store):
|
||||||
|
cover=get_cover(row)
|
||||||
|
if cover is None:
|
||||||
|
self._exit()
|
||||||
|
return
|
||||||
|
covers.append(cover)
|
||||||
|
GLib.idle_add(self._progress_bar.set_fraction, (i+1)/total)
|
||||||
|
treeiter=self._store.get_iter_first()
|
||||||
|
i=0
|
||||||
|
def set_cover(treeiter, cover):
|
||||||
|
if self._store.iter_is_valid(treeiter):
|
||||||
|
self._store.set_value(treeiter, 0, cover)
|
||||||
|
while treeiter is not None:
|
||||||
|
if self._stop_flag:
|
||||||
|
self._exit()
|
||||||
|
return
|
||||||
|
cover=covers[i].get_pixbuf(self._cover_size)
|
||||||
|
GLib.idle_add(set_cover, treeiter, cover)
|
||||||
|
GLib.idle_add(self._progress_bar.set_fraction, 0.5+(i+1)/total)
|
||||||
|
i+=1
|
||||||
|
treeiter=self._store.iter_next(treeiter)
|
||||||
|
self._exit()
|
||||||
|
|
||||||
|
def _exit(self):
|
||||||
|
GLib.idle_add(self._settings.set_property, "cursor-watch", False)
|
||||||
|
GLib.idle_add(self._progress_bar.hide)
|
||||||
|
GLib.idle_add(self._progress_bar.set_fraction, 0)
|
||||||
|
if self._callback is not None:
|
||||||
|
GLib.idle_add(self._callback)
|
||||||
|
|
||||||
class AlbumWindow(FocusFrame):
|
class AlbumWindow(FocusFrame):
|
||||||
def __init__(self, client, settings, artist_window):
|
def __init__(self, client, settings, artist_window):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self._settings=settings
|
self._settings=settings
|
||||||
self._client=client
|
self._client=client
|
||||||
self._artist_window=artist_window
|
self._artist_window=artist_window
|
||||||
self._stop_flag=False
|
|
||||||
self._done=True
|
|
||||||
self._pending=[]
|
|
||||||
|
|
||||||
# cover, display_label, display_label_artist, tooltip(titles), album, year, artist, index
|
# cover, display_label, display_label_artist, album, date, artist
|
||||||
self._store=Gtk.ListStore(GdkPixbuf.Pixbuf, str, str, str, str, str, str, int)
|
self._store=Gtk.ListStore(GdkPixbuf.Pixbuf, str, str, str, str, str)
|
||||||
self._sort_settings()
|
self._store.set_default_sort_func(lambda *args: 0)
|
||||||
|
|
||||||
# iconview
|
# iconview
|
||||||
self._iconview=Gtk.IconView(
|
self._iconview=Gtk.IconView(
|
||||||
model=self._store, item_width=0, pixbuf_column=0, markup_column=1, tooltip_column=3, activate_on_single_click=True
|
model=self._store, item_width=0, pixbuf_column=0, markup_column=1, activate_on_single_click=True
|
||||||
)
|
)
|
||||||
|
|
||||||
# scroll
|
# scroll
|
||||||
@ -2193,6 +2318,9 @@ class AlbumWindow(FocusFrame):
|
|||||||
self._album_popover=AlbumPopover(self._client, self._settings)
|
self._album_popover=AlbumPopover(self._client, self._settings)
|
||||||
self._artist_popover=ArtistPopover(self._client)
|
self._artist_popover=ArtistPopover(self._client)
|
||||||
|
|
||||||
|
# cover thread
|
||||||
|
self._cover_thread=AlbumLoadingThread(self._client, self._settings, self._progress_bar, self._iconview, self._store, None, None)
|
||||||
|
|
||||||
# connect
|
# connect
|
||||||
self._iconview.connect("item-activated", self._on_item_activated)
|
self._iconview.connect("item-activated", self._on_item_activated)
|
||||||
self._iconview.connect("button-press-event", self._on_button_press_event)
|
self._iconview.connect("button-press-event", self._on_button_press_event)
|
||||||
@ -2219,13 +2347,16 @@ class AlbumWindow(FocusFrame):
|
|||||||
self._iconview.set_model(self._store)
|
self._iconview.set_model(self._store)
|
||||||
|
|
||||||
def _clear(self, *args):
|
def _clear(self, *args):
|
||||||
if self._done:
|
def callback():
|
||||||
self._album_popover.popdown()
|
self._album_popover.popdown()
|
||||||
self._artist_popover.popdown()
|
self._artist_popover.popdown()
|
||||||
self._workaround_clear()
|
self._workaround_clear()
|
||||||
elif not self._clear in self._pending:
|
return False
|
||||||
self._stop_flag=True
|
if self._cover_thread.is_alive():
|
||||||
self._pending.append(self._clear)
|
self._cover_thread.set_callback(callback)
|
||||||
|
self._cover_thread.stop()
|
||||||
|
else:
|
||||||
|
callback()
|
||||||
|
|
||||||
def scroll_to_current_album(self):
|
def scroll_to_current_album(self):
|
||||||
def callback():
|
def callback():
|
||||||
@ -2235,125 +2366,46 @@ class AlbumWindow(FocusFrame):
|
|||||||
row_num=len(self._store)
|
row_num=len(self._store)
|
||||||
for i in range(0, row_num):
|
for i in range(0, row_num):
|
||||||
path=Gtk.TreePath(i)
|
path=Gtk.TreePath(i)
|
||||||
if self._store[path][4] == album:
|
if self._store[path][3] == album:
|
||||||
self._iconview.set_cursor(path, None, False)
|
self._iconview.set_cursor(path, None, False)
|
||||||
self._iconview.select_path(path)
|
self._iconview.select_path(path)
|
||||||
self._iconview.scroll_to_path(path, True, 0, 0)
|
self._iconview.scroll_to_path(path, True, 0, 0)
|
||||||
break
|
break
|
||||||
if self._done:
|
return False
|
||||||
|
if self._cover_thread.is_alive():
|
||||||
|
self._cover_thread.set_callback(callback)
|
||||||
|
else:
|
||||||
callback()
|
callback()
|
||||||
elif not self.scroll_to_current_album in self._pending:
|
|
||||||
self._pending.append(self.scroll_to_current_album)
|
|
||||||
|
|
||||||
def _sort_settings(self, *args):
|
def _sort_settings(self, *args):
|
||||||
if self._settings.get_boolean("sort-albums-by-year"):
|
if not self._cover_thread.is_alive():
|
||||||
self._store.set_sort_column_id(5, Gtk.SortType.ASCENDING)
|
if self._settings.get_boolean("sort-albums-by-year"):
|
||||||
else:
|
self._store.set_sort_column_id(4, Gtk.SortType.ASCENDING)
|
||||||
self._store.set_sort_column_id(1, Gtk.SortType.ASCENDING)
|
else:
|
||||||
|
self._store.set_sort_column_id(1, Gtk.SortType.ASCENDING)
|
||||||
|
|
||||||
def _refresh(self, *args):
|
def _refresh(self, *args):
|
||||||
if self._done:
|
def callback():
|
||||||
self._done=False
|
if self._cover_thread.is_alive(): # already started?
|
||||||
self._settings.set_property("cursor-watch", True)
|
return False
|
||||||
self._progress_bar.show()
|
artist=self._artist_window.get_selected()
|
||||||
self._store.clear()
|
genre=self._artist_window.genre_select.get_selected()
|
||||||
self._iconview.set_model(None)
|
self._cover_thread=AlbumLoadingThread(self._client,self._settings,self._progress_bar,self._iconview,self._store,artist,genre)
|
||||||
try: # self._artist_window can still be empty (e.g. when client is not connected and cover size gets changed)
|
self._cover_thread.start()
|
||||||
artist=self._artist_window.get_selected()
|
return False
|
||||||
genre=self._artist_window.genre_select.get_selected()
|
if self._cover_thread.is_alive():
|
||||||
except:
|
self._cover_thread.set_callback(callback)
|
||||||
self._done_callback()
|
self._cover_thread.stop()
|
||||||
return
|
else:
|
||||||
if artist is None:
|
callback()
|
||||||
self._iconview.set_markup_column(2) # show artist names
|
|
||||||
if genre is None:
|
|
||||||
artists=self._client.comp_list(self._settings.get_artist_type())
|
|
||||||
else:
|
|
||||||
artists=self._client.comp_list(self._settings.get_artist_type(), "genre", genre)
|
|
||||||
else:
|
|
||||||
self._iconview.set_markup_column(1) # hide artist names
|
|
||||||
artists=[artist]
|
|
||||||
# prepare albmus list (run all mpd related commands)
|
|
||||||
albums=[]
|
|
||||||
for i, artist in enumerate(artists):
|
|
||||||
try: # client cloud meanwhile disconnect
|
|
||||||
if self._stop_flag:
|
|
||||||
self._done_callback()
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
if i > 0: # more than one artist to show (all artists)
|
|
||||||
self._progress_bar.pulse()
|
|
||||||
albums.extend(self._client.get_albums(artist, genre))
|
|
||||||
while Gtk.events_pending():
|
|
||||||
Gtk.main_iteration_do(True)
|
|
||||||
except MPDBase.ConnectionError:
|
|
||||||
self._done_callback()
|
|
||||||
return
|
|
||||||
# temporarily display all albums with fallback cover
|
|
||||||
size=self._settings.get_int("album-cover")
|
|
||||||
fallback_cover=GdkPixbuf.Pixbuf.new_from_file_at_size(FALLBACK_COVER, size, size)
|
|
||||||
for i, album in enumerate(albums):
|
|
||||||
# tooltip
|
|
||||||
duration=str(album["duration"])
|
|
||||||
length=int(album["length"])
|
|
||||||
tooltip=ngettext("{number} song ({duration})", "{number} songs ({duration})", length).format(
|
|
||||||
number=length, duration=duration)
|
|
||||||
# album label
|
|
||||||
if album["year"]:
|
|
||||||
display_label=f"<b>{GLib.markup_escape_text(album['album'])}</b> ({GLib.markup_escape_text(album['year'])})"
|
|
||||||
else:
|
|
||||||
display_label=f"<b>{GLib.markup_escape_text(album['album'])}</b>"
|
|
||||||
display_label_artist=f"{display_label}\n{GLib.markup_escape_text(album['artist'])}"
|
|
||||||
# add album
|
|
||||||
self._store.append(
|
|
||||||
[fallback_cover, display_label, display_label_artist,
|
|
||||||
tooltip, album["album"], album["year"], album["artist"], i]
|
|
||||||
)
|
|
||||||
self._iconview.set_model(self._store)
|
|
||||||
|
|
||||||
def render_covers():
|
|
||||||
def set_cover(row, cover):
|
|
||||||
row[0]=cover
|
|
||||||
size=self._settings.get_int("album-cover")
|
|
||||||
fallback_cover=GdkPixbuf.Pixbuf.new_from_file_at_size(FALLBACK_COVER, size, size)
|
|
||||||
total_albums=len(albums)
|
|
||||||
for i, row in enumerate(self._store):
|
|
||||||
album=albums[row[7]]
|
|
||||||
if self._stop_flag:
|
|
||||||
break
|
|
||||||
cover=album["cover"].get_pixbuf(size)
|
|
||||||
GLib.idle_add(set_cover, row, cover)
|
|
||||||
GLib.idle_add(self._progress_bar.set_fraction, (i+1)/total_albums)
|
|
||||||
GLib.idle_add(self._done_callback)
|
|
||||||
|
|
||||||
cover_thread=threading.Thread(target=render_covers, daemon=True)
|
|
||||||
cover_thread.start()
|
|
||||||
elif not self._refresh in self._pending:
|
|
||||||
self._stop_flag=True
|
|
||||||
self._pending.append(self._refresh)
|
|
||||||
|
|
||||||
def _path_to_playlist(self, path, mode="default"):
|
def _path_to_playlist(self, path, mode="default"):
|
||||||
album=self._store[path][4]
|
album=self._store[path][3]
|
||||||
year=self._store[path][5]
|
year=self._store[path][4]
|
||||||
artist=self._store[path][6]
|
artist=self._store[path][5]
|
||||||
genre=self._artist_window.genre_select.get_selected()
|
genre=self._artist_window.genre_select.get_selected()
|
||||||
self._client.album_to_playlist(album, artist, year, genre, mode)
|
self._client.album_to_playlist(album, artist, year, genre, mode)
|
||||||
|
|
||||||
def _done_callback(self, *args):
|
|
||||||
self._settings.set_property("cursor-watch", False)
|
|
||||||
self._progress_bar.hide()
|
|
||||||
self._progress_bar.set_fraction(0)
|
|
||||||
self._stop_flag=False
|
|
||||||
self._done=True
|
|
||||||
pending=self._pending
|
|
||||||
self._pending=[]
|
|
||||||
for p in pending:
|
|
||||||
try:
|
|
||||||
p()
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
return False
|
|
||||||
|
|
||||||
def _on_button_press_event(self, widget, event):
|
def _on_button_press_event(self, widget, event):
|
||||||
path=widget.get_path_at_pos(int(event.x), int(event.y))
|
path=widget.get_path_at_pos(int(event.x), int(event.y))
|
||||||
if event.button == 1 and event.type == Gdk.EventType._2BUTTON_PRESS:
|
if event.button == 1 and event.type == Gdk.EventType._2BUTTON_PRESS:
|
||||||
@ -2367,9 +2419,9 @@ class AlbumWindow(FocusFrame):
|
|||||||
h=self._scroll_hadj.get_value()
|
h=self._scroll_hadj.get_value()
|
||||||
genre=self._artist_window.genre_select.get_selected()
|
genre=self._artist_window.genre_select.get_selected()
|
||||||
if path is not None:
|
if path is not None:
|
||||||
album=self._store[path][4]
|
album=self._store[path][3]
|
||||||
year=self._store[path][5]
|
year=self._store[path][4]
|
||||||
artist=self._store[path][6]
|
artist=self._store[path][5]
|
||||||
# when using "button-press-event" in iconview popovers only show up in combination with idle_add (bug in GTK?)
|
# when using "button-press-event" in iconview popovers only show up in combination with idle_add (bug in GTK?)
|
||||||
GLib.idle_add(self._album_popover.open, album, artist, year, genre, widget, event.x-h, event.y-v)
|
GLib.idle_add(self._album_popover.open, album, artist, year, genre, widget, event.x-h, event.y-v)
|
||||||
else:
|
else:
|
||||||
@ -2377,9 +2429,9 @@ class AlbumWindow(FocusFrame):
|
|||||||
GLib.idle_add(self._artist_popover.open, artist, genre, widget, event.x-h, event.y-v)
|
GLib.idle_add(self._artist_popover.open, artist, genre, widget, event.x-h, event.y-v)
|
||||||
|
|
||||||
def _on_item_activated(self, widget, path):
|
def _on_item_activated(self, widget, path):
|
||||||
album=self._store[path][4]
|
album=self._store[path][3]
|
||||||
year=self._store[path][5]
|
year=self._store[path][4]
|
||||||
artist=self._store[path][6]
|
artist=self._store[path][5]
|
||||||
genre=self._artist_window.genre_select.get_selected()
|
genre=self._artist_window.genre_select.get_selected()
|
||||||
self._client.album_to_playlist(album, artist, year, genre)
|
self._client.album_to_playlist(album, artist, year, genre)
|
||||||
|
|
||||||
@ -2398,7 +2450,7 @@ class AlbumWindow(FocusFrame):
|
|||||||
y=rect.y+rect.height//2
|
y=rect.y+rect.height//2
|
||||||
genre=self._artist_window.genre_select.get_selected()
|
genre=self._artist_window.genre_select.get_selected()
|
||||||
self._album_popover.open(
|
self._album_popover.open(
|
||||||
self._store[paths[0]][4], self._store[paths[0]][6], self._store[paths[0]][5], genre, self._iconview, x, y
|
self._store[paths[0]][3], self._store[paths[0]][5], self._store[paths[0]][4], genre, self._iconview, x, y
|
||||||
)
|
)
|
||||||
|
|
||||||
def _on_add_to_playlist(self, emitter, mode):
|
def _on_add_to_playlist(self, emitter, mode):
|
||||||
@ -2408,10 +2460,8 @@ class AlbumWindow(FocusFrame):
|
|||||||
self._path_to_playlist(paths[0], mode)
|
self._path_to_playlist(paths[0], mode)
|
||||||
|
|
||||||
def _on_cover_size_changed(self, *args):
|
def _on_cover_size_changed(self, *args):
|
||||||
def callback():
|
if self._client.connected():
|
||||||
self._refresh()
|
self._refresh()
|
||||||
return False
|
|
||||||
GLib.idle_add(callback)
|
|
||||||
|
|
||||||
class Browser(Gtk.Paned):
|
class Browser(Gtk.Paned):
|
||||||
def __init__(self, client, settings):
|
def __init__(self, client, settings):
|
||||||
|
Loading…
Reference in New Issue
Block a user