def code_response(ctrl: Api, resp: Union[ApiResponse, models.BaseModel]): """ Convert amplipi.ctrl.Api responses to json/http responses """ if isinstance(resp, ApiResponse): if resp.code == ApiCode.OK: # general commands return None to indicate success return ctrl.get_state() # TODO: refine error codes based on error message raise HTTPException(404, resp.msg) return resp
def view(request: Request, ctrl: Api = Depends(get_ctrl), src: int = 0): """ Webapp main view """ state = ctrl.get_state() context = { # needed for template to make response 'request': request, # simplified amplipi state 'cur_src': src, 'sources': state.sources, 'zones': state.zones, 'groups': state.groups, 'presets': state.presets, 'inputs': [ctrl.get_inputs(src) for src in state.sources], 'unused_groups': [unused_groups(ctrl, src.id) for src in state.sources if src.id is not None], 'unused_zones': [unused_zones(ctrl, src.id) for src in state.sources if src.id is not None], 'ungrouped_zones': [ungrouped_zones(ctrl, src.id) for src in state.sources if src.id is not None], 'song_info': [src.info for src in state.sources if src.info is not None], # src.info should never be None 'version': state.info.version if state.info else 'unknown', } return templates.TemplateResponse('index.html.j2', context, media_type='text/html')
def exec_command(ctrl: Api = Depends(get_ctrl), sid: int = params.StreamID, cmd: models.StreamCommand = None) -> models.Status: """ Executes a comamnd on a stream (stream=**sid**). Command options: * Play Stream: **play** * Pause Stream: **pause** * Skip to next song: **next** * Stop Stream: **stop** * Like/Love Current Song: **love** * Ban Current Song (pandora only): **ban** * Shelve Current Song (pandora only): **shelve** Currently only available with Pandora streams""" return code_response(ctrl, ctrl.exec_stream_command(sid, cmd=cmd))
def get_streams(ctrl: Api = Depends(get_ctrl)) -> Dict[str, List[models.Stream]]: """ Get all streams """ return {'streams' : ctrl.get_state().streams}
def get_stream(ctrl: Api = Depends(get_ctrl), sid: int = params.StreamID) -> models.Stream: """ Get Stream with id=**sid** """ _, stream = utils.find(ctrl.get_state().streams, sid) if stream is not None: return stream raise HTTPException(404, f'stream {sid} not found')
def announce(announcement: models.Announcement, ctrl: Api = Depends(get_ctrl)) -> models.Status: """ Make an announcement """ return code_response(ctrl, ctrl.announce(announcement))
def reset(ctrl: Api = Depends(get_ctrl)) -> models.Status: """ Reload the current configuration, resetting the firmware in the process. """ ctrl.reinit(settings=ctrl._settings, change_notifier=notify_on_change) return ctrl.get_state()
def get_source(ctrl: Api = Depends(get_ctrl), sid: int = params.SourceID) -> models.Source: """ Get Source with id=**sid** """ # TODO: add get_X capabilities to underlying API? sources = ctrl.get_state().sources return sources[sid]
def delete_preset(ctrl: Api = Depends(get_ctrl), pid: int = params.PresetID) -> models.Status: """ Delete a preset """ return code_response(ctrl, ctrl.delete_preset(pid))
def create_group(group: models.Group, ctrl: Api = Depends(get_ctrl)) -> models.Group: """ Create a new grouping of zones """ # TODO: add named example group return code_response(ctrl, ctrl.create_group(group))
def change_station(ctrl: Api = Depends(get_ctrl), sid: int = params.StreamID, station: int = params.StationID) -> models.Status: """ Change station on a pandora stream (stream=**sid**) """ # This is a specific version of exec command, it needs to be placed before the genertic version so the path is resolved properly return code_response(ctrl, ctrl.exec_stream_command(sid, cmd=f'station={station}'))
def set_zone(zone: models.ZoneUpdate, ctrl: Api = Depends(get_ctrl), zid: int = params.ZoneID) -> models.Status: """ Update a zone's configuration (zone=**zid**) """ return code_response(ctrl, ctrl.set_zone(zid, zone))
def set_zones(multi_update: models.MultiZoneUpdate, ctrl: Api = Depends(get_ctrl)) -> models.Status: """ Update a bunch of zones (and groups) with the same configuration changes """ return code_response(ctrl, ctrl.set_zones(multi_update))
def get_zone(ctrl: Api = Depends(get_ctrl), zid: int = params.ZoneID) -> models.Zone: """ Get Zone with id=**zid** """ zones = ctrl.get_state().zones if 0 <= zid < len(zones): return zones[zid] raise HTTPException(404, f'zone {zid} not found')
def get_zones(ctrl: Api = Depends(get_ctrl)) -> Dict[str, List[models.Zone]]: """ Get all zones """ return {'zones': ctrl.get_state().zones}
def set_source(update: models.SourceUpdate, ctrl: Api = Depends(get_ctrl), sid: int = params.SourceID) -> models.Status: """ Update a source's configuration (source=**sid**) """ return code_response(ctrl, ctrl.set_source(sid, update))
def set_stream(ctrl: Api = Depends(get_ctrl), sid: int = params.StreamID, update: models.StreamUpdate = None) -> models.Status: """ Update a stream's configuration (stream=**sid**) """ return code_response(ctrl, ctrl.set_stream(sid, update))
def create_preset(preset: models.Preset, ctrl: Api = Depends(get_ctrl)) -> models.Preset: """ Create a new preset configuration """ return code_response(ctrl, ctrl.create_preset(preset))
def delete_stream(ctrl: Api = Depends(get_ctrl), sid: int = params.StreamID) -> models.Status: """ Delete a stream """ return code_response(ctrl, ctrl.delete_stream(sid))
def get_preset(ctrl: Api = Depends(get_ctrl), pid: int = params.PresetID) -> models.Preset: """ Get Preset with id=**pid** """ _, preset = utils.find(ctrl.get_state().presets, pid) if preset is not None: return preset raise HTTPException(404, f'preset {pid} not found')
def get_groups(ctrl: Api = Depends(get_ctrl)) -> Dict[str, List[models.Group]]: """ Get all groups """ return {'groups' : ctrl.get_state().groups}
def get_sources(ctrl: Api = Depends(get_ctrl)) -> Dict[str, List[models.Source]]: """ Get all sources """ return {'sources' : ctrl.get_state().sources}
def get_presets(ctrl: Api = Depends(get_ctrl)) -> Dict[str, List[models.Preset]]: """ Get all presets """ return {'presets' : ctrl.get_state().presets}
def get_group(ctrl: Api = Depends(get_ctrl), gid: int = params.GroupID) -> models.Group: """ Get Group with id=**gid** """ _, grp = utils.find(ctrl.get_state().groups, gid) if grp is not None: return grp raise HTTPException(404, f'group {gid} not found')
def set_preset(ctrl: Api = Depends(get_ctrl), pid: int = params.PresetID, update: models.PresetUpdate = None) -> models.Status: """ Update a preset's configuration (preset=**pid**) """ return code_response(ctrl, ctrl.set_preset(pid, update))
def set_group(group: models.GroupUpdate, ctrl: Api = Depends(get_ctrl), gid: int = params.GroupID) -> models.Status: """ Update a groups's configuration (group=**gid**) """ return code_response(ctrl, ctrl.set_group(gid, group))
def load_preset(ctrl: Api = Depends(get_ctrl), pid: int = params.PresetID) -> models.Status: """ Load a preset configuration """ return code_response(ctrl, ctrl.load_preset(pid))
def delete_group(ctrl: Api = Depends(get_ctrl), gid: int = params.GroupID) -> models.Status: """ Delete a group (group=**gid**) """ return code_response(ctrl, ctrl.delete_group(gid))
def create_stream(stream: models.Stream, ctrl: Api = Depends(get_ctrl)) -> models.Stream: """ Create a new audio stream - For Pandora the station is the number at the end of the Pandora URL for a 'station', e.g. 4610303469018478727 from https://www.pandora.com/station/play/4610303469018478727. 'user' and 'password' are the account username and password """ return code_response(ctrl, ctrl.create_stream(stream))
def load_config(config: models.Status, ctrl: Api = Depends(get_ctrl)) -> models.Status: """ Load a new configuration (and return the configuration loaded). This will overwrite the current configuration so it is advised to save the previous config from. """ ctrl.reinit(settings=ctrl._settings, change_notifier=notify_on_change, config=config) return ctrl.get_state()