Commit b65f0a1a authored by David Trattnig's avatar David Trattnig
Browse files

Extended data model for single entries and API.

parent 19345293
......@@ -114,12 +114,14 @@ class Schedule(DB.Model, AuraDatabaseModel):
"""
__tablename__ = 'schedule'
# primary and foreign keys
schedule_start = Column(DateTime, primary_key=True)
# Primary keys
id = Column(Integer, primary_key=True, autoincrement=True)
schedule_start = Column(DateTime, unique=True, index=True)
schedule_end = Column(DateTime, unique=True, index=True)
schedule_id = Column(Integer, unique=True)
schedule_end = Column(DateTime)
schedule_id = Column(Integer) #, primary_key=True, autoincrement=False)
show_id = Column(Integer) # well, in fact not needed..
show_id = Column(Integer)
show_name = Column(String(256))
show_hosts = Column(String(256))
funding_category = Column(String(256))
......@@ -409,6 +411,19 @@ class PlaylistEntry(DB.Model, AuraDatabaseModel):
return next_entries
def as_dict(self):
"""
Returns the entry as a dictionary for serialization.
"""
if self.meta_data:
return {
"duration": self.duration,
"artist": self.meta_data.artist,
"album": self.meta_data.album,
"title": self.meta_data.title
}
return None
def __str__(self):
"""
String representation of the object.
......@@ -458,22 +473,73 @@ class TrackService(DB.Model, AuraDatabaseModel):
# Foreign keys
track_start = Column(DateTime)
schedule_start = Column(DateTime, ForeignKey("schedule.schedule_start"))
artificial_playlist_entry_id = Column(Integer, ForeignKey("playlist_entry.artificial_id"))
artificial_schedule_id = Column(Integer, ForeignKey("schedule.id"))
artificial_playlist_entry_id = Column(Integer, ForeignKey("playlist_entry.artificial_id"), nullable=True)
single_entry_id = Column(Integer, ForeignKey("single_entry.id"), nullable=True)
# Data
schedule = relationship("Schedule", foreign_keys=[schedule_start], lazy="joined")
schedule = relationship("Schedule", foreign_keys=[artificial_schedule_id], lazy="joined")
playlist_entry = relationship("PlaylistEntry", primaryjoin="and_(TrackService.artificial_playlist_entry_id==PlaylistEntry.artificial_id)", lazy="joined")
fallback = Column(String(255), nullable=True)
single_entry = relationship("SingleEntry", foreign_keys=[single_entry_id], lazy="joined")
fallback_type = Column(Integer, default=0)
def __init__(self, playlist_entry):
def __init__(self, entry, fallback_type=0):
"""
Initializes a trackservice entry based on a playlist entry.
"""
self.artificial_playlist_entry_id = playlist_entry.artificial_id
self.schedule_start = playlist_entry.playlist.schedule_start
self.track_start = datetime.datetime.now()
self.fallback_type = fallback_type
if fallback_type < 4:
self.schedule_start = entry.playlist.schedule_start
self.artificial_playlist_entry_id = entry.artificial_id
self.playlist_entry = entry
else:
self.single_entry = entry
# @hybrid_property
# def schedule_info(self):
# """
# Retrieves information on the schedule/show.
# """
# info = {}
# schedule.schedule_start
# schedule.schedule_end
# schedule.schedule_id
# show_id = Column(Integer)
# show_name = Column(String(256))
# show_hosts = Column(String(256))
# funding_category = Column(String(256))
# comment = Column(String(512))
# languages = Column(String(256))
# type = Column(String(256))
# category = Column(String(256))
# topic = Column(String(256))
# musicfocus = Column(String(256))
@hybrid_property
def track(self):
"""
Retrieves the track information as a dictionary.
Depending on possible fallback scenarios either `playlist_entry` or `single_entry` is used as a basis:
- Scenario 1: No fallback, all info is gathered via the playlist entry
- Scenario 2: Fallback-type > 0, info is also gathered via the defined playlist entry
- Scenario 3: This type of fallback didn't get scheduled; a local audio-file is played
"""
if self.playlist_entry:
return self.playlist_entry.as_dict()
elif self.single_entry:
return self.single_entry.as_dict()
else:
return None
@staticmethod
......@@ -482,10 +548,6 @@ class TrackService(DB.Model, AuraDatabaseModel):
Select one specific track-service item by ID.
"""
track = DB.session.query(TrackService).filter(TrackService.id == id).first()
track.artist = track.playlist_entry.meta_data[0].artist
track.album = track.playlist_entry.meta_data[0].album
track.title = track.playlist_entry.meta_data[0].title
track.duration = track.playlist_entry.duration
return track
......@@ -495,17 +557,13 @@ class TrackService(DB.Model, AuraDatabaseModel):
Selects the currently playing track.
"""
track = DB.session.query(TrackService).filter(func.max(TrackService.id)).first()
track.artist = track.playlist_entry.meta_data[0].artist
track.album = track.playlist_entry.meta_data[0].album
track.title = track.playlist_entry.meta_data[0].title
track.duration = track.playlist_entry.duration
return track
@staticmethod
def select_last_hours(n):
"""
Selects the tracks playin in the past (`n`) hours.
Selects the tracks playing in the past (`n`) hours.
"""
last_hours = datetime.datetime.today() - datetime.timedelta(hours=n)
tracks = DB.session.query(TrackService).filter(TrackService.track_start >= str(last_hours)).all()
......@@ -520,10 +578,14 @@ class TrackService(DB.Model, AuraDatabaseModel):
Select the track-service items for a day.
"""
day_plus_one = day + datetime.timedelta(days=1)
tracks = DB.session.query(TrackService).filter(TrackService.track_start >= str(day), TrackService.track_start < str(day_plus_one)).all()
for track in tracks:
track = TrackService.select_one(track.id)
return tracks
tracks = DB.session.query(TrackService).\
filter(TrackService.track_start >= str(day), TrackService.track_start < str(day_plus_one)).\
order_by(TrackService.track_start.desc()).all()
res = []
for item in tracks:
if item.track: res.append(item)
return res
@staticmethod
......@@ -544,6 +606,106 @@ class TrackService(DB.Model, AuraDatabaseModel):
class SingleEntry(DB.Model, AuraDatabaseModel):
"""
An entry played in case of e.g. a local fallback or custom programming without a playlist nor schedule.
"""
__tablename__ = 'single_entry'
# Primary keys
id = Column(Integer, primary_key=True)
# Relationships
trackservice_id = Column(Integer) #, ForeignKey("trackservice.id"))
meta_data_id = Column(Integer) #, ForeignKey("trackservice.id"))
trackservice = relationship("TrackService", uselist=False, back_populates="single_entry")
meta_data = relationship("SingleEntryMetaData", uselist=False, back_populates="entry")
# Data
uri = Column(String(1024))
duration = Column(BigInteger)
filename = Column(String(1024))
entry_start = Column(DateTime)
@hybrid_property
def start_unix(self):
return time.mktime(self.entry_start.timetuple())
@hybrid_property
def end_unix(self):
return time.mktime(self.entry_start.timetuple()) + self.duration
@hybrid_property
def volume(self):
return 100
@hybrid_property
def type(self):
if self.uri.startswith("http"):
return ScheduleEntryType.STREAM
if self.uri.startswith("pool") or self.uri.startswith("playlist") or self.uri.startswith("file"):
return ScheduleEntryType.FILESYSTEM
if self.uri.startswith("live") or self.uri.startswith("linein"):
if self.cleansource == "0":
return ScheduleEntryType.LIVE_0
elif self.cleansource == "1":
return ScheduleEntryType.LIVE_1
elif self.cleansource == "2":
return ScheduleEntryType.LIVE_2
elif self.cleansource == "3":
return ScheduleEntryType.LIVE_3
elif self.cleansource == "4":
return ScheduleEntryType.LIVE_4
def as_dict(self):
"""
Returns the entry as a dictionary for serialization.
"""
if self.meta_data:
return {
"duration": self.duration,
"artist": self.meta_data.artist,
"album": self.meta_data.album,
"title": self.meta_data.title
}
return None
def __str__(self):
"""
String representation of the object.
"""
time_start = SimpleUtil.fmt_time(self.start_unix)
time_end = SimpleUtil.fmt_time(self.end_unix)
track = self.filename[-15:]
return "SingleEntry ID#%s [%s - %s | %ssec | Track: ...%s]" % (str(self.id), time_start, time_end, self.duration, track)
class SingleEntryMetaData(DB.Model, AuraDatabaseModel):
"""
Metadata for a autonomous entry such as the artist and track name.
"""
__tablename__ = "single_entry_metadata"
id = Column(Integer, primary_key=True)
single_entry_id = Column(Integer, ForeignKey("single_entry.id"))
artist = Column(String(256))
title = Column(String(256))
album = Column(String(256))
entry = relationship("SingleEntry", uselist=False, back_populates="meta_data")
@staticmethod
def select_metadata_for_entry(single_entry_id):
return DB.session.query(SingleEntry).filter(SingleEntryMetaData.id == single_entry_id).first()
# class TrackServiceSchedule(DB.Model, AuraDatabaseModel):
# """
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment