Pypo fixes and improvements
General: * Moved pypo author info into one file * Added two database columns in schedule table: "schedule_group_played" and "media_item_played". API clients: * Created get_liquidsoap_data() function which allows you to give arbitrary data to liquidsoap. * Added documentation * Renamed functions to make it more obvious what is happening pypo_cli: * Got rid of more constants that were not needed * Created function set_export_source() to reduce code repetition * Separated the downloading of the schedule from tracking what has been played. The tracking info is now kept in a separate file. This fixes the major bug that the playlist keeps restarting for the first minute of playback. * converted more print statements to debug statements pypoTester: * Now uses samples from the audio_samples directory, and schedules two audio clips back-to-back.
This commit is contained in:
parent
a138424451
commit
3613812012
|
@ -1,6 +1,15 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# This file holds the implementations for all the API clients.
|
||||||
|
#
|
||||||
|
# If you want to develop a new client, here are some suggestions:
|
||||||
|
# Get the fetch methods working first, then the push, then the liquidsoap notifier.
|
||||||
|
# You will probably want to create a script on your server side to automatically
|
||||||
|
# schedule a playlist one minute from the current time.
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
import urllib
|
import urllib
|
||||||
|
@ -22,49 +31,82 @@ def api_client_factory(config):
|
||||||
|
|
||||||
class ApiClientInterface:
|
class ApiClientInterface:
|
||||||
|
|
||||||
# This is optional.
|
# Implementation: optional
|
||||||
|
#
|
||||||
|
# Called from: beginning of all scripts
|
||||||
|
#
|
||||||
# Should exit the program if this version of pypo is not compatible with
|
# Should exit the program if this version of pypo is not compatible with
|
||||||
# 3rd party software.
|
# 3rd party software.
|
||||||
def check_version(self):
|
def check_version(self):
|
||||||
nil
|
pass
|
||||||
|
|
||||||
# Required.
|
# Implementation: Required
|
||||||
|
#
|
||||||
|
# Called from: fetch loop
|
||||||
|
#
|
||||||
# This is the main method you need to implement when creating a new API client.
|
# This is the main method you need to implement when creating a new API client.
|
||||||
# start and end are for testing purposes.
|
# start and end are for testing purposes.
|
||||||
# start and end are strings in the format YYYY-DD-MM-hh-mm-ss
|
# start and end are strings in the format YYYY-DD-MM-hh-mm-ss
|
||||||
def get_schedule(self, start=None, end=None):
|
def get_schedule(self, start=None, end=None):
|
||||||
return 0, []
|
return 0, []
|
||||||
|
|
||||||
# Required.
|
# Implementation: Required
|
||||||
|
#
|
||||||
|
# Called from: fetch loop
|
||||||
|
#
|
||||||
# This downloads the media from the server.
|
# This downloads the media from the server.
|
||||||
def get_media(self, src, dst):
|
def get_media(self, src, dst):
|
||||||
nil
|
pass
|
||||||
|
|
||||||
# This is optional.
|
# Implementation: optional
|
||||||
# You dont actually have to implement this function for the liquidsoap playout to work.
|
#
|
||||||
def update_scheduled_item(self, item_id, value):
|
# Called from: push loop
|
||||||
nil
|
#
|
||||||
|
# Tell server that the scheduled *playlist* has started.
|
||||||
|
def notify_scheduled_item_start_playing(self, pkey, schedule):
|
||||||
|
pass
|
||||||
|
|
||||||
# This is optional.
|
# Implementation: optional
|
||||||
# You dont actually have to implement this function for the liquidsoap playout to work.
|
# You dont actually have to implement this function for the liquidsoap playout to work.
|
||||||
def update_start_playing(self, playlist_type, export_source, media_id, playlist_id, transmission_id):
|
#
|
||||||
nil
|
# Called from: pypo_notify.py
|
||||||
|
#
|
||||||
|
# This is a callback from liquidsoap, we use this to notify about the
|
||||||
|
# currently playing *song*. We get passed a JSON string which we handed to
|
||||||
|
# liquidsoap in get_liquidsoap_data().
|
||||||
|
def notify_media_item_start_playing(self, data, media_id):
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Implementation: optional
|
||||||
|
# You dont actually have to implement this function for the liquidsoap playout to work.
|
||||||
def generate_range_dp(self):
|
def generate_range_dp(self):
|
||||||
nil
|
pass
|
||||||
|
|
||||||
|
# Implementation: optional
|
||||||
|
#
|
||||||
|
# Called from: push loop
|
||||||
|
#
|
||||||
|
# Return a dict of extra info you want to pass to liquidsoap
|
||||||
|
# You will be able to use this data in update_start_playing
|
||||||
|
def get_liquidsoap_data(self, pkey, schedule):
|
||||||
|
pass
|
||||||
|
|
||||||
# Put here whatever tests you want to run to make sure your API is working
|
# Put here whatever tests you want to run to make sure your API is working
|
||||||
def test(self):
|
def test(self):
|
||||||
nil
|
pass
|
||||||
|
|
||||||
|
|
||||||
#def get_media_type(self, playlist):
|
#def get_media_type(self, playlist):
|
||||||
# nil
|
# nil
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# Campcaster API Client
|
||||||
|
################################################################################
|
||||||
|
|
||||||
class CampcasterApiClient(ApiClientInterface):
|
class CampcasterApiClient(ApiClientInterface):
|
||||||
|
|
||||||
def __init__(self, config):
|
def __init__(self, config):
|
||||||
self.config = config
|
self.config = config
|
||||||
#self.api_auth = api_auth
|
|
||||||
|
|
||||||
def __get_campcaster_version(self):
|
def __get_campcaster_version(self):
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
|
@ -109,7 +151,6 @@ class CampcasterApiClient(ApiClientInterface):
|
||||||
def test(self):
|
def test(self):
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
status, items = self.get_schedule('2010-01-01-00-00-00', '2011-01-01-00-00-00')
|
status, items = self.get_schedule('2010-01-01-00-00-00', '2011-01-01-00-00-00')
|
||||||
#print items
|
|
||||||
schedule = items["playlists"]
|
schedule = items["playlists"]
|
||||||
logger.debug("Number of playlists found: %s", str(len(schedule)))
|
logger.debug("Number of playlists found: %s", str(len(schedule)))
|
||||||
count = 1
|
count = 1
|
||||||
|
@ -117,12 +158,10 @@ class CampcasterApiClient(ApiClientInterface):
|
||||||
logger.debug("Playlist #%s",str(count))
|
logger.debug("Playlist #%s",str(count))
|
||||||
count+=1
|
count+=1
|
||||||
#logger.info("found playlist at %s", pkey)
|
#logger.info("found playlist at %s", pkey)
|
||||||
#print pkey
|
|
||||||
playlist = schedule[pkey]
|
playlist = schedule[pkey]
|
||||||
for item in playlist["medias"]:
|
for item in playlist["medias"]:
|
||||||
filename = urlparse(item["uri"])
|
filename = urlparse(item["uri"])
|
||||||
filename = filename.query[5:]
|
filename = filename.query[5:]
|
||||||
#print filename
|
|
||||||
self.get_media(item["uri"], filename)
|
self.get_media(item["uri"], filename)
|
||||||
|
|
||||||
|
|
||||||
|
@ -142,6 +181,7 @@ class CampcasterApiClient(ApiClientInterface):
|
||||||
print 'pypo is compatible with this version of Campcaster.'
|
print 'pypo is compatible with this version of Campcaster.'
|
||||||
print
|
print
|
||||||
|
|
||||||
|
|
||||||
def get_schedule(self, start=None, end=None):
|
def get_schedule(self, start=None, end=None):
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
@ -183,26 +223,26 @@ class CampcasterApiClient(ApiClientInterface):
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
print e
|
print e
|
||||||
|
|
||||||
schedule = response["playlists"]
|
#schedule = response["playlists"]
|
||||||
scheduleKeys = sorted(schedule.iterkeys())
|
#scheduleKeys = sorted(schedule.iterkeys())
|
||||||
|
#
|
||||||
# Remove all playlists that have passed current time
|
## Remove all playlists that have passed current time
|
||||||
try:
|
#try:
|
||||||
tnow = time.localtime(time.time())
|
# tnow = time.localtime(time.time())
|
||||||
str_tnow_s = "%04d-%02d-%02d-%02d-%02d-%02d" % (tnow[0], tnow[1], tnow[2], tnow[3], tnow[4], tnow[5])
|
# str_tnow_s = "%04d-%02d-%02d-%02d-%02d-%02d" % (tnow[0], tnow[1], tnow[2], tnow[3], tnow[4], tnow[5])
|
||||||
toRemove = []
|
# toRemove = []
|
||||||
for pkey in scheduleKeys:
|
# for pkey in scheduleKeys:
|
||||||
if (str_tnow_s > schedule[pkey]['end']):
|
# if (str_tnow_s > schedule[pkey]['end']):
|
||||||
toRemove.append(pkey)
|
# toRemove.append(pkey)
|
||||||
else:
|
# else:
|
||||||
break
|
# break
|
||||||
#logger.debug("Remove keys: %s", toRemove)
|
# #logger.debug("Remove keys: %s", toRemove)
|
||||||
for index in toRemove:
|
# for index in toRemove:
|
||||||
del schedule[index]
|
# del schedule[index]
|
||||||
#logger.debug("Schedule dict: %s", schedule)
|
# #logger.debug("Schedule dict: %s", schedule)
|
||||||
except Exception, e:
|
#except Exception, e:
|
||||||
logger.debug("'Ignore Past Playlists' feature not supported by API: %s", e)
|
# logger.debug("'Ignore Past Playlists' feature not supported by API: %s", e)
|
||||||
response["playlists"] = schedule
|
#response["playlists"] = schedule
|
||||||
|
|
||||||
return status, response
|
return status, response
|
||||||
|
|
||||||
|
@ -220,51 +260,58 @@ class CampcasterApiClient(ApiClientInterface):
|
||||||
logger.error("%s", e)
|
logger.error("%s", e)
|
||||||
|
|
||||||
|
|
||||||
def update_scheduled_item(self, item_id, value):
|
"""
|
||||||
pass
|
Tell server that the scheduled *playlist* has started.
|
||||||
#logger = logging.getLogger()
|
"""
|
||||||
#
|
def notify_scheduled_item_start_playing(self, pkey, schedule):
|
||||||
#url = self.config["base_url"] + self.config["api_base"] + self.config["update_item_url"]
|
logger = logging.getLogger()
|
||||||
#
|
playlist = schedule[pkey]
|
||||||
#try:
|
schedule_id = playlist["schedule_id"]
|
||||||
# response = urllib.urlopen(url, self.api_auth)
|
url = self.config["base_url"] + self.config["api_base"] + self.config["update_item_url"]
|
||||||
# response = json.read(response.read())
|
url = url.replace("%%schedule_id%%", str(schedule_id))
|
||||||
# logger.info("API-Status %s", response['status'])
|
url += "&api_key=" + self.config["api_key"]
|
||||||
# logger.info("API-Message %s", response['message'])
|
logger.debug(url)
|
||||||
#
|
|
||||||
#except Exception, e:
|
try:
|
||||||
# print e
|
response = urllib.urlopen(url)
|
||||||
# api_status = False
|
response = json.read(response.read())
|
||||||
# logger.critical("Unable to connect - %s", e)
|
logger.info("API-Status %s", response['status'])
|
||||||
#
|
logger.info("API-Message %s", response['message'])
|
||||||
#return response
|
|
||||||
|
except Exception, e:
|
||||||
|
logger.critical("Unable to connect - %s", e)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
def update_start_playing(self, playlist_type, export_source, media_id, playlist_id, transmission_id):
|
"""
|
||||||
pass
|
This is a callback from liquidsoap, we use this to notify about the
|
||||||
#logger = logging.getLogger()
|
currently playing *song*. We get passed a JSON string which we handed to
|
||||||
#
|
liquidsoap in get_liquidsoap_data().
|
||||||
#url = self.config["base_url"] + self.config["api_base"] + self.config["update_start_playing_url"]
|
"""
|
||||||
#url = url.replace("%%playlist_type%%", str(playlist_type))
|
def notify_media_item_start_playing(self, data, media_id):
|
||||||
#url = url.replace("%%export_source%%", str(export_source))
|
logger = logging.getLogger()
|
||||||
#url = url.replace("%%media_id%%", str(media_id))
|
response = ''
|
||||||
#url = url.replace("%%playlist_id%%", str(playlist_id))
|
if (data[0] != '{'):
|
||||||
#url = url.replace("%%transmission_id%%", str(transmission_id))
|
return response
|
||||||
#print url
|
try:
|
||||||
#
|
data = json.read(data)
|
||||||
#try:
|
logger.debug(str(data))
|
||||||
# response = urllib.urlopen(url)
|
schedule_id = data["schedule_id"]
|
||||||
# response = json.read(response.read())
|
url = self.config["base_url"] + self.config["api_base"] + self.config["update_start_playing_url"]
|
||||||
# logger.info("API-Status %s", response['status'])
|
url = url.replace("%%media_id%%", str(media_id))
|
||||||
# logger.info("API-Message %s", response['message'])
|
url = url.replace("%%schedule_id%%", str(schedule_id))
|
||||||
# logger.info("TXT %s", response['str_dls'])
|
url += "&api_key=" + self.config["api_key"]
|
||||||
#
|
logger.debug(url)
|
||||||
#except Exception, e:
|
response = urllib.urlopen(url)
|
||||||
# print e
|
response = json.read(response.read())
|
||||||
# api_status = False
|
logger.info("API-Status %s", response['status'])
|
||||||
# logger.critical("Unable to connect - %s", e)
|
logger.info("API-Message %s", response['message'])
|
||||||
#
|
|
||||||
#return response
|
except Exception, e:
|
||||||
|
logger.critical("Exception: %s", e)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
def generate_range_dp(self):
|
def generate_range_dp(self):
|
||||||
|
@ -287,6 +334,17 @@ class CampcasterApiClient(ApiClientInterface):
|
||||||
#
|
#
|
||||||
#return response
|
#return response
|
||||||
|
|
||||||
|
def get_liquidsoap_data(self, pkey, schedule):
|
||||||
|
logger = logging.getLogger()
|
||||||
|
playlist = schedule[pkey]
|
||||||
|
data = dict()
|
||||||
|
try:
|
||||||
|
data["schedule_id"] = playlist['id']
|
||||||
|
except Exception, e:
|
||||||
|
data["schedule_id"] = 0
|
||||||
|
data = json.write(data)
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
|
@ -327,7 +385,7 @@ class ObpApiClient():
|
||||||
|
|
||||||
|
|
||||||
def get_obp_version(self):
|
def get_obp_version(self):
|
||||||
logger = logging.getLogger("ObpApiClient.get_obp_version")
|
logger = logging.getLogger()
|
||||||
|
|
||||||
# lookup OBP version
|
# lookup OBP version
|
||||||
url = self.config["base_url"] + self.config["api_base"]+ self.config["version_url"]
|
url = self.config["base_url"] + self.config["api_base"]+ self.config["version_url"]
|
||||||
|
@ -369,7 +427,7 @@ class ObpApiClient():
|
||||||
|
|
||||||
|
|
||||||
def get_schedule(self, start=None, end=None):
|
def get_schedule(self, start=None, end=None):
|
||||||
logger = logging.getLogger("CampcasterApiClient.get_schedule")
|
logger = logging.getLogger()
|
||||||
|
|
||||||
"""
|
"""
|
||||||
calculate start/end time range (format: YYYY-DD-MM-hh-mm-ss,YYYY-DD-MM-hh-mm-ss)
|
calculate start/end time range (format: YYYY-DD-MM-hh-mm-ss,YYYY-DD-MM-hh-mm-ss)
|
||||||
|
@ -421,13 +479,15 @@ class ObpApiClient():
|
||||||
logger.error("%s", e)
|
logger.error("%s", e)
|
||||||
|
|
||||||
|
|
||||||
def update_scheduled_item(self, item_id, value):
|
"""
|
||||||
logger = logging.getLogger("ObpApiClient.update_scheduled_item")
|
Tell server that the scheduled *playlist* has started.
|
||||||
# lookup OBP version
|
"""
|
||||||
|
def notify_scheduled_item_start_playing(self, pkey, schedule):
|
||||||
|
#def update_scheduled_item(self, item_id, value):
|
||||||
|
logger = logging.getLogger()
|
||||||
url = self.config["base_url"] + self.config["api_base"] + self.config["update_item_url"]
|
url = self.config["base_url"] + self.config["api_base"] + self.config["update_item_url"]
|
||||||
url = url.replace("%%item_id%%", str(item_id))
|
url = url.replace("%%item_id%%", str(schedule[pkey]["id"]))
|
||||||
url = url.replace("%%played%%", str(value))
|
url = url.replace("%%played%%", "1")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
response = urllib.urlopen(url, self.api_auth)
|
response = urllib.urlopen(url, self.api_auth)
|
||||||
|
@ -442,9 +502,18 @@ class ObpApiClient():
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
"""
|
||||||
def update_start_playing(self, playlist_type, export_source, media_id, playlist_id, transmission_id):
|
This is a callback from liquidsoap, we use this to notify about the
|
||||||
logger = logging.getLogger("ApiClient.update_scheduled_item")
|
currently playing *song*. We get passed a JSON string which we handed to
|
||||||
|
liquidsoap in get_liquidsoap_data().
|
||||||
|
"""
|
||||||
|
def notify_media_item_start_playing(self, data, media_id):
|
||||||
|
# def update_start_playing(self, playlist_type, export_source, media_id, playlist_id, transmission_id):
|
||||||
|
logger = logging.getLogger()
|
||||||
|
playlist_type = data["playlist_type"]
|
||||||
|
export_source = data["export_source"]
|
||||||
|
playlist_id = data["playlist_id"]
|
||||||
|
transmission_id = data["transmission_id"]
|
||||||
|
|
||||||
url = self.config["base_url"] + self.config["api_base"] + self.config["update_start_playing_url"]
|
url = self.config["base_url"] + self.config["api_base"] + self.config["update_start_playing_url"]
|
||||||
url = url.replace("%%playlist_type%%", str(playlist_type))
|
url = url.replace("%%playlist_type%%", str(playlist_type))
|
||||||
|
@ -470,7 +539,7 @@ class ObpApiClient():
|
||||||
|
|
||||||
|
|
||||||
def generate_range_dp(self):
|
def generate_range_dp(self):
|
||||||
logger = logging.getLogger("ObpApiClient.generate_range_dp")
|
logger = logging.getLogger()
|
||||||
|
|
||||||
url = self.config["base_url"] + self.config["api_base"] + self.config["generate_range_url"]
|
url = self.config["base_url"] + self.config["api_base"] + self.config["generate_range_url"]
|
||||||
|
|
||||||
|
@ -486,5 +555,20 @@ class ObpApiClient():
|
||||||
api_status = False
|
api_status = False
|
||||||
logger.critical("Unable to handle the OBP API request - %s", e)
|
logger.critical("Unable to handle the OBP API request - %s", e)
|
||||||
|
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
def get_liquidsoap_data(self, pkey, schedule):
|
||||||
|
playlist = schedule[pkey]
|
||||||
|
data = dict()
|
||||||
|
data["ptype"] = playlist['subtype']
|
||||||
|
try:
|
||||||
|
data["user_id"] = playlist['user_id']
|
||||||
|
data["playlist_id"] = playlist['id']
|
||||||
|
data["transmission_id"] = playlist['schedule_id']
|
||||||
|
except Exception, e:
|
||||||
|
data["playlist_id"] = 0
|
||||||
|
data["user_id"] = 0
|
||||||
|
data["transmission_id"] = 0
|
||||||
|
data = json.write(data)
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
|
@ -14,67 +14,12 @@ api_client = "campcaster"
|
||||||
# _include_ trailing slash !! #
|
# _include_ trailing slash !! #
|
||||||
############################################
|
############################################
|
||||||
cache_dir = '/opt/pypo/cache/'
|
cache_dir = '/opt/pypo/cache/'
|
||||||
schedule_dir = '/opt/pypo/cache/schedule'
|
|
||||||
file_dir = '/opt/pypo/files/'
|
file_dir = '/opt/pypo/files/'
|
||||||
tmp_dir = '/opt/pypo/tmp/'
|
tmp_dir = '/opt/pypo/tmp/'
|
||||||
|
|
||||||
############################################
|
|
||||||
# API path & co #
|
|
||||||
############################################
|
|
||||||
# Value needed to access the API
|
|
||||||
api_key = 'AAA'
|
|
||||||
|
|
||||||
# Hostname
|
# Hostname
|
||||||
base_url = 'http://localhost/'
|
base_url = 'http://localhost/'
|
||||||
|
|
||||||
################################################################################
|
|
||||||
# Generic Config - if you are creating a new API client, define these values #
|
|
||||||
################################################################################
|
|
||||||
# Path to the base of the API
|
|
||||||
#api_base = ''
|
|
||||||
|
|
||||||
# URL to get the version number of the API
|
|
||||||
#version_url = ''
|
|
||||||
|
|
||||||
# Schedule export path.
|
|
||||||
# %%from%% - starting date/time in the form YYYY-MM-DD-hh-mm
|
|
||||||
# %%to%% - starting date/time in the form YYYY-MM-DD-hh-mm
|
|
||||||
#export_url = ''
|
|
||||||
|
|
||||||
# Update whether an item has been played.
|
|
||||||
# %%item_id%%
|
|
||||||
# %%played%%
|
|
||||||
#update_item_url = ''
|
|
||||||
|
|
||||||
# Update whether an item is currently playing.
|
|
||||||
#update_start_playing_url = ''
|
|
||||||
|
|
||||||
# ???
|
|
||||||
#generate_range_url = ''
|
|
||||||
|
|
||||||
|
|
||||||
#####################
|
|
||||||
# Campcaster Config #
|
|
||||||
#####################
|
|
||||||
api_base = 'campcaster/'
|
|
||||||
version_url = 'api/api_version.php?api_key=%%api_key%%'
|
|
||||||
export_url = 'api/schedule.php?from=%%from%%&to=%%to%%&api_key=%%api_key%%'
|
|
||||||
update_item_url = 'api/schedule.php?item_id=%%item_id%%&played=%%played%%'
|
|
||||||
update_start_playing_url = 'api/update_start_playing.php?playlist_type=%%playlist_type%%&export_source=%%export_source%%&media_id=%%media_id%%&playlist_id=%%playlist_id%%&transmission_id=%%transmission_id%%'
|
|
||||||
generate_range_url = 'api/generate_range_dp.php'
|
|
||||||
|
|
||||||
|
|
||||||
##############
|
|
||||||
# OBP config #
|
|
||||||
##############
|
|
||||||
#base_url = 'http://localhost/'
|
|
||||||
#api_base = ''
|
|
||||||
#version_url = 'api/pypo/status/json'
|
|
||||||
#update_item_url = 'api/pypo/update_shedueled_item/$$item_id%%?played=%%played%%'
|
|
||||||
#update_start_playing_url = 'api/pypo/update_start_playing/?playlist_type=%%playlist_type%%&export_source=%%export_source%%&media_id=%%media_id%%&playlist_id=%%playlist_id%%&transmission_id=%%transmission_id%%'
|
|
||||||
#generate_range_url = 'api/pypo/generate_range_dp/'
|
|
||||||
|
|
||||||
|
|
||||||
############################################
|
############################################
|
||||||
# Liquidsoap settings #
|
# Liquidsoap settings #
|
||||||
############################################
|
############################################
|
||||||
|
@ -87,10 +32,90 @@ ls_port = '1234'
|
||||||
prepare_ahead = 24 #in hours
|
prepare_ahead = 24 #in hours
|
||||||
cache_for = 24 #how long to hold the cache, in hours
|
cache_for = 24 #how long to hold the cache, in hours
|
||||||
|
|
||||||
poll_interval = 10 # in seconds
|
# Poll interval in seconds.
|
||||||
|
#
|
||||||
|
# This is how often the poll script downloads new schedules and files from the
|
||||||
|
# server.
|
||||||
|
#
|
||||||
|
# For production use, this number depends on whether you plan on making any
|
||||||
|
# last-minute changes to your schedule. This number should be set to half of
|
||||||
|
# the time you expect to "lock-in" your schedule. So if your schedule is set
|
||||||
|
# 24 hours in advance, this can be set to poll every 12 hours.
|
||||||
|
#
|
||||||
|
poll_interval = 10 # in seconds.
|
||||||
|
|
||||||
|
|
||||||
|
# Push interval in seconds.
|
||||||
|
#
|
||||||
|
# This is how often the push script checks whether it has something new to
|
||||||
|
# push to liquidsoap.
|
||||||
|
#
|
||||||
|
# It's hard to imagine a situation where this should be more than 1 second.
|
||||||
|
#
|
||||||
push_interval = 1 # in seconds
|
push_interval = 1 # in seconds
|
||||||
|
|
||||||
# 'pre' or 'otf'. 'pre' cues while playlist preparation
|
# 'pre' or 'otf'. 'pre' cues while playlist preparation
|
||||||
# while 'otf' (on the fly) cues while loading into ls
|
# while 'otf' (on the fly) cues while loading into ls
|
||||||
# (needs the post_processor patch)
|
# (needs the post_processor patch)
|
||||||
cue_style = 'pre'
|
cue_style = 'pre'
|
||||||
|
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# Uncomment *one of the sets* of values from the API clients below, and comment
|
||||||
|
# out all the others.
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
#####################
|
||||||
|
# Campcaster Config #
|
||||||
|
#####################
|
||||||
|
# Value needed to access the API
|
||||||
|
api_key = 'AAA'
|
||||||
|
|
||||||
|
# Path to the base of the API
|
||||||
|
api_base = 'campcaster/'
|
||||||
|
|
||||||
|
# URL to get the version number of the server API
|
||||||
|
version_url = 'api/api_version.php?api_key=%%api_key%%'
|
||||||
|
|
||||||
|
# Schedule export path.
|
||||||
|
# %%from%% - starting date/time in the form YYYY-MM-DD-hh-mm
|
||||||
|
# %%to%% - starting date/time in the form YYYY-MM-DD-hh-mm
|
||||||
|
export_url = 'api/schedule.php?from=%%from%%&to=%%to%%&api_key=%%api_key%%'
|
||||||
|
|
||||||
|
# Update whether a schedule group has begun playing.
|
||||||
|
update_item_url = 'api/notify_schedule_group_play.php?schedule_id=%%schedule_id%%'
|
||||||
|
|
||||||
|
# Update whether an audio clip is currently playing.
|
||||||
|
update_start_playing_url = 'api/notify_media_item_start_play.php?media_id=%%media_id%%&schedule_id=%%schedule_id%%'
|
||||||
|
|
||||||
|
# ???
|
||||||
|
generate_range_url = 'api/generate_range_dp.php'
|
||||||
|
|
||||||
|
|
||||||
|
##############
|
||||||
|
# OBP config #
|
||||||
|
##############
|
||||||
|
# Value needed to access the API
|
||||||
|
#api_key = 'AAA'
|
||||||
|
|
||||||
|
#base_url = 'http://localhost/'
|
||||||
|
|
||||||
|
# Path to the base of the API
|
||||||
|
#api_base = ''
|
||||||
|
|
||||||
|
# URL to get the version number of the server API
|
||||||
|
#version_url = 'api/pypo/status/json'
|
||||||
|
|
||||||
|
# Schedule export path.
|
||||||
|
# %%from%% - starting date/time in the form YYYY-MM-DD-hh-mm
|
||||||
|
# %%to%% - starting date/time in the form YYYY-MM-DD-hh-mm
|
||||||
|
|
||||||
|
# Update whether an item has been played.
|
||||||
|
#update_item_url = 'api/pypo/update_shedueled_item/$$item_id%%?played=%%played%%'
|
||||||
|
|
||||||
|
# Update whether an item is currently playing.
|
||||||
|
#update_start_playing_url = 'api/pypo/mod/medialibrary/?playlist_type=%%playlist_type%%&export_source=%%export_source%%&media_id=%%media_id%%&playlist_id=%%playlist_id%%&transmission_id=%%transmission_id%%'
|
||||||
|
|
||||||
|
# ???
|
||||||
|
#generate_range_url = 'api/pypo/generate_range_dp/'
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# author Jonas Ohrstrom <jonas@digris.ch>
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Python part of radio playout (pypo)
|
Python part of radio playout (pypo)
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# author Jonas Ohrstrom <jonas@digris.ch>
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Python part of radio playout (pypo)
|
Python part of radio playout (pypo)
|
||||||
|
|
||||||
|
@ -19,7 +17,7 @@ tracks over and over again.
|
||||||
|
|
||||||
Attention & ToDos
|
Attention & ToDos
|
||||||
- liquidsoap does not like mono files! So we have to make sure that only files with
|
- liquidsoap does not like mono files! So we have to make sure that only files with
|
||||||
2 channels are fed to LS
|
2 channels are fed to LiquidSoap
|
||||||
(solved: current = audio_to_stereo(current) - maybe not with ultimate performance)
|
(solved: current = audio_to_stereo(current) - maybe not with ultimate performance)
|
||||||
|
|
||||||
|
|
||||||
|
@ -74,14 +72,14 @@ parser = OptionParser(usage=usage)
|
||||||
parser.add_option("-v", "--compat", help="Check compatibility with server API version", default=False, action="store_true", dest="check_compat")
|
parser.add_option("-v", "--compat", help="Check compatibility with server API version", default=False, action="store_true", dest="check_compat")
|
||||||
|
|
||||||
parser.add_option("-t", "--test", help="Do a test to make sure everything is working properly.", default=False, action="store_true", dest="test")
|
parser.add_option("-t", "--test", help="Do a test to make sure everything is working properly.", default=False, action="store_true", dest="test")
|
||||||
parser.add_option("-f", "--fetch-scheduler", help="Fetch from scheduler - scheduler (loop, interval in config file)", default=False, action="store_true", dest="fetch_scheduler")
|
parser.add_option("-f", "--fetch-scheduler", help="Fetch the schedule from server. This is a polling process that runs forever.", default=False, action="store_true", dest="fetch_scheduler")
|
||||||
parser.add_option("-p", "--push-scheduler", help="Push scheduler to Liquidsoap (loop, interval in config file)", default=False, action="store_true", dest="push_scheduler")
|
parser.add_option("-p", "--push-scheduler", help="Push the schedule to Liquidsoap. This is a polling process that runs forever.", default=False, action="store_true", dest="push_scheduler")
|
||||||
|
|
||||||
parser.add_option("-F", "--fetch-daypart", help="Fetch from daypart - scheduler (loop, interval in config file)", default=False, action="store_true", dest="fetch_daypart")
|
parser.add_option("-F", "--fetch-daypart", help="Fetch from daypart - scheduler (loop, interval in config file)", default=False, action="store_true", dest="fetch_daypart")
|
||||||
parser.add_option("-P", "--push-daypart", help="Push daypart to Liquidsoap (loop, interval in config file)", default=False, action="store_true", dest="push_daypart")
|
parser.add_option("-P", "--push-daypart", help="Push daypart to Liquidsoap (loop, interval in config file)", default=False, action="store_true", dest="push_daypart")
|
||||||
|
|
||||||
parser.add_option("-b", "--cleanup", help="Cleanup", default=False, action="store_true", dest="cleanup")
|
parser.add_option("-b", "--cleanup", help="Cleanup", default=False, action="store_true", dest="cleanup")
|
||||||
parser.add_option("-j", "--jingles", help="Get new jingles from obp, comma separated list if jingle-id's as argument", metavar="LIST")
|
#parser.add_option("-j", "--jingles", help="Get new jingles from server, comma separated list if jingle-id's as argument", metavar="LIST")
|
||||||
parser.add_option("-c", "--check", help="Check the cached schedule and exit", default=False, action="store_true", dest="check")
|
parser.add_option("-c", "--check", help="Check the cached schedule and exit", default=False, action="store_true", dest="check")
|
||||||
|
|
||||||
# parse options
|
# parse options
|
||||||
|
@ -93,32 +91,19 @@ logging.config.fileConfig("logging.cfg")
|
||||||
# loading config file
|
# loading config file
|
||||||
try:
|
try:
|
||||||
config = ConfigObj('config.cfg')
|
config = ConfigObj('config.cfg')
|
||||||
CACHE_DIR = config['cache_dir']
|
|
||||||
FILE_DIR = config['file_dir']
|
|
||||||
TMP_DIR = config['tmp_dir']
|
|
||||||
API_BASE = config['api_base']
|
|
||||||
API_KEY = config['api_key']
|
|
||||||
POLL_INTERVAL = float(config['poll_interval'])
|
POLL_INTERVAL = float(config['poll_interval'])
|
||||||
PUSH_INTERVAL = float(config['push_interval'])
|
PUSH_INTERVAL = float(config['push_interval'])
|
||||||
LS_HOST = config['ls_host']
|
LS_HOST = config['ls_host']
|
||||||
LS_PORT = config['ls_port']
|
LS_PORT = config['ls_port']
|
||||||
#PREPARE_AHEAD = config['prepare_ahead']
|
|
||||||
CACHE_FOR = config['cache_for']
|
|
||||||
CUE_STYLE = config['cue_style']
|
|
||||||
#print config
|
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
print 'Error loading config file: ', e
|
print 'Error loading config file: ', e
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
#TIME = time.localtime(time.time())
|
|
||||||
TIME = (2010, 6, 26, 15, 33, 23, 2, 322, 0)
|
|
||||||
|
|
||||||
class Global:
|
class Global:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
print
|
print
|
||||||
|
|
||||||
def selfcheck(self):
|
def selfcheck(self):
|
||||||
self.api_auth = urllib.urlencode({'api_key': API_KEY})
|
|
||||||
self.api_client = api_client.api_client_factory(config)
|
self.api_client = api_client.api_client_factory(config)
|
||||||
self.api_client.check_version()
|
self.api_client.check_version()
|
||||||
|
|
||||||
|
@ -128,18 +113,23 @@ class Global:
|
||||||
"""
|
"""
|
||||||
class Playout:
|
class Playout:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.file_dir = FILE_DIR
|
|
||||||
self.tmp_dir = TMP_DIR
|
|
||||||
self.api_auth = urllib.urlencode({'api_key': API_KEY})
|
|
||||||
self.api_client = api_client.api_client_factory(config)
|
self.api_client = api_client.api_client_factory(config)
|
||||||
self.cue_file = CueFile()
|
self.cue_file = CueFile()
|
||||||
self.silence_file = self.file_dir + 'basic/silence.mp3'
|
self.silence_file = config["file_dir"] + 'basic/silence.mp3'
|
||||||
|
self.push_ahead = 15
|
||||||
# set initial state
|
|
||||||
self.range_updated = False
|
self.range_updated = False
|
||||||
|
|
||||||
|
|
||||||
def test_api(self):
|
def test_api(self):
|
||||||
self.api_client.test()
|
self.api_client.test()
|
||||||
|
|
||||||
|
|
||||||
|
def set_export_source(self, export_source):
|
||||||
|
self.export_source = export_source
|
||||||
|
self.cache_dir = config["cache_dir"] + self.export_source + '/'
|
||||||
|
self.schedule_file = self.cache_dir + 'schedule.pickle'
|
||||||
|
self.schedule_tracker_file = self.cache_dir + "schedule_tracker.pickle"
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Fetching part of pypo
|
Fetching part of pypo
|
||||||
|
@ -155,9 +145,7 @@ class Playout:
|
||||||
"""
|
"""
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
|
|
||||||
self.export_source = export_source
|
self.set_export_source(export_source)
|
||||||
self.cache_dir = CACHE_DIR + self.export_source + '/'
|
|
||||||
self.schedule_file = self.cache_dir + 'schedule'
|
|
||||||
|
|
||||||
try: os.mkdir(self.cache_dir)
|
try: os.mkdir(self.cache_dir)
|
||||||
except Exception, e: pass
|
except Exception, e: pass
|
||||||
|
@ -185,10 +173,10 @@ class Playout:
|
||||||
except Exception, e: logger.error("%s", e)
|
except Exception, e: logger.error("%s", e)
|
||||||
|
|
||||||
# prepare the playlists
|
# prepare the playlists
|
||||||
if CUE_STYLE == 'pre':
|
if config["cue_style"] == 'pre':
|
||||||
try: self.prepare_playlists_cue(self.export_source)
|
try: self.prepare_playlists_cue()
|
||||||
except Exception, e: logger.error("%s", e)
|
except Exception, e: logger.error("%s", e)
|
||||||
elif CUE_STYLE == 'otf':
|
elif config["cue_style"] == 'otf':
|
||||||
try: self.prepare_playlists(self.export_source)
|
try: self.prepare_playlists(self.export_source)
|
||||||
except Exception, e: logger.error("%s", e)
|
except Exception, e: logger.error("%s", e)
|
||||||
|
|
||||||
|
@ -210,10 +198,10 @@ class Playout:
|
||||||
|
|
||||||
tnow = time.localtime(time.time())
|
tnow = time.localtime(time.time())
|
||||||
|
|
||||||
if(tnow[3] == 16):
|
if (tnow[3] == 16):
|
||||||
self.range_updated = False
|
self.range_updated = False
|
||||||
|
|
||||||
if(tnow[3] == 17 and self.range_updated == False):
|
if (tnow[3] == 17 and self.range_updated == False):
|
||||||
try:
|
try:
|
||||||
print self.api_client.generate_range_dp()
|
print self.api_client.generate_range_dp()
|
||||||
logger.info("daypart updated")
|
logger.info("daypart updated")
|
||||||
|
@ -248,18 +236,11 @@ class Playout:
|
||||||
playlist folder.
|
playlist folder.
|
||||||
file is eg 2010-06-23-15-00-00/17_cue_10.132-123.321.mp3
|
file is eg 2010-06-23-15-00-00/17_cue_10.132-123.321.mp3
|
||||||
"""
|
"""
|
||||||
def prepare_playlists_cue(self, export_source):
|
def prepare_playlists_cue(self):
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
|
|
||||||
self.export_source = export_source
|
# Load schedule from disk
|
||||||
|
schedule = self.load_schedule()
|
||||||
try:
|
|
||||||
schedule_file = open(self.schedule_file, "r")
|
|
||||||
schedule = pickle.load(schedule_file)
|
|
||||||
schedule_file.close()
|
|
||||||
except Exception, e:
|
|
||||||
logger.error("%s", e)
|
|
||||||
schedule = None
|
|
||||||
|
|
||||||
# Dont do anything if schedule is empty
|
# Dont do anything if schedule is empty
|
||||||
if (not schedule):
|
if (not schedule):
|
||||||
|
@ -271,7 +252,6 @@ class Playout:
|
||||||
try:
|
try:
|
||||||
for pkey in scheduleKeys:
|
for pkey in scheduleKeys:
|
||||||
logger.info("found playlist at %s", pkey)
|
logger.info("found playlist at %s", pkey)
|
||||||
#print pkey
|
|
||||||
playlist = schedule[pkey]
|
playlist = schedule[pkey]
|
||||||
|
|
||||||
# create playlist directory
|
# create playlist directory
|
||||||
|
@ -282,18 +262,20 @@ class Playout:
|
||||||
|
|
||||||
ls_playlist = '';
|
ls_playlist = '';
|
||||||
|
|
||||||
print '*****************************************'
|
logger.debug('*****************************************')
|
||||||
print 'pkey: ' + str(pkey)
|
logger.debug('pkey: ' + str(pkey))
|
||||||
print 'cached at : ' + self.cache_dir + str(pkey)
|
logger.debug('cached at : ' + self.cache_dir + str(pkey))
|
||||||
print 'subtype: ' + str(playlist['subtype'])
|
logger.debug('subtype: ' + str(playlist['subtype']))
|
||||||
print 'played: ' + str(playlist['played'])
|
logger.debug('played: ' + str(playlist['played']))
|
||||||
print 'schedule id: ' + str(playlist['schedule_id'])
|
logger.debug('schedule id: ' + str(playlist['schedule_id']))
|
||||||
print 'duration: ' + str(playlist['duration'])
|
logger.debug('duration: ' + str(playlist['duration']))
|
||||||
print 'source id: ' + str(playlist['x_ident'])
|
logger.debug('source id: ' + str(playlist['x_ident']))
|
||||||
print '*****************************************'
|
logger.debug('*****************************************')
|
||||||
|
|
||||||
|
# Creating an API call like the next two lines would make this more flexible
|
||||||
|
# mediaType = api_client.get_media_type(playlist)
|
||||||
|
# if (mediaType == PYPO_MEDIA_SKIP):
|
||||||
|
|
||||||
#mediaType = api_client.get_media_type(playlist)
|
|
||||||
#if (mediaType == PYPO_MEDIA_SKIP):
|
|
||||||
if int(playlist['played']) == 1:
|
if int(playlist['played']) == 1:
|
||||||
logger.info("playlist %s already played / sent to liquidsoap, so will ignore it", pkey)
|
logger.info("playlist %s already played / sent to liquidsoap, so will ignore it", pkey)
|
||||||
|
|
||||||
|
@ -401,7 +383,6 @@ class Playout:
|
||||||
|
|
||||||
if True == os.access(dst, os.R_OK):
|
if True == os.access(dst, os.R_OK):
|
||||||
# check filesize (avoid zero-byte files)
|
# check filesize (avoid zero-byte files)
|
||||||
#print 'waiting: ' + dst
|
|
||||||
try: fsize = os.path.getsize(dst)
|
try: fsize = os.path.getsize(dst)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
logger.error("%s", e)
|
logger.error("%s", e)
|
||||||
|
@ -445,15 +426,11 @@ class Playout:
|
||||||
else:
|
else:
|
||||||
if os.path.isfile(dst):
|
if os.path.isfile(dst):
|
||||||
logger.debug("file already in cache: %s", dst)
|
logger.debug("file already in cache: %s", dst)
|
||||||
#print 'cached'
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
logger.debug("try to download and cue %s", media['uri'])
|
logger.debug("try to download and cue %s", media['uri'])
|
||||||
|
|
||||||
#print '***'
|
dst_tmp = config["tmp_dir"] + "".join([random.choice(string.letters) for i in xrange(10)]) + '.mp3'
|
||||||
dst_tmp = self.tmp_dir + "".join([random.choice(string.letters) for i in xrange(10)]) + '.mp3'
|
|
||||||
#print dst_tmp
|
|
||||||
#print '***'
|
|
||||||
self.api_client.get_media(media['uri'], dst_tmp)
|
self.api_client.get_media(media['uri'], dst_tmp)
|
||||||
|
|
||||||
# cue
|
# cue
|
||||||
|
@ -509,7 +486,7 @@ class Playout:
|
||||||
logger.debug("try to copy and cue %s", media['uri'])
|
logger.debug("try to copy and cue %s", media['uri'])
|
||||||
|
|
||||||
print '***'
|
print '***'
|
||||||
dst_tmp = self.tmp_dir + "".join([random.choice(string.letters) for i in xrange(10)])
|
dst_tmp = config["tmp_dir"] + "".join([random.choice(string.letters) for i in xrange(10)])
|
||||||
print dst_tmp
|
print dst_tmp
|
||||||
print '***'
|
print '***'
|
||||||
|
|
||||||
|
@ -550,10 +527,8 @@ class Playout:
|
||||||
"""
|
"""
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
|
|
||||||
self.export_source = export_source
|
self.set_export_source(export_source)
|
||||||
self.cache_dir = CACHE_DIR + self.export_source + '/'
|
offset = 3600 * int(config["cache_for"])
|
||||||
self.schedule_file = self.cache_dir + 'schedule'
|
|
||||||
offset = 3600 * int(CACHE_FOR)
|
|
||||||
now = time.time()
|
now = time.time()
|
||||||
|
|
||||||
for r, d, f in os.walk(self.cache_dir):
|
for r, d, f in os.walk(self.cache_dir):
|
||||||
|
@ -588,128 +563,109 @@ class Playout:
|
||||||
def push(self, export_source):
|
def push(self, export_source):
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
|
|
||||||
self.export_source = export_source
|
self.set_export_source(export_source)
|
||||||
self.cache_dir = CACHE_DIR + self.export_source + '/'
|
|
||||||
self.schedule_file = self.cache_dir + 'schedule'
|
|
||||||
|
|
||||||
self.push_ahead = 15
|
#try:
|
||||||
|
# dummy = self.schedule
|
||||||
|
# logger.debug('schedule already loaded')
|
||||||
|
#except Exception, e:
|
||||||
|
# self.schedule = self.push_init(self.export_source)
|
||||||
|
|
||||||
|
self.schedule = self.load_schedule()
|
||||||
|
playedItems = self.load_schedule_tracker()
|
||||||
|
|
||||||
try:
|
|
||||||
dummy = self.schedule
|
|
||||||
logger.debug('schedule already loaded')
|
|
||||||
except Exception, e:
|
|
||||||
self.schedule = self.push_init(self.export_source)
|
|
||||||
|
|
||||||
self.schedule = self.push_init(self.export_source)
|
|
||||||
|
|
||||||
|
|
||||||
"""
|
|
||||||
I'm quite sure that this could be achieved in a much more elegant way in python...
|
|
||||||
"""
|
|
||||||
|
|
||||||
tcomming = time.localtime(time.time() + self.push_ahead)
|
tcomming = time.localtime(time.time() + self.push_ahead)
|
||||||
tnow = time.localtime(time.time())
|
tnow = time.localtime(time.time())
|
||||||
|
|
||||||
str_tnow = "%04d-%02d-%02d-%02d-%02d" % (tnow[0], tnow[1], tnow[2], tnow[3], tnow[4])
|
str_tnow = "%04d-%02d-%02d-%02d-%02d" % (tnow[0], tnow[1], tnow[2], tnow[3], tnow[4])
|
||||||
str_tnow_s = "%04d-%02d-%02d-%02d-%02d-%02d" % (tnow[0], tnow[1], tnow[2], tnow[3], tnow[4], tnow[5])
|
str_tnow_s = "%04d-%02d-%02d-%02d-%02d-%02d" % (tnow[0], tnow[1], tnow[2], tnow[3], tnow[4], tnow[5])
|
||||||
|
|
||||||
str_tcomming = "%04d-%02d-%02d-%02d-%02d" % (tcomming[0], tcomming[1], tcomming[2], tcomming[3], tcomming[4])
|
str_tcomming = "%04d-%02d-%02d-%02d-%02d" % (tcomming[0], tcomming[1], tcomming[2], tcomming[3], tcomming[4])
|
||||||
str_tcomming_s = "%04d-%02d-%02d-%02d-%02d-%02d" % (tcomming[0], tcomming[1], tcomming[2], tcomming[3], tcomming[4], tcomming[5])
|
str_tcomming_s = "%04d-%02d-%02d-%02d-%02d-%02d" % (tcomming[0], tcomming[1], tcomming[2], tcomming[3], tcomming[4], tcomming[5])
|
||||||
|
|
||||||
#print '--'
|
|
||||||
#print str_tnow_s + ' now'
|
|
||||||
#print str_tcomming_s + ' comming'
|
|
||||||
|
|
||||||
playnow = None
|
playnow = None
|
||||||
|
|
||||||
if self.schedule == None:
|
if self.schedule == None:
|
||||||
print 'unable to loop schedule - maybe write in progress'
|
logger.warn('Unable to loop schedule - maybe write in progress?')
|
||||||
print 'will try in next loop'
|
logger.warn('Will try again in next loop.')
|
||||||
|
|
||||||
else:
|
else:
|
||||||
for pkey in self.schedule:
|
for pkey in self.schedule:
|
||||||
|
|
||||||
if pkey[0:16] == str_tcomming:
|
if pkey[0:16] == str_tcomming:
|
||||||
logger.debug('Preparing to push playlist scheduled at: %s', pkey)
|
logger.debug('Preparing to push playlist scheduled at: %s', pkey)
|
||||||
playlist = self.schedule[pkey]
|
playlist = self.schedule[pkey]
|
||||||
|
playedFlag = (pkey in playedItems) and playedItems[pkey].get("played", 0)
|
||||||
if int(playlist['played']) != 1:
|
logger.debug("PLAYED FLAG: " + str(playedFlag))
|
||||||
#print '!!!!!!!!!!!!!!!!!!!'
|
if not playedFlag:
|
||||||
#print 'MATCH'
|
# We have a match, replace the current playlist and
|
||||||
|
# force liquidsoap to refresh.
|
||||||
"""
|
|
||||||
ok we have a match, replace the current playlist and
|
|
||||||
force liquidsoap to refresh
|
|
||||||
Add a 'played' state to the list in schedule, so it is not called again
|
|
||||||
in the next push loop
|
|
||||||
"""
|
|
||||||
ptype = playlist['subtype']
|
ptype = playlist['subtype']
|
||||||
|
|
||||||
try:
|
if (self.push_liquidsoap(pkey, self.schedule, ptype) == 1):
|
||||||
user_id = playlist['user_id']
|
|
||||||
playlist_id = playlist['id']
|
|
||||||
transmission_id = playlist['schedule_id']
|
|
||||||
|
|
||||||
except Exception, e:
|
|
||||||
playlist_id = 0
|
|
||||||
user_id = 0
|
|
||||||
transmission_id = 0
|
|
||||||
print e
|
|
||||||
|
|
||||||
#print 'Playlist id:',
|
|
||||||
|
|
||||||
if (self.push_liquidsoap(pkey, ptype, user_id, playlist_id, transmission_id, self.push_ahead) == 1):
|
|
||||||
logger.debug("Pushed to liquidsoap, updating 'played' status.")
|
logger.debug("Pushed to liquidsoap, updating 'played' status.")
|
||||||
self.schedule[pkey]['played'] = 1
|
# Marked the current playlist as 'played' in the schedule tracker
|
||||||
"""
|
# so it is not called again in the next push loop.
|
||||||
Call api to update schedule states and
|
# Write changes back to tracker file.
|
||||||
write changes back to cache file
|
playedItems[pkey] = playlist
|
||||||
"""
|
playedItems[pkey]['played'] = 1
|
||||||
self.api_client.update_scheduled_item(int(playlist['schedule_id']), 1)
|
schedule_tracker = open(self.schedule_tracker_file, "w")
|
||||||
schedule_file = open(self.schedule_file, "w")
|
pickle.dump(playedItems, schedule_tracker)
|
||||||
pickle.dump(self.schedule, schedule_file)
|
schedule_tracker.close()
|
||||||
schedule_file.close()
|
logger.debug("Wrote schedule to disk: "+str(playedItems))
|
||||||
logger.debug("Wrote schedule to disk")
|
|
||||||
|
# Call API to update schedule states
|
||||||
#else:
|
logger.debug("Doing callback to server to update 'played' status.")
|
||||||
# print 'Nothing to do...'
|
self.api_client.notify_scheduled_item_start_playing(pkey, self.schedule)
|
||||||
|
|
||||||
|
|
||||||
def push_init(self, export_source):
|
def load_schedule(self):
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
|
schedule = None
|
||||||
|
|
||||||
self.export_source = export_source
|
# create the file if it doesnt exist
|
||||||
self.cache_dir = CACHE_DIR + self.export_source + '/'
|
if (not os.path.exists(self.schedule_file)):
|
||||||
self.schedule_file = self.cache_dir + 'schedule'
|
logger.debug('creating file ' + self.schedule_file)
|
||||||
|
open(self.schedule_file, 'w').close()
|
||||||
# load the schedule from cache
|
else:
|
||||||
logger.debug('loading schedule from cache...')
|
# load the schedule from cache
|
||||||
try:
|
logger.debug('loading schedule file '+self.schedule_file)
|
||||||
schedule_file = open(self.schedule_file, "r")
|
try:
|
||||||
schedule = pickle.load(schedule_file)
|
schedule_file = open(self.schedule_file, "r")
|
||||||
schedule_file.close()
|
schedule = pickle.load(schedule_file)
|
||||||
|
schedule_file.close()
|
||||||
except Exception, e:
|
|
||||||
logger.error('%s', e)
|
except Exception, e:
|
||||||
schedule = None
|
logger.error('%s', e)
|
||||||
|
|
||||||
return schedule
|
return schedule
|
||||||
|
|
||||||
|
|
||||||
def push_liquidsoap(self, pkey, ptype, user_id, playlist_id, transmission_id, push_ahead):
|
def load_schedule_tracker(self):
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
|
playedItems = dict()
|
||||||
|
|
||||||
|
# create the file if it doesnt exist
|
||||||
|
if (not os.path.exists(self.schedule_tracker_file)):
|
||||||
|
logger.debug('creating file ' + self.schedule_tracker_file)
|
||||||
|
schedule_tracker = open(self.schedule_tracker_file, 'w')
|
||||||
|
pickle.dump(playedItems, schedule_tracker)
|
||||||
|
schedule_tracker.close()
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
logger.debug('loading schedule tracker file '+ self.schedule_tracker_file)
|
||||||
|
schedule_tracker = open(self.schedule_tracker_file, "r")
|
||||||
|
playedItems = pickle.load(schedule_tracker)
|
||||||
|
schedule_tracker.close()
|
||||||
|
except Exception, e:
|
||||||
|
logger.error('Unable to load schedule tracker file: %s', e)
|
||||||
|
|
||||||
|
return playedItems
|
||||||
|
|
||||||
|
|
||||||
#self.export_source = export_source
|
def push_liquidsoap(self, pkey, schedule, ptype):
|
||||||
|
logger = logging.getLogger()
|
||||||
self.push_ahead = push_ahead
|
|
||||||
|
|
||||||
self.cache_dir = CACHE_DIR + self.export_source + '/'
|
|
||||||
self.schedule_file = self.cache_dir + 'schedule'
|
|
||||||
|
|
||||||
src = self.cache_dir + str(pkey) + '/list.lsp'
|
src = self.cache_dir + str(pkey) + '/list.lsp'
|
||||||
|
|
||||||
logger.debug(src)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if True == os.access(src, os.R_OK):
|
if True == os.access(src, os.R_OK):
|
||||||
logger.debug('OK - Can read playlist file')
|
logger.debug('OK - Can read playlist file')
|
||||||
|
@ -724,8 +680,7 @@ class Playout:
|
||||||
if (int(ptype) == 6):
|
if (int(ptype) == 6):
|
||||||
tn.write("live_in.start")
|
tn.write("live_in.start")
|
||||||
tn.write("\n")
|
tn.write("\n")
|
||||||
|
|
||||||
|
|
||||||
if (int(ptype) < 5):
|
if (int(ptype) < 5):
|
||||||
for line in pl_file.readlines():
|
for line in pl_file.readlines():
|
||||||
logger.debug(line.strip())
|
logger.debug(line.strip())
|
||||||
|
@ -741,19 +696,11 @@ class Playout:
|
||||||
logger.debug('sending "flip"')
|
logger.debug('sending "flip"')
|
||||||
tn = telnetlib.Telnet(LS_HOST, 1234)
|
tn = telnetlib.Telnet(LS_HOST, 1234)
|
||||||
|
|
||||||
"""
|
# Get any extra information for liquidsoap (which will be sent back to us)
|
||||||
Pass some extra information to liquidsoap
|
liquidsoap_data = self.api_client.get_liquidsoap_data(pkey, schedule)
|
||||||
"""
|
logger.debug("Sending additional data to liquidsoap: "+liquidsoap_data)
|
||||||
logger.debug('user_id: %s', user_id)
|
tn.write("vars.pypo_data "+liquidsoap_data+"\n")
|
||||||
logger.debug('playlist_id: %s', playlist_id)
|
|
||||||
logger.debug('transmission_id: %s', transmission_id)
|
|
||||||
logger.debug('ptype: %s', ptype)
|
|
||||||
|
|
||||||
tn.write("vars.user_id %s\n" % user_id)
|
|
||||||
tn.write("vars.playlist_id %s\n" % playlist_id)
|
|
||||||
tn.write("vars.transmission_id %s\n" % transmission_id)
|
|
||||||
tn.write("vars.playlist_type %s\n" % ptype)
|
|
||||||
|
|
||||||
# if(int(ptype) < 5):
|
# if(int(ptype) < 5):
|
||||||
# tn.write(self.export_source + '.flip')
|
# tn.write(self.export_source + '.flip')
|
||||||
# tn.write("\n")
|
# tn.write("\n")
|
||||||
|
@ -761,7 +708,7 @@ class Playout:
|
||||||
tn.write(self.export_source + '.flip')
|
tn.write(self.export_source + '.flip')
|
||||||
tn.write("\n")
|
tn.write("\n")
|
||||||
|
|
||||||
if(int(ptype) == 6):
|
if (int(ptype) == 6):
|
||||||
tn.write("live.active 1")
|
tn.write("live.active 1")
|
||||||
tn.write("\n")
|
tn.write("\n")
|
||||||
else:
|
else:
|
||||||
|
@ -772,7 +719,7 @@ class Playout:
|
||||||
|
|
||||||
tn.write("exit\n")
|
tn.write("exit\n")
|
||||||
|
|
||||||
logger.debug(tn.read_all())
|
tn.read_all()
|
||||||
status = 1
|
status = 1
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
logger.error('%s', e)
|
logger.error('%s', e)
|
||||||
|
@ -857,38 +804,38 @@ class Playout:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Updates the jingles. Give comma separated list of jingle tracks.
|
Updates the jingles. Give comma separated list of jingle tracks.
|
||||||
|
|
||||||
|
NOTE: commented out because it needs to be converted to use the API client. - Paul
|
||||||
"""
|
"""
|
||||||
def update_jingles(self, options):
|
#def update_jingles(self, options):
|
||||||
print 'jingles'
|
# print 'jingles'
|
||||||
|
#
|
||||||
jingle_list = string.split(options, ',')
|
# jingle_list = string.split(options, ',')
|
||||||
print jingle_list
|
# print jingle_list
|
||||||
for media_id in jingle_list:
|
# for media_id in jingle_list:
|
||||||
# api path maybe should not be hard-coded
|
# # api path maybe should not be hard-coded
|
||||||
src = API_BASE + 'api/pypo/get_media/' + str(media_id)
|
# src = API_BASE + 'api/pypo/get_media/' + str(media_id)
|
||||||
print src
|
# print src
|
||||||
# include the hourly jungles for the moment
|
# # include the hourly jungles for the moment
|
||||||
dst = "%s%s/%s.mp3" % (self.file_dir, 'jingles/hourly', str(media_id))
|
# dst = "%s%s/%s.mp3" % (config["file_dir"], 'jingles/hourly', str(media_id))
|
||||||
print dst
|
# print dst
|
||||||
|
#
|
||||||
try:
|
# try:
|
||||||
print '** urllib auth with: ',
|
# print '** urllib auth with: ',
|
||||||
print self.api_auth
|
# print self.api_auth
|
||||||
opener = urllib.URLopener()
|
# opener = urllib.URLopener()
|
||||||
opener.retrieve (src, dst, False, self.api_auth)
|
# opener.retrieve (src, dst, False, self.api_auth)
|
||||||
logger.info("downloaded %s to %s", src, dst)
|
# logger.info("downloaded %s to %s", src, dst)
|
||||||
except Exception, e:
|
# except Exception, e:
|
||||||
print e
|
# print e
|
||||||
logger.error("%s", e)
|
# logger.error("%s", e)
|
||||||
|
|
||||||
|
|
||||||
def check_schedule(self, export_source):
|
def check_schedule(self, export_source):
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
|
|
||||||
self.export_source = export_source
|
self.set_export_source(export_source)
|
||||||
self.cache_dir = CACHE_DIR + self.export_source + '/'
|
|
||||||
self.schedule_file = self.cache_dir + 'schedule'
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
schedule_file = open(self.schedule_file, "r")
|
schedule_file = open(self.schedule_file, "r")
|
||||||
schedule = pickle.load(schedule_file)
|
schedule = pickle.load(schedule_file)
|
||||||
|
@ -898,11 +845,8 @@ class Playout:
|
||||||
logger.error("%s", e)
|
logger.error("%s", e)
|
||||||
schedule = None
|
schedule = None
|
||||||
|
|
||||||
#for pkey in schedule:
|
|
||||||
for pkey in sorted(schedule.iterkeys()):
|
for pkey in sorted(schedule.iterkeys()):
|
||||||
|
|
||||||
playlist = schedule[pkey]
|
playlist = schedule[pkey]
|
||||||
|
|
||||||
print '*****************************************'
|
print '*****************************************'
|
||||||
print '\033[0;32m%s %s\033[m' % ('scheduled at:', str(pkey))
|
print '\033[0;32m%s %s\033[m' % ('scheduled at:', str(pkey))
|
||||||
print 'cached at : ' + self.cache_dir + str(pkey)
|
print 'cached at : ' + self.cache_dir + str(pkey)
|
||||||
|
@ -911,7 +855,6 @@ class Playout:
|
||||||
print 'schedule id: ' + str(playlist['schedule_id'])
|
print 'schedule id: ' + str(playlist['schedule_id'])
|
||||||
print 'duration: ' + str(playlist['duration'])
|
print 'duration: ' + str(playlist['duration'])
|
||||||
print 'source id: ' + str(playlist['x_ident'])
|
print 'source id: ' + str(playlist['x_ident'])
|
||||||
|
|
||||||
print '-----------------------------------------'
|
print '-----------------------------------------'
|
||||||
|
|
||||||
for media in playlist['medias']:
|
for media in playlist['medias']:
|
||||||
|
@ -921,7 +864,6 @@ class Playout:
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
||||||
print
|
print
|
||||||
print '###########################################'
|
print '###########################################'
|
||||||
print '# *** pypo *** #'
|
print '# *** pypo *** #'
|
||||||
|
@ -997,11 +939,11 @@ while run == True:
|
||||||
time.sleep(PUSH_INTERVAL)
|
time.sleep(PUSH_INTERVAL)
|
||||||
|
|
||||||
|
|
||||||
while options.jingles:
|
#while options.jingles:
|
||||||
try: po.update_jingles(options.jingles)
|
# try: po.update_jingles(options.jingles)
|
||||||
except Exception, e:
|
# except Exception, e:
|
||||||
print e
|
# print e
|
||||||
sys.exit()
|
# sys.exit()
|
||||||
|
|
||||||
|
|
||||||
while options.check:
|
while options.check:
|
||||||
|
@ -1011,7 +953,7 @@ while run == True:
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
while options.cleanup:
|
while options.cleanup:
|
||||||
try: po.cleanup()
|
try: po.cleanup('scheduler')
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
print e
|
print e
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
|
@ -1,21 +1,18 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# author Jonas Ohrstrom <jonas@digris.ch>
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Python part of radio playout (pypo)
|
Python part of radio playout (pypo)
|
||||||
|
|
||||||
This function acts as a gateway between liquidsoap and the obp-api.
|
This function acts as a gateway between liquidsoap and the obp-api.
|
||||||
Mainliy used to tell the plattform what pypo/LS does.
|
Mainliy used to tell the platform what pypo/LS does.
|
||||||
|
|
||||||
Main case:
|
Main case:
|
||||||
- whenever Liquidsoap starts playing a new track, its on_metadata callback calls
|
- whenever Liquidsoap starts playing a new track, its on_metadata callback calls
|
||||||
a function in liquidsoap (notify(m)) which then calls the python script here
|
a function in liquidsoap (notify(m)) which then calls the python script here
|
||||||
with the currently starting filename as parameter
|
with the currently starting filename as parameter
|
||||||
- this python script takes this parameter, tries to extract the actual
|
- this python script takes this parameter, tries to extract the actual
|
||||||
media id from it, and then calls back to obp via api to tell about
|
media id from it, and then calls back to API to tell it about it.
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -171,7 +168,6 @@ class Notify:
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
||||||
print
|
print
|
||||||
print '#########################################'
|
print '#########################################'
|
||||||
print '# *** pypo *** #'
|
print '# *** pypo *** #'
|
||||||
|
|
|
@ -1,21 +1,18 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# author Jonas Ohrstrom <jonas@digris.ch>
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Python part of radio playout (pypo)
|
Python part of radio playout (pypo)
|
||||||
|
|
||||||
This function acts as a gateway between liquidsoap and the obp-api.
|
This function acts as a gateway between liquidsoap and the server API.
|
||||||
Mainliy used to tell the plattform what pypo/LS does.
|
Mainly used to tell the platform what pypo/liquidsoap does.
|
||||||
|
|
||||||
Main case:
|
Main case:
|
||||||
- whenever LS starts playing a new track, its on_metadata callback calls
|
- whenever LS starts playing a new track, its on_metadata callback calls
|
||||||
a function in ls (notify(m)) which then calls the pythin script here
|
a function in ls (notify(m)) which then calls the python script here
|
||||||
with the currently starting filename as parameter
|
with the currently starting filename as parameter
|
||||||
- this python script takes this parameter, tries to extract the actual
|
- this python script takes this parameter, tries to extract the actual
|
||||||
media id from it, and then calls back to obp via api to tell about
|
media id from it, and then calls back to the API to tell about it about it.
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -52,14 +49,14 @@ usage = "%prog [options]" + " - notification gateway"
|
||||||
parser = OptionParser(usage=usage)
|
parser = OptionParser(usage=usage)
|
||||||
|
|
||||||
# Options
|
# Options
|
||||||
#parser.add_option("-p", "--playing", help="Tell daddy what is playing right now", dest="playing", default=False, metavar=False)
|
parser.add_option("-d", "--data", help="Pass JSON data from liquidsoap into this script.", metavar="data")
|
||||||
parser.add_option("-p", "--playing", help="Tell daddy what is playing right now", default=False, action="store_true", dest="playing")
|
#parser.add_option("-p", "--playing", help="Tell server what is playing right now.", default=False, action="store_true", dest="playing")
|
||||||
parser.add_option("-t", "--playlist-type", help="Tell daddy what is playing right now", metavar="playlist_type")
|
#parser.add_option("-t", "--playlist-type", help="", metavar="playlist_type")
|
||||||
parser.add_option("-M", "--media-id", help="Tell daddy what is playing right now", metavar="media_id")
|
parser.add_option("-m", "--media-id", help="ID of the file that is currently playing.", metavar="media_id")
|
||||||
parser.add_option("-U", "--user-id", help="Tell daddy what is playing right now", metavar="user_id")
|
#parser.add_option("-U", "--user-id", help="", metavar="user_id")
|
||||||
parser.add_option("-P", "--playlist-id", help="Tell daddy what is playing right now", metavar="playlist_id")
|
#parser.add_option("-P", "--playlist-id", help="", metavar="playlist_id")
|
||||||
parser.add_option("-T", "--transmission-id", help="Tell daddy what is playing right now", metavar="transmission_id")
|
#parser.add_option("-T", "--transmission-id", help="", metavar="transmission_id")
|
||||||
parser.add_option("-E", "--export-source", help="Tell daddy what is playing right now", metavar="export_source")
|
#parser.add_option("-E", "--export-source", help="", metavar="export_source")
|
||||||
|
|
||||||
# parse options
|
# parse options
|
||||||
(options, args) = parser.parse_args()
|
(options, args) = parser.parse_args()
|
||||||
|
@ -70,10 +67,6 @@ logging.config.fileConfig("logging.cfg")
|
||||||
# loading config file
|
# loading config file
|
||||||
try:
|
try:
|
||||||
config = ConfigObj('config.cfg')
|
config = ConfigObj('config.cfg')
|
||||||
TMP_DIR = config['tmp_dir']
|
|
||||||
BASE_URL = config['base_url']
|
|
||||||
API_BASE = BASE_URL + 'mod/medialibrary/'
|
|
||||||
API_KEY = config['api_key']
|
|
||||||
|
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
print 'error: ', e
|
print 'error: ', e
|
||||||
|
@ -85,144 +78,156 @@ class Global:
|
||||||
print
|
print
|
||||||
|
|
||||||
def selfcheck(self):
|
def selfcheck(self):
|
||||||
|
pass
|
||||||
self.api_auth = urllib.urlencode({'api_key': API_KEY})
|
#self.api_client = api_client.api_client_factory(config)
|
||||||
self.api_client = api_client.api_client_factory(config)
|
#self.api_client.check_version()
|
||||||
self.api_client.check_version()
|
|
||||||
|
|
||||||
class Notify:
|
class Notify:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.tmp_dir = TMP_DIR
|
|
||||||
self.api_auth = urllib.urlencode({'api_key': API_KEY})
|
|
||||||
self.api_client = api_client.api_client_factory(config)
|
self.api_client = api_client.api_client_factory(config)
|
||||||
self.dls_client = DlsClient('127.0.0.128', 50008, 'myusername', 'mypass')
|
#self.dls_client = DlsClient('127.0.0.128', 50008, 'myusername', 'mypass')
|
||||||
|
|
||||||
|
|
||||||
def start_playing(self, options):
|
def notify_media_start_playing(self, data, media_id):
|
||||||
logger = logging.getLogger("start_playing")
|
logger = logging.getLogger()
|
||||||
tnow = time.localtime(time.time())
|
#tnow = time.localtime(time.time())
|
||||||
|
|
||||||
#print options
|
logger.debug('#################################################')
|
||||||
|
logger.debug('# Calling server to update about what\'s playing #')
|
||||||
print '#################################################'
|
logger.debug('#################################################')
|
||||||
print '# calling obp to tell about what\'s playing #'
|
logger.debug('data = '+ str(data))
|
||||||
print '#################################################'
|
#print 'options.data = '+ options.data
|
||||||
|
#data = json.read(options.data)
|
||||||
if int(options.playlist_type) < 5:
|
response = self.api_client.notify_media_item_start_playing(data, media_id)
|
||||||
print 'seems to be a playlist'
|
logger.debug("Response: "+str(response))
|
||||||
|
|
||||||
try:
|
|
||||||
media_id = int(options.media_id)
|
|
||||||
except Exception, e:
|
|
||||||
media_id = 0
|
|
||||||
|
|
||||||
response = self.api_client.update_start_playing(options.playlist_type, options.export_source, media_id, options.playlist_id, options.transmission_id)
|
|
||||||
|
|
||||||
print response
|
|
||||||
|
|
||||||
if int(options.playlist_type) == 6:
|
|
||||||
print 'seems to be a couchcast'
|
|
||||||
|
|
||||||
try:
|
|
||||||
media_id = int(options.media_id)
|
|
||||||
except Exception, e:
|
|
||||||
media_id = 0
|
|
||||||
|
|
||||||
response = self.api_client.update_start_playing(options.playlist_type, options.export_source, media_id, options.playlist_id, options.transmission_id)
|
|
||||||
|
|
||||||
print response
|
|
||||||
|
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
|
#def start_playing(self, options):
|
||||||
|
# logger = logging.getLogger("start_playing")
|
||||||
|
# tnow = time.localtime(time.time())
|
||||||
|
#
|
||||||
|
# #print options
|
||||||
|
#
|
||||||
|
# logger.debug('#################################################')
|
||||||
|
# logger.debug('# Calling server to update about what\'s playing #')
|
||||||
|
# logger.debug('#################################################')
|
||||||
|
#
|
||||||
|
# if int(options.playlist_type) < 5:
|
||||||
|
# logger.debug('seems to be a playlist')
|
||||||
|
#
|
||||||
|
# try:
|
||||||
|
# media_id = int(options.media_id)
|
||||||
|
# except Exception, e:
|
||||||
|
# media_id = 0
|
||||||
|
#
|
||||||
|
# response = self.api_client.update_start_playing(options.playlist_type, options.export_source, media_id, options.playlist_id, options.transmission_id)
|
||||||
|
#
|
||||||
|
# logger.debug(response)
|
||||||
|
#
|
||||||
|
# if int(options.playlist_type) == 6:
|
||||||
|
# logger.debug('seems to be a couchcast')
|
||||||
|
#
|
||||||
|
# try:
|
||||||
|
# media_id = int(options.media_id)
|
||||||
|
# except Exception, e:
|
||||||
|
# media_id = 0
|
||||||
|
#
|
||||||
|
# response = self.api_client.update_start_playing(options.playlist_type, options.export_source, media_id, options.playlist_id, options.transmission_id)
|
||||||
|
#
|
||||||
|
# logger.debug(response)
|
||||||
|
#
|
||||||
|
# sys.exit()
|
||||||
|
|
||||||
def start_playing_legacy(self, options):
|
#def start_playing_legacy(self, options):
|
||||||
logger = logging.getLogger("start_playing")
|
# logger = logging.getLogger("start_playing")
|
||||||
tnow = time.localtime(time.time())
|
# tnow = time.localtime(time.time())
|
||||||
|
#
|
||||||
print '#################################################'
|
# print '#################################################'
|
||||||
print '# calling obp to tell about what\'s playing #'
|
# print '# Calling server to update about what\'s playing #'
|
||||||
print '#################################################'
|
# print '#################################################'
|
||||||
|
#
|
||||||
path = options
|
# path = options
|
||||||
|
#
|
||||||
print
|
# print
|
||||||
print path
|
# print path
|
||||||
print
|
# print
|
||||||
|
#
|
||||||
if 'pl_id' in path:
|
# if 'pl_id' in path:
|
||||||
print 'seems to be a playlist'
|
# print 'seems to be a playlist'
|
||||||
type = 'playlist'
|
# type = 'playlist'
|
||||||
id = path[5:]
|
# id = path[5:]
|
||||||
|
#
|
||||||
elif 'text' in path:
|
# elif 'text' in path:
|
||||||
print 'seems to be a playlist'
|
# print 'seems to be a playlist'
|
||||||
type = 'text'
|
# type = 'text'
|
||||||
id = path[4:]
|
# id = path[4:]
|
||||||
print id
|
# print id
|
||||||
|
#
|
||||||
else:
|
# else:
|
||||||
print 'seems to be a single track (media)'
|
# print 'seems to be a single track (media)'
|
||||||
type = 'media'
|
# type = 'media'
|
||||||
try:
|
# try:
|
||||||
file = path.split("/")[-1:][0]
|
# file = path.split("/")[-1:][0]
|
||||||
if file.find('_cue_') > 0:
|
# if file.find('_cue_') > 0:
|
||||||
id = file.split("_cue_")[0]
|
# id = file.split("_cue_")[0]
|
||||||
else:
|
# else:
|
||||||
id = file.split(".")[-2:][0]
|
# id = file.split(".")[-2:][0]
|
||||||
|
#
|
||||||
except Exception, e:
|
# except Exception, e:
|
||||||
#print e
|
# #print e
|
||||||
id = False
|
# id = False
|
||||||
|
#
|
||||||
try:
|
# try:
|
||||||
id = id
|
# id = id
|
||||||
except Exception, e:
|
# except Exception, e:
|
||||||
#print e
|
# #print e
|
||||||
id = False
|
# id = False
|
||||||
|
#
|
||||||
print
|
# print
|
||||||
print type + " id: ",
|
# print type + " id: ",
|
||||||
print id
|
# print id
|
||||||
|
#
|
||||||
|
#
|
||||||
response = self.api_client.update_start_playing(type, id, self.export_source, path)
|
# response = self.api_client.update_start_playing(type, id, self.export_source, path)
|
||||||
|
#
|
||||||
print 'DONE'
|
# print 'DONE'
|
||||||
|
#
|
||||||
try:
|
# try:
|
||||||
txt = response['txt']
|
# txt = response['txt']
|
||||||
print '#######################################'
|
# print '#######################################'
|
||||||
print txt
|
# print txt
|
||||||
print '#######################################'
|
# print '#######################################'
|
||||||
#self.dls_client.set_txt(txt)
|
# #self.dls_client.set_txt(txt)
|
||||||
|
#
|
||||||
except Exception, e:
|
# except Exception, e:
|
||||||
print e
|
# print e
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
||||||
print
|
print
|
||||||
print '#########################################'
|
print '#########################################'
|
||||||
print '# *** pypo *** #'
|
print '# *** pypo *** #'
|
||||||
print '# pypo notification gateway #'
|
print '# pypo notification gateway #'
|
||||||
print '#########################################'
|
print '#########################################'
|
||||||
print
|
|
||||||
|
|
||||||
# initialize
|
# initialize
|
||||||
g = Global()
|
g = Global()
|
||||||
g.selfcheck()
|
logger = logging.getLogger()
|
||||||
n = Notify()
|
#if options.playing:
|
||||||
|
# try: n.start_playing(options)
|
||||||
|
# except Exception, e:
|
||||||
run = True
|
# print e
|
||||||
while run == True:
|
# sys.exit()
|
||||||
logger = logging.getLogger("pypo notify")
|
if not options.data:
|
||||||
|
print "NOTICE: 'data' command-line argument not given."
|
||||||
if options.playing:
|
sys.exit()
|
||||||
try: n.start_playing(options)
|
|
||||||
except Exception, e:
|
if not options.media_id:
|
||||||
print e
|
print "NOTICE: 'media_id' command-line argument not given."
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
sys.exit()
|
try:
|
||||||
|
g.selfcheck()
|
||||||
|
n = Notify()
|
||||||
|
n.notify_media_start_playing(options.data, options.media_id)
|
||||||
|
except Exception, e:
|
||||||
|
print e
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# author Jonas Ohrstrom <jonas@digris.ch>
|
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
cue script that gets called by liquidsoap if a file in the playlist
|
cue script that gets called by liquidsoap if a file in the playlist
|
||||||
|
|
|
@ -6,7 +6,11 @@ playlist_id = ref '0'
|
||||||
user_id = ref '0'
|
user_id = ref '0'
|
||||||
transmission_id = ref '0'
|
transmission_id = ref '0'
|
||||||
playlist_type = ref '0'
|
playlist_type = ref '0'
|
||||||
|
pypo_data = ref '0'
|
||||||
|
|
||||||
|
def set_pypo_data(s)
|
||||||
|
pypo_data := s
|
||||||
|
end
|
||||||
|
|
||||||
def set_user_id(s)
|
def set_user_id(s)
|
||||||
user_id := s
|
user_id := s
|
||||||
|
@ -29,4 +33,5 @@ end
|
||||||
server.register(namespace="vars", "user_id", fun (s) -> begin set_user_id(s) "Done!" end)
|
server.register(namespace="vars", "user_id", fun (s) -> begin set_user_id(s) "Done!" end)
|
||||||
server.register(namespace="vars", "playlist_id", fun (s) -> begin set_playlist_id(s) "Done!" end)
|
server.register(namespace="vars", "playlist_id", fun (s) -> begin set_playlist_id(s) "Done!" end)
|
||||||
server.register(namespace="vars", "transmission_id", fun (s) -> begin set_transmission_id(s) "Done!" end)
|
server.register(namespace="vars", "transmission_id", fun (s) -> begin set_transmission_id(s) "Done!" end)
|
||||||
server.register(namespace="vars", "playlist_type", fun (s) -> begin set_playlist_type(s) "Done!" end)
|
server.register(namespace="vars", "playlist_type", fun (s) -> begin set_playlist_type(s) "Done!" end)
|
||||||
|
server.register(namespace="vars", "pypo_data", fun (s) -> begin set_pypo_data(s) "Done!" end)
|
|
@ -4,10 +4,10 @@
|
||||||
|
|
||||||
def notify(m)
|
def notify(m)
|
||||||
|
|
||||||
print('user_id: #{!user_id}')
|
# print('user_id: #{!user_id}')
|
||||||
print('playlist_id: #{!playlist_id}')
|
# print('playlist_id: #{!playlist_id}')
|
||||||
print('transmission_id: #{!transmission_id}')
|
# print('transmission_id: #{!transmission_id}')
|
||||||
print('playlist_type: #{!playlist_type}')
|
# print('playlist_type: #{!playlist_type}')
|
||||||
|
|
||||||
if !playlist_type=='5' then
|
if !playlist_type=='5' then
|
||||||
print('livesession')
|
print('livesession')
|
||||||
|
@ -20,8 +20,9 @@ def notify(m)
|
||||||
end
|
end
|
||||||
|
|
||||||
if !playlist_type=='0' or !playlist_type=='1' or !playlist_type=='2' or !playlist_type=='3' or !playlist_type=='4' then
|
if !playlist_type=='0' or !playlist_type=='1' or !playlist_type=='2' or !playlist_type=='3' or !playlist_type=='4' then
|
||||||
print('playlist')
|
print('include_notify.liq: notify on playlist')
|
||||||
system("./notify.sh --playing --playlist-type=#{!playlist_type} --media-id=#{m['media_id']} --export-source=#{m['export_source']}")
|
#system("./notify.sh --playing --playlist-type=#{!playlist_type} --media-id=#{m['media_id']} --export-source=#{m['export_source']}")
|
||||||
|
system("./notify.sh --data='#{!pypo_data}' --media-id=#{m['media_id']}")
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
|
@ -2,9 +2,6 @@
|
||||||
# liquidsoap config file #
|
# liquidsoap config file #
|
||||||
###########################################
|
###########################################
|
||||||
|
|
||||||
# author Jonas Ohrstrom <jonas@digris.ch>
|
|
||||||
|
|
||||||
|
|
||||||
# this file is specific to the obp
|
# this file is specific to the obp
|
||||||
# installation. eg it assumes that there are
|
# installation. eg it assumes that there are
|
||||||
# two instances of LS running
|
# two instances of LS running
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# author Jonas Ohrstrom <jonas@digris.ch>
|
|
||||||
# Register the cut protocol
|
# Register the cut protocol
|
||||||
def cue_protocol(arg,delay)
|
def cue_protocol(arg,delay)
|
||||||
# The extraction program
|
# The extraction program
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# author Jonas Ohrstrom <jonas@digris.ch>
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import shutil
|
import shutil
|
||||||
import random
|
import random
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
require_once('../conf.php');
|
require_once('../conf.php');
|
||||||
require_once('DB.php');
|
|
||||||
require_once('../backend/StoredFile.php');
|
require_once('../backend/StoredFile.php');
|
||||||
|
|
||||||
$api_key = $_GET['api_key'];
|
$api_key = $_GET['api_key'];
|
||||||
|
@ -13,13 +12,6 @@ if(!in_array($api_key, $CC_CONFIG["apiKey"]))
|
||||||
|
|
||||||
PEAR::setErrorHandling(PEAR_ERROR_RETURN);
|
PEAR::setErrorHandling(PEAR_ERROR_RETURN);
|
||||||
|
|
||||||
$CC_DBC = DB::connect($CC_CONFIG['dsn'], TRUE);
|
|
||||||
if (PEAR::isError($CC_DBC)) {
|
|
||||||
echo "ERROR: ".$CC_DBC->getMessage()." ".$CC_DBC->getUserInfo()."\n";
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
$CC_DBC->setFetchMode(DB_FETCHMODE_ASSOC);
|
|
||||||
|
|
||||||
$filename = $_GET["file"];
|
$filename = $_GET["file"];
|
||||||
$file_id = substr($filename, 0, strpos($filename, "."));
|
$file_id = substr($filename, 0, strpos($filename, "."));
|
||||||
if (ctype_alnum($file_id) && strlen($file_id) == 32) {
|
if (ctype_alnum($file_id) && strlen($file_id) == 32) {
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
<?php
|
||||||
|
require_once('../conf.php');
|
||||||
|
require_once('../backend/Schedule.php');
|
||||||
|
|
||||||
|
$api_key = $_GET['api_key'];
|
||||||
|
if(!in_array($api_key, $CC_CONFIG["apiKey"]))
|
||||||
|
{
|
||||||
|
header('HTTP/1.0 401 Unauthorized');
|
||||||
|
print 'You are not allowed to access this resource.';
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
PEAR::setErrorHandling(PEAR_ERROR_RETURN);
|
||||||
|
|
||||||
|
$schedule_group_id = $_GET["schedule_id"];
|
||||||
|
$media_id = $_GET["media_id"];
|
||||||
|
$f = StoredFile::RecallByGunid($media_id);
|
||||||
|
|
||||||
|
if (is_numeric($schedule_group_id)) {
|
||||||
|
$sg = new ScheduleGroup($schedule_group_id);
|
||||||
|
if ($sg->exists()) {
|
||||||
|
$result = $sg->notifyMediaItemStartPlay($f->getId());
|
||||||
|
if (!PEAR::isError($result)) {
|
||||||
|
echo json_encode(array("status"=>1, "message"=>""));
|
||||||
|
exit;
|
||||||
|
} else {
|
||||||
|
echo json_encode(array("status"=>0, "message"=>"DB Error:".$result->getMessage()));
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
echo json_encode(array("status"=>0, "message"=>"Schedule group does not exist: ".$schedule_group_id));
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
echo json_encode(array("status"=>0, "message" => "Incorrect or non-numeric arguments given."));
|
||||||
|
}
|
||||||
|
?>
|
|
@ -0,0 +1,35 @@
|
||||||
|
<?php
|
||||||
|
require_once('../conf.php');
|
||||||
|
require_once('../backend/Schedule.php');
|
||||||
|
|
||||||
|
$api_key = $_GET['api_key'];
|
||||||
|
if (!in_array($api_key, $CC_CONFIG["apiKey"]))
|
||||||
|
{
|
||||||
|
header('HTTP/1.0 401 Unauthorized');
|
||||||
|
print 'You are not allowed to access this resource.';
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
PEAR::setErrorHandling(PEAR_ERROR_RETURN);
|
||||||
|
|
||||||
|
$schedule_group_id = $_GET["schedule_id"];
|
||||||
|
if (is_numeric($schedule_group_id)) {
|
||||||
|
$sg = new ScheduleGroup($schedule_group_id);
|
||||||
|
if ($sg->exists()) {
|
||||||
|
$result = $sg->notifyGroupStartPlay();
|
||||||
|
if (!PEAR::isError($result)) {
|
||||||
|
echo json_encode(array("status"=>1, "message"=>""));
|
||||||
|
exit;
|
||||||
|
} else {
|
||||||
|
echo json_encode(array("status"=>0, "message"=>"DB Error:".$result->getMessage()));
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
echo json_encode(array("status"=>0, "message"=>"Schedule group does not exist: ".$schedule_group_id));
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
echo json_encode(array("status"=>0, "message"=>"Incorrect or non-numeric arguments given."));
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
?>
|
|
@ -1,6 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
require_once('../conf.php');
|
require_once('../conf.php');
|
||||||
require_once('DB.php');
|
|
||||||
require_once('../backend/Schedule.php');
|
require_once('../backend/Schedule.php');
|
||||||
|
|
||||||
$api_key = $_GET['api_key'];
|
$api_key = $_GET['api_key'];
|
||||||
|
@ -13,12 +12,6 @@ if(!in_array($api_key, $CC_CONFIG["apiKey"]))
|
||||||
|
|
||||||
PEAR::setErrorHandling(PEAR_ERROR_RETURN);
|
PEAR::setErrorHandling(PEAR_ERROR_RETURN);
|
||||||
|
|
||||||
$CC_DBC = DB::connect($CC_CONFIG['dsn'], TRUE);
|
|
||||||
if (PEAR::isError($CC_DBC)) {
|
|
||||||
echo "ERROR: ".$CC_DBC->getMessage()." ".$CC_DBC->getUserInfo()."\n";
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
$CC_DBC->setFetchMode(DB_FETCHMODE_ASSOC);
|
|
||||||
$from = $_GET["from"];
|
$from = $_GET["from"];
|
||||||
$to = $_GET["to"];
|
$to = $_GET["to"];
|
||||||
echo Schedule::ExportRangeAsJson($from, $to);
|
echo Schedule::ExportRangeAsJson($from, $to);
|
||||||
|
|
|
@ -10,6 +10,21 @@ class ScheduleGroup {
|
||||||
$this->groupId = $p_groupId;
|
$this->groupId = $p_groupId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if the schedule group exists in the DB.
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function exists() {
|
||||||
|
global $CC_CONFIG, $CC_DBC;
|
||||||
|
$sql = "SELECT COUNT(*) FROM ".$CC_CONFIG['scheduleTable']
|
||||||
|
." WHERE group_id=".$this->groupId;
|
||||||
|
$result = $CC_DBC->GetOne($sql);
|
||||||
|
if (PEAR::isError($result)) {
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
return $result != "0";
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a date to an ID by stripping out all characters
|
* Convert a date to an ID by stripping out all characters
|
||||||
* and padding with zeros.
|
* and padding with zeros.
|
||||||
|
@ -204,6 +219,22 @@ class ScheduleGroup {
|
||||||
// $sql = "UPDATE ".$CC_CONFIG["scheduleTable"]. " SET id=, starts=,ends="
|
// $sql = "UPDATE ".$CC_CONFIG["scheduleTable"]. " SET id=, starts=,ends="
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function notifyGroupStartPlay() {
|
||||||
|
global $CC_CONFIG, $CC_DBC;
|
||||||
|
$sql = "UPDATE ".$CC_CONFIG['scheduleTable']
|
||||||
|
." SET schedule_group_played=TRUE"
|
||||||
|
." WHERE group_id=".$this->groupId;
|
||||||
|
return $CC_DBC->query($sql);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function notifyMediaItemStartPlay($p_fileId) {
|
||||||
|
global $CC_CONFIG, $CC_DBC;
|
||||||
|
$sql = "UPDATE ".$CC_CONFIG['scheduleTable']
|
||||||
|
." SET media_item_played=TRUE"
|
||||||
|
." WHERE group_id=".$this->groupId
|
||||||
|
." AND file_id=".pg_escape_string($p_fileId);
|
||||||
|
return $CC_DBC->query($sql);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Schedule {
|
class Schedule {
|
||||||
|
@ -464,7 +495,7 @@ class Schedule {
|
||||||
$playlists[$pkey]['user_id'] = 0;
|
$playlists[$pkey]['user_id'] = 0;
|
||||||
$playlists[$pkey]['id'] = $dx["playlist_id"];
|
$playlists[$pkey]['id'] = $dx["playlist_id"];
|
||||||
$playlists[$pkey]['start'] = Schedule::CcTimeToPypoTime($dx["start"]);
|
$playlists[$pkey]['start'] = Schedule::CcTimeToPypoTime($dx["start"]);
|
||||||
$playlists[$pkey]['end'] = Schedule::CcTimeToPypoTime($dx["end"]);
|
$playlists[$pkey]['end'] = Schedule::CcTimeToPypoTime($dx["end"]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -244,6 +244,8 @@ CREATE TABLE "cc_schedule"
|
||||||
"fade_out" TIME default '00:00:00',
|
"fade_out" TIME default '00:00:00',
|
||||||
"cue_in" TIME default '00:00:00',
|
"cue_in" TIME default '00:00:00',
|
||||||
"cue_out" TIME default '00:00:00',
|
"cue_out" TIME default '00:00:00',
|
||||||
|
"schedule_group_played" BOOLEAN default 'f',
|
||||||
|
"media_item_played" BOOLEAN default 'f',
|
||||||
PRIMARY KEY ("id")
|
PRIMARY KEY ("id")
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -182,6 +182,8 @@
|
||||||
<column name="fade_out" phpName="FadeOut" type="TIME" required="false" defaultValue="00:00:00"/>
|
<column name="fade_out" phpName="FadeOut" type="TIME" required="false" defaultValue="00:00:00"/>
|
||||||
<column name="cue_in" phpName="CueIn" type="TIME" required="false" defaultValue="00:00:00"/>
|
<column name="cue_in" phpName="CueIn" type="TIME" required="false" defaultValue="00:00:00"/>
|
||||||
<column name="cue_out" phpName="CueOut" type="TIME" required="false" defaultValue="00:00:00"/>
|
<column name="cue_out" phpName="CueOut" type="TIME" required="false" defaultValue="00:00:00"/>
|
||||||
|
<column name="schedule_group_played" phpName="ScheduleGroupPlayed" type="BOOLEAN" required="false" defaultValue="0"/>
|
||||||
|
<column name="media_item_played" phpName="MediaItemPlayed" type="BOOLEAN" required="false" defaultValue="0"/>
|
||||||
</table>
|
</table>
|
||||||
<table name="cc_sess" phpName="CcSess">
|
<table name="cc_sess" phpName="CcSess">
|
||||||
<column name="sessid" phpName="Sessid" type="CHAR" size="32" primaryKey="true" required="true"/>
|
<column name="sessid" phpName="Sessid" type="CHAR" size="32" primaryKey="true" required="true"/>
|
||||||
|
|
|
@ -31,11 +31,26 @@ $pl = new Playlist();
|
||||||
$pl->create($playlistName);
|
$pl->create($playlistName);
|
||||||
|
|
||||||
// Add a media clip
|
// Add a media clip
|
||||||
$mediaFile = StoredFile::findByOriginalName("test10001.mp3");
|
$mediaFile = StoredFile::findByOriginalName("Manolo Camp - Morning Coffee.mp3");
|
||||||
if (is_null($mediaFile)) {
|
if (is_null($mediaFile)) {
|
||||||
echo "Adding test audio clip to the database.\n";
|
echo "Adding test audio clip to the database.\n";
|
||||||
$v = array("filepath" => __DIR__."/test10001.mp3");
|
$v = array("filepath" => __DIR__."/../../audio_samples/OpSound/Manolo Camp - Morning Coffee.mp3");
|
||||||
$mediaFile = StoredFile::Insert($v);
|
$mediaFile = StoredFile::Insert($v);
|
||||||
|
if (PEAR::isError($mediaFile)) {
|
||||||
|
var_dump($mediaFile);
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$pl->addAudioClip($mediaFile->getId());
|
||||||
|
$mediaFile = StoredFile::findByOriginalName("Peter Rudenko - Opening.mp3");
|
||||||
|
if (is_null($mediaFile)) {
|
||||||
|
echo "Adding test audio clip to the database.\n";
|
||||||
|
$v = array("filepath" => __DIR__."/../../audio_samples/OpSound/Peter Rudenko - Opening.mp3");
|
||||||
|
$mediaFile = StoredFile::Insert($v);
|
||||||
|
if (PEAR::isError($mediaFile)) {
|
||||||
|
var_dump($mediaFile);
|
||||||
|
exit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$pl->addAudioClip($mediaFile->getId());
|
$pl->addAudioClip($mediaFile->getId());
|
||||||
echo "done.\n";
|
echo "done.\n";
|
||||||
|
|
Loading…
Reference in New Issue