|
@@ -1,11 +1,32 @@
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
import datetime as dt
|
|
|
+import dateutil.tz
|
|
|
import mutagen
|
|
|
|
|
|
import symuid.tag_interface
|
|
|
|
|
|
|
|
|
+def _timestamp_to_utc_dt(ts):
|
|
|
+ return dt.datetime.utcfromtimestamp(ts) \
|
|
|
+ .replace(tzinfo=dateutil.tz.tzutc())
|
|
|
+
|
|
|
+assert _timestamp_to_utc_dt(1528795204) \
|
|
|
+ == dt.datetime(2018, 6, 12, 9, 20, 4, tzinfo=dateutil.tz.tzutc())
|
|
|
+
|
|
|
+
|
|
|
+class PlayCount:
|
|
|
+
|
|
|
+ def __init__(self, player, library_id, register_dt, count):
|
|
|
+ self.player = player
|
|
|
+ self.library_id = library_id
|
|
|
+ assert isinstance(register_dt, dt.datetime), register_dt
|
|
|
+ assert register_dt.tzinfo is not None, register_dt
|
|
|
+ self.register_dt = register_dt
|
|
|
+ assert isinstance(count, int) and count >= 0, count
|
|
|
+ self.count = count
|
|
|
+
|
|
|
+
|
|
|
class Track:
|
|
|
|
|
|
def __init__(self, path):
|
|
@@ -21,7 +42,44 @@ class Track:
|
|
|
def path(self):
|
|
|
return self._iface.track_path
|
|
|
|
|
|
+ def _get_play_counts(self, player=None, library_id=None):
|
|
|
+ label = 'symuid:pcnt'
|
|
|
+ assert library_id is None or player is not None
|
|
|
+ if player:
|
|
|
+ label += ':' + player
|
|
|
+ if library_id:
|
|
|
+ label += ':' + library_id
|
|
|
+ for k, c in self._iface.get_free_ints(label):
|
|
|
+ player, library_id, register_ts_dec = k.split(':')[2:]
|
|
|
+ yield PlayCount(
|
|
|
+ player=player,
|
|
|
+ library_id=library_id,
|
|
|
+ register_dt=_timestamp_to_utc_dt(int(register_ts_dec)),
|
|
|
+ count=c,
|
|
|
+ )
|
|
|
+
|
|
|
+ def _get_latest_play_counts(self, player=None, library_id=None):
|
|
|
+ latest = {}
|
|
|
+ for count in self._get_play_counts(player, library_id):
|
|
|
+ if not count.player in latest:
|
|
|
+ latest[count.player] = {}
|
|
|
+ if not count.library_id in latest[count.player] \
|
|
|
+ or latest[count.player][count.library_id].register_dt < count.register_dt:
|
|
|
+ latest[count.player][count.library_id] = count
|
|
|
+ return [c for p in latest.values() for c in p.values()]
|
|
|
+
|
|
|
+ def get_latest_play_count(self, player, library_id):
|
|
|
+ assert player is not None, player
|
|
|
+ assert library is not None, library_id
|
|
|
+ counts = self._get_latest_play_counts(player, library_id)
|
|
|
+ if len(counts) == 0:
|
|
|
+ return None
|
|
|
+ else:
|
|
|
+ assert len(counts) == 1, counts
|
|
|
+ return counts[0]
|
|
|
+
|
|
|
def register_play_count(self, player, library_id, register_dt, play_count, tag_set_cb=None):
|
|
|
+ # TODO accept PlayCount as param
|
|
|
assert isinstance(register_dt, dt.datetime), register_dt
|
|
|
assert isinstance(play_count, int), play_count
|
|
|
tag_label = 'symuid:pcnt:{}:{}:{:.0f}'.format(
|