This is a multi-selection model so we can do operations on multiple tracks at once. Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
154 lines
5.1 KiB
Python
154 lines
5.1 KiB
Python
# Copyright 2021 (c) Anna Schumaker.
|
|
import audio
|
|
import lib
|
|
from gi.repository import GObject
|
|
from gi.repository import Gio
|
|
from gi.repository import Gtk
|
|
from lib import bus
|
|
from . import controls
|
|
from . import runtime
|
|
|
|
class PlaylistModel(GObject.GObject, Gio.ListModel):
|
|
def __init__(self):
|
|
GObject.GObject.__init__(self)
|
|
self.playlist = None
|
|
self.tracks = [ ]
|
|
|
|
def do_get_item_type(self): return GObject.TYPE_PYOBJECT
|
|
def do_get_n_items(self): return len(self.tracks)
|
|
def do_get_item(self, n):
|
|
return self.tracks[n] if n < len(self.tracks) else None
|
|
|
|
def get_playlist(self): return self.playlist
|
|
def set_playlist(self, playlist):
|
|
if self.playlist:
|
|
self.playlist.disconnect_by_func(self.refreshed)
|
|
self.playlist.disconnect_by_func(self.track_added)
|
|
self.playlist.disconnect_by_func(self.track_removed)
|
|
self.playlist = playlist
|
|
self.refreshed(playlist)
|
|
self.playlist.connect("refreshed", self.refreshed)
|
|
self.playlist.connect("track-added", self.track_added)
|
|
self.playlist.connect("track-removed", self.track_removed)
|
|
|
|
def track_added(self, plist, track):
|
|
index = plist.get_track_index(track)
|
|
self.tracks.insert(index, track)
|
|
self.emit("items-changed", index, 0, 1)
|
|
|
|
def track_removed(self, plist, track, adjusted_current):
|
|
index = self.tracks.index(track)
|
|
del self.tracks[index]
|
|
self.emit("items-changed", index, 1, 0)
|
|
|
|
def refreshed(self, plist):
|
|
rm = len(self.tracks)
|
|
self.tracks = plist.get_tracks()
|
|
self.emit("items-changed", 0, rm, len(self.tracks))
|
|
|
|
|
|
class Filter(lib.filter.Regex):
|
|
def do_match(self, track):
|
|
fields = [ f"disc={track.disc.number}",
|
|
f"track={track.number}",
|
|
f"title={track.title}",
|
|
f"artist={track.artist.name}",
|
|
f"album={track.album.name}",
|
|
f"subtitle={track.disc.subtitle}",
|
|
f"year={track.year.year}" ]
|
|
return self.search(' & '.join(fields))
|
|
PlaylistFilter = Filter()
|
|
|
|
|
|
class FilterPlaylistModel(Gtk.FilterListModel):
|
|
def __init__(self):
|
|
Gtk.FilterListModel.__init__(self)
|
|
self.set_model(PlaylistModel())
|
|
self.set_filter(PlaylistFilter)
|
|
|
|
def get_playlist(self): return self.get_model().get_playlist()
|
|
def set_playlist(self, plist):
|
|
self.set_incremental(plist.get_n_tracks() > 1000)
|
|
self.get_model().set_playlist(plist)
|
|
|
|
def get_runtime(self):
|
|
n = self.get_n_items()
|
|
return sum([ int(self.get_item(i).length) for i in range(n) ])
|
|
|
|
|
|
class PlaylistSelection(Gtk.MultiSelection):
|
|
def __init__(self):
|
|
Gtk.MultiSelection.__init__(self)
|
|
self.set_model(FilterPlaylistModel())
|
|
|
|
def get_filter_model(self): return self.get_model()
|
|
def get_playlist(self): return self.get_model().get_playlist()
|
|
def set_playlist(self, plist): return self.get_model().set_playlist(plist)
|
|
|
|
|
|
class TagModel(GObject.GObject, Gio.ListModel):
|
|
def __init__(self, tag=None):
|
|
GObject.GObject.__init__(self)
|
|
self.Controls = controls.Controls()
|
|
self.bus = bus.Bus(1)
|
|
self.items = [ ]
|
|
self.__set_tag__(tag)
|
|
audio.Player.connect("track-changed", self.on_tracks_changed)
|
|
|
|
def __set_tag__(self, tag):
|
|
self.tag = tag
|
|
if self.tag != None:
|
|
self.items = self.tag.tracks.copy()
|
|
self.tag.TrackAdded.register(self.track_added)
|
|
self.tag.TrackRemoved.register(self.track_removed)
|
|
self.Controls.set_tag(tag)
|
|
return len(self.items)
|
|
|
|
def __unset_tag__(self):
|
|
n = len(self.items)
|
|
if self.tag:
|
|
self.tag.TrackAdded.unregister(self.track_added)
|
|
self.tag.TrackRemoved.unregister(self.track_removed)
|
|
self.items.clear()
|
|
return n
|
|
|
|
def do_get_item_type(self):
|
|
return GObject.TYPE_PYOBJECT
|
|
|
|
def do_get_n_items(self):
|
|
return len(self.items)
|
|
|
|
def do_get_item(self, n):
|
|
if n < len(self.items):
|
|
return self.items[n]
|
|
|
|
def items_changed(self, pos, removed, added):
|
|
super().items_changed(pos, removed, added)
|
|
runtime.set_runtime(self.tag.runtime)
|
|
runtime.set_visible_count(len(self.items))
|
|
|
|
def switch_tag(self, tag):
|
|
removed = self.__unset_tag__()
|
|
added = self.__set_tag__(tag)
|
|
self.items_changed(0, removed, added)
|
|
|
|
def do_track_added(self, tag, track, pos):
|
|
self.items.insert(pos, track)
|
|
self.items_changed(pos, 0, 1)
|
|
|
|
def track_added(self, tag, track, pos):
|
|
self.bus.board(self.do_track_added, tag, track, pos)
|
|
|
|
def do_track_removed(self, tag, track, pos):
|
|
self.items.remove(track)
|
|
self.items_changed(pos, 1, 0)
|
|
|
|
def track_removed(self, tag, track, pos):
|
|
self.bus.board(self.do_track_removed, tag, track, pos)
|
|
|
|
def on_tracks_changed(self, player, prev, new):
|
|
if prev in self.items:
|
|
self.items_changed(self.items.index(prev), 1, 1)
|
|
if new in self.items:
|
|
self.items_changed(self.items.index(new), 1, 1)
|