Fix moving items, force correct weighting.

This commit is contained in:
Matthew Stratford 2021-04-24 21:33:36 +01:00
parent 2bd3dda9df
commit fc7906e246
3 changed files with 54 additions and 15 deletions

View file

@ -14,13 +14,13 @@
import json import json
from typing import Any, Dict, List, Optional from typing import Any, Dict, List, Optional, Union
import os import os
from baps_types.marker import Marker from baps_types.marker import Marker
class PlanItem: class PlanItem:
_timeslotitemid: int = 0 _timeslotitemid: str = "0"
_weight: int = 0 _weight: int = 0
_filename: Optional[str] _filename: Optional[str]
_title: str _title: str
@ -38,9 +38,13 @@ class PlanItem:
self._weight = value self._weight = value
@property @property
def timeslotitemid(self) -> int: def timeslotitemid(self) -> str:
return self._timeslotitemid return self._timeslotitemid
@timeslotitemid.setter
def timeslotitemid(self, value):
self._timeslotitemid = str(value)
@property @property
def filename(self) -> Optional[str]: def filename(self) -> Optional[str]:
return self._filename return self._filename
@ -129,7 +133,7 @@ class PlanItem:
} }
def __init__(self, new_item: Dict[str, Any]): def __init__(self, new_item: Dict[str, Any]):
self._timeslotitemid = new_item["timeslotitemid"] self._timeslotitemid = str(new_item["timeslotitemid"])
self._managedid = new_item["managedid"] if "managedid" in new_item else None self._managedid = new_item["managedid"] if "managedid" in new_item else None
self._trackid = ( self._trackid = (
int(new_item["trackid"]) int(new_item["trackid"])

View file

@ -278,8 +278,17 @@ class Player:
return True return True
def _check_ghosts(self, item: PlanItem):
if isinstance(item.timeslotitemid, str) and item.timeslotitemid.startswith("I"):
# Kinda a bodge for the moment, each "Ghost" (item which is not saved in the database showplan yet) needs to have a unique temporary item.
# To do this, we'll start with the channel number the item was originally added to (to stop items somehow simultaneously added to different channels from having the same id)
# And chuck in the unix epoch in ns for good measure.
item.timeslotitemid = "GHOST-{}-{}".format(self.state.get()["channel"], time.time_ns())
return item
def add_to_plan(self, new_item: Dict[str, Any]) -> bool: def add_to_plan(self, new_item: Dict[str, Any]) -> bool:
new_item_obj = PlanItem(new_item) new_item_obj = PlanItem(new_item)
new_item_obj = self._check_ghosts(new_item_obj)
plan_copy: List[PlanItem] = copy.copy(self.state.get()["show_plan"]) plan_copy: List[PlanItem] = copy.copy(self.state.get()["show_plan"])
# Shift any plan items after the new position down one to make space. # Shift any plan items after the new position down one to make space.
for item in plan_copy: for item in plan_copy:
@ -288,10 +297,7 @@ class Player:
plan_copy += [new_item_obj] # Add the new item. plan_copy += [new_item_obj] # Add the new item.
def sort_weight(e: PlanItem): plan_copy = self._fix_weights(plan_copy)
return e.weight
plan_copy.sort(key=sort_weight) # Sort into weighted order.
self.state.update("show_plan", plan_copy) self.state.update("show_plan", plan_copy)
return True return True
@ -303,11 +309,8 @@ class Player:
if i.weight == weight: if i.weight == weight:
plan_copy.remove(i) plan_copy.remove(i)
found = True found = True
elif (
i.weight > weight
): # Shuffle up the weights of the items following the deleted one.
i.weight -= 1
if found: if found:
plan_copy = self._fix_weights(plan_copy)
self.state.update("show_plan", plan_copy) self.state.update("show_plan", plan_copy)
return True return True
return False return False
@ -490,7 +493,7 @@ class Player:
# This essentially allows the tracklist end API call to happen in a separate thread, to avoid hanging playout/loading. # This essentially allows the tracklist end API call to happen in a separate thread, to avoid hanging playout/loading.
def _potentially_tracklist(self): def _potentially_tracklist(self):
mode: TracklistMode = self.state.get()["tracklist_mode"] mode = self.state.get()["tracklist_mode"]
time: int = -1 time: int = -1
if mode == "on": if mode == "on":
@ -680,6 +683,24 @@ class Player:
self._retMsg(str(self.status), okay_str=True, self._retMsg(str(self.status), okay_str=True,
custom_prefix="ALL:STATUS:") custom_prefix="ALL:STATUS:")
def _fix_weights(self, plan):
def _sort_weight(e: PlanItem):
return e.weight
for item in plan:
self.logger.log.info("Pre weights:\n{}".format(item))
plan.sort(key=_sort_weight) # Sort into weighted order.
for item in plan:
self.logger.log.info("Post Sort:\n{}".format(item))
for i in range(len(plan)):
plan[i].weight = i # Recorrect the weights on the channel.
for item in plan:
self.logger.log.info("Post Weights:\n{}".format(item))
return plan
def __init__( def __init__(
self, channel: int, in_q: multiprocessing.Queue, out_q: multiprocessing.Queue, server_state: StateManager self, channel: int, in_q: multiprocessing.Queue, out_q: multiprocessing.Queue, server_state: StateManager
): ):
@ -707,6 +728,11 @@ class Player:
self.state.update("channel", channel) self.state.update("channel", channel)
self.state.update("tracklist_mode", server_state.get()["tracklist_mode"]) self.state.update("tracklist_mode", server_state.get()["tracklist_mode"])
# Just in case there's any weights somehow messed up, let's fix them.
plan_copy: List[PlanItem] = copy.copy(self.state.get()["show_plan"])
plan_copy = self._fix_weights(plan_copy)
self.state.update("show_plan", plan_copy)
loaded_state = copy.copy(self.state.state) loaded_state = copy.copy(self.state.state)
if loaded_state["output"]: if loaded_state["output"]:

View file

@ -123,7 +123,7 @@ class WebsocketServer:
# Message format: # Message format:
# SOURCE:COMMAND:EXTRADATA # SOURCE:COMMAND:EXTRADATA
message = "WEBSOCKET:" + command message = "WEBSOCKET:"
# If we just want PLAY, PAUSE etc, we're all done. # If we just want PLAY, PAUSE etc, we're all done.
# Else, let's pipe in some extra info. # Else, let's pipe in some extra info.
@ -158,14 +158,22 @@ class WebsocketServer:
# Tell the old channel to remove "weight" # Tell the old channel to remove "weight"
extra += str(data["weight"]) extra += str(data["weight"])
command = "REMOVE"
# Now modify the item with the weight in the new channel # Now modify the item with the weight in the new channel
new_channel = int(data["new_channel"]) new_channel = int(data["new_channel"])
self.logger.log.info(new_channel)
item = data["item"] item = data["item"]
item["weight"] = int(data["new_weight"]) item["weight"] = int(data["new_weight"])
# If we're moving within the same channel, add 1 to the weight, since we're adding the new item before we remove the old one, UI gave us the weight expected after removing.
if channel == new_channel and data["new_weight"] > data["weight"]:
item["weight"] += 1
# Now send the special case. # Now send the special case.
self.channel_to_q[new_channel].put( self.channel_to_q[new_channel].put(
"ADD:" + json.dumps(item)) "WEBSOCKET:ADD:" + json.dumps(item))
except ValueError as e: except ValueError as e:
self.logger.log.exception( self.logger.log.exception(
@ -176,6 +184,7 @@ class WebsocketServer:
pass pass
# Stick the message together and send! # Stick the message together and send!
message += command # Put the command in at the end, in case MOVE etc changed it.
if extra != "": if extra != "":
message += ":" + extra message += ":" + extra