API Reference

Application

Application starts by running run.py, that in turns launches main() function in main.py.

easyplayer.main.main()[source]

main starting point of the application, reads configuration file and setup logging

Core component

class easyplayer.core.App(*args, **kwargs)[source]

Main app component

Child components:

  • WebClient

  • AudioPlayer

  • VideoPlayer

  • Workshop

  • DownloadManager

init(config)[source]

Component initializiation, launches other child components and timers

started(component, *args)[source]

Handler for application started event. Starts timer for check_allowed event.

command(cmd, *args, **kwargs)[source]

handler for command event. Some commands are handled by workshop module and some locally in this class.

content_update()[source]

local command: start download unconditionally

refresh_files()[source]

local command: download and refresh existing files

update_finished(exit_code)[source]

handle actions after update

application_restart(**kw)[source]

local command: terminate application

watchdog()[source]

send message to circus watchdog

check_allowed()[source]

check if allowed to play

finish_download()[source]

reset download status

check_download()[source]

check download status

new_program()[source]

handle new program event

new_info()[source]

handle new info event

no_song_to_play()[source]

check the MediaStream or get the program from server

signal(signo, stack)[source]

catch interrupt

Audio Player

class easyplayer.audio.check_start(*args, **kwargs)[source]

check all start conditions

class easyplayer.audio.check_players(*args, **kwargs)[source]

check if players are running

class easyplayer.audio.start_playing(*args, **kwargs)[source]

start playing

class easyplayer.audio.schedule(*args, **kwargs)[source]

get position and schedule next start

class easyplayer.audio.fade_out(*args, **kwargs)[source]

start fading out current player until stop

class easyplayer.audio.fade_in(*args, **kwargs)[source]

start volume fade in

class easyplayer.audio.play_next(*args, **kwargs)[source]

play next media

class easyplayer.audio.interrupt(*args, **kwargs)[source]

interrupt Event

class easyplayer.audio.not_allowed(*args, **kwargs)[source]

not allowed to play

class easyplayer.audio.check_status(*args, **kwargs)[source]

check status

class easyplayer.audio.MediaPlayer(*args, **kwargs)[source]

Base class for Audio and Video players containg common functionality

check_start()[source]

check if everything is ready to start, repeat if not

new_info()[source]

handle new info from server

check_status(player_name)[source]

check players status

class easyplayer.audio.AudioPlayer(*args, **kwargs)[source]

Audio player communicates with 2 cmus players, schedules switching of songs with crossfade

start_playing()[source]

starting audio - start scheduling

schedule(player_name, skip_next_song=False)[source]

schedule next fade out at the end of the song, fade in of next song and checking status in between

fade_out(player_name)[source]

start fading out current player

play_next(player_name)[source]

start playing next song

fade_in(player_name)[source]

fade in volume

interrupt(event_item)[source]

play time based Event item (not circuits event)

not_allowed()[source]

send not allowed status to web server

reload_programs()[source]

handle reloading of programs

Video Player

class easyplayer.video.resume_playback(*args, **kwargs)[source]

resume paused

class easyplayer.video.stop_playing(*args, **kwargs)[source]

stop playing

class easyplayer.video.VideoPlayer(*args, **kwargs)[source]

Video Player handles switching between 2 omx video players and 2 fbi image viewers according to media type in video stream

play_next(player_name)[source]

play next media

schedule(player_name)[source]

schedule start of next media and checking status in between

Web client

class easyplayer.webclient.WebClient(*args, **kwargs)[source]

Sends heartbeat to server with status data, can get a command in response. Command will be sent to workshop component, web commands will be executed immediately - getting player info or program data. Another task is logging played songs to server.

set_status(status)[source]

used states: playing, stopped, not_allowed, no_song

set_dwld_status(status)[source]

used states: download, waiting, suspended, finished

task_success(event, task, response, **kw)[source]

returned from succesful task

task_failure(event, task, error, **kw)[source]

returned from failed task

update_finished(exit_code)[source]

send update exit code to server

handle_check(response)[source]

process data from server

Workshop

class easyplayer.workshop.Command[source]

command object

reboot(script_path, **kw)[source]

reboot device

firmware_update(data_dir, script_path, token, remote_url, **kw)[source]

update application or system software

send_screenshot(data_dir, script_path, **kw)[source]

take current screenshot and send back

send_logs(data_dir, logfile, **kw)[source]

pack log files and send back

easyplayer.workshop.execute(cmd, **kw)[source]

task executing a command

class easyplayer.workshop.Workshop(*args, **kwargs)[source]

execute commands coming from server

handle(cmd)[source]

handle command

adjust_systime(offset)[source]

adjust system time

Download Manager

class easyplayer.download.switch_storage(*args, **kwargs)[source]

switch current storage to the new one with downloaded files

easyplayer.download.communicate(song, dwld_info, token, remote_url)[source]

send request for media url that can be downloaded

class easyplayer.download.State[source]

An enumeration.

exception easyplayer.download.NoNewProgramData[source]
exception easyplayer.download.NoProgramData[source]
class easyplayer.download.DownloadManager(*args, **kwargs)[source]

handles downloading files from server

handle_download()[source]

download one song from program, if exists or if force is True

task_success(event, task, response, **kw)[source]

returned from succesful task

task_failure(event, task, error, **kw)[source]

returned from unhandled error in download task

start_download(refresh=False, force=False)[source]

start downloading workflow

Keyword Arguments:

  • refresh {bool} – redownload all files

  • force {bool} – start even if suspended

continue_download()[source]

continue download after suspnsion

finish_download()[source]

after finish actions

download_message(message, **kwargs)[source]

compose message for server

Storage

class easyplayer.storage.data.PlayerInfoData(data_dir)[source]

storage for player info

class easyplayer.storage.data.ProgramData(data_dir)[source]

storage for actual program data

switch(other)[source]

move other file to my data path

items()[source]

iterate over program data items

program_hash()[source]

get stored hash of program data

filenames()[source]

iterate over program data file names

existing_files()[source]

iterate over existing file names from program data

class easyplayer.storage.data.NewProgramData(data_dir)[source]

storage for new program data

compare_data(datastring)[source]

return true if equal

program_hash()[source]

get hash of new program data

class easyplayer.storage.data.InitialProgramData(data_dir)[source]

storage for initial data

class easyplayer.storage.files.FileStorage(data_dir, subdir='music')[source]

folder with media files

Watchdog

class easyplayer.circus.watchdog.WatchDog(endpoint, pubsub_endpoint, check_delay, ssh_server, **config)[source]

Plugin that binds an udp socket and waits for watchdog messages. For “watchdoged” processes, the watchdog will kill them (using the “kill” command) if they don’t send heartbeat in a certain period of time materialized by loop_rate * max_count. (circus will automatically restart the missing processes in the watcher)

Each monitored process should send udp message at least at the loop_rate. The udp message format is a line of text, decoded using msg_regex parameter. The heartbeat message MUST at least contain the pid of the process sending the message.

The list of monitored watchers are determined by the parameter watchers_regex in the configuration.

At startup, the plugin does not know all the circus watchers and pids, so it’s needed to discover all watchers and pids. After the discover, the monitoring list is updated by messages from circusd handled in self.handle_recv

Plugin Options –

  • loop_rate – watchdog loop rate in seconds. At each loop, WatchDog will looks for “dead” processes.

  • watchers_regex – regex for matching watcher names that should be monitored by the watchdog (default: “.*” all watchers are monitored)

  • msg_regex – regex for decoding the received heartbeat message in udp (default: “^(?P<pid>.*);(?P<timestamp>.*)$”) the default format is a simple text message: “pid;timestamp”

  • max_count – max number of passed loop without receiving any heartbeat before restarting process (default: 3)

  • ip – ip the watchdog will bind on (default: 127.0.0.1)

  • port – port the watchdog will bind on (default: 1664)

  • watchers_stop_signal – optionally override the stop_signal used when killing the processes

  • watchers_graceful_timeout – optionally override the graceful_timeout used when killing the processes

handle_init()[source]

Initialization of plugin

  • set the periodic call back for the process monitoring (at loop_rate)

  • create the listening UDP socket

handle_stop()[source]

Called right before the plugin is stopped by Circus.

handle_recv(data)[source]

Handle received message from circusd

We need to handle two messages: - spawn: add a new monitored child pid - reap: remove a killed child pid from monitoring

receive_udp_socket(fd, events)[source]

Check the socket for received UDP message. This method is periodically called by the ioloop. If messages are received and parsed, update the status of the corresponing pid.

look_after()[source]

Checks for the watchdoged watchers and restart a process if no received watchdog after the loop_rate * max_count period.