diff --git a/3rd_party/liquidsoap/liquidsoap b/3rd_party/liquidsoap/liquidsoap new file mode 100755 index 000000000..ba00712ff Binary files /dev/null and b/3rd_party/liquidsoap/liquidsoap differ diff --git a/3rd_party/pypo/obp/__init__.py b/3rd_party/pypo/api_clients/__init__.py similarity index 50% rename from 3rd_party/pypo/obp/__init__.py rename to 3rd_party/pypo/api_clients/__init__.py index 61a986ccd..e87a14276 100644 --- a/3rd_party/pypo/obp/__init__.py +++ b/3rd_party/pypo/api_clients/__init__.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- -from api_client import * \ No newline at end of file +__all__ = ["api_client"] diff --git a/3rd_party/pypo/api_clients/api_client.py b/3rd_party/pypo/api_clients/api_client.py new file mode 100644 index 000000000..eb948a4ce --- /dev/null +++ b/3rd_party/pypo/api_clients/api_client.py @@ -0,0 +1,355 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import sys +import time +import urllib +import logging +from util import json +import os + +def api_client_factory(config): + if config["api_client"] == "campcaster": + return CampcasterApiClient(config) + elif config["api_client"] == "obp": + return ObpApiClient(config) + else: + print 'API Client "'+config["api_client"]+'" not supported. Please check your config file.' + print + sys.exit() + +class ApiClientInterface: + + # This is optional. + # Should exit the program if this version of pypo is not compatible with + # 3rd party software. + def check_version(self): + nil + + # This is the main method you need to implement when creating a new API client. + def get_schedule(self): + return 0, [] + + # This is optional. + # You dont actually have to implement this function for the liquidsoap playout to work. + def update_scheduled_item(self, item_id, value): + nil + + # This is optional. + # 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 + + def generate_range_dp(self): + nil + + +class CampcasterApiClient(ApiClientInterface): + + def __init__(self, config): + self.config = config + #self.api_auth = api_auth + + def __get_campcaster_version(self): + logger = logging.getLogger("CampcasterApiClient.get_campcaster_version") + url = self.config["base_url"] + self.config["api_base"] + self.config["version_url"] + url = url.replace("%%api_key%%", self.config["api_key"]) + + try: + logger.debug("Trying to contact %s", url) + response = urllib.urlopen(url) + data = response.read() + response_json = json.read(data) + version = response_json['version'] + logger.debug("Campcaster Version %s detected", version) + except Exception, e: + try: + if e[1] == 401: + print '#####################################' + print '# YOUR API KEY SEEMS TO BE INVALID:' + print '# ' + self.config["api_key"] + print '#####################################' + sys.exit() + except Exception, e: + pass + + try: + if e[1] == 404: + print '#####################################' + print '# Unable to contact the OBP-API' + print '# ' + url + print '#####################################' + sys.exit() + except Exception, e: + pass + + version = 0 + logger.error("Unable to detect Campcaster Version - %s", e) + + return version + + def check_version(self): + version = self.__get_campcaster_version() + if (version == 0): + print 'Unable to get Campcaster version number.' + print + sys.exit() + elif (version[0:4] != "1.6."): + print 'Campcaster version: ' + str(version) + print 'pypo not compatible with this version of Campcaster.' + print + sys.exit() + else: + print 'Campcaster version: ' + str(version) + print 'pypo is compatible with this version of Campcaster.' + print + + def get_schedule(self): + logger = logging.getLogger("CampcasterApiClient.get_schedule") + + """ + calculate start/end time range (format: YYYY-DD-MM-hh-mm-ss,YYYY-DD-MM-hh-mm-ss) + (seconds are ignored, just here for consistency) + """ + tnow = time.localtime(time.time()) + tstart = time.localtime(time.time() - 3600 * int(self.config["cache_for"])) + tend = time.localtime(time.time() + 3600 * int(self.config["prepare_ahead"])) + + range = {} + range['start'] = "%04d-%02d-%02d-%02d-%02d" % (tstart[0], tstart[1], tstart[2], tstart[3], tstart[4]) + range['end'] = "%04d-%02d-%02d-%02d-%02d" % (tend[0], tend[1], tend[2], tend[3], tend[4]) + + # Construct the URL + export_url = self.config["base_url"] + self.config["api_base"] + self.config["export_url"] + + # Insert the start and end times into the URL + export_url = export_url.replace('%%api_key%%', self.config["api_key"]) + export_url = export_url.replace('%%from%%', range['start']) + export_url = export_url.replace('%%to%%', range['end']) + logger.info("export from %s", export_url) + + response = "" + status = 0 + try: + response_json = urllib.urlopen(export_url).read() + response = json.read(response_json) + logger.info("export status %s", response['check']) + status = response['check'] + except Exception, e: + print e + + return status, response + + def update_scheduled_item(self, item_id, value): + logger = logging.getLogger("CampcasterApiClient.update_scheduled_item") + + url = self.config["base_url"] + self.config["api_base"] + self.config["update_item_url"] + + try: + response = urllib.urlopen(url, self.api_auth) + response = json.read(response.read()) + logger.info("API-Status %s", response['status']) + logger.info("API-Message %s", response['message']) + + except Exception, e: + print e + api_status = False + logger.critical("Unable to connect - %s", e) + + return response + + + def update_start_playing(self, playlist_type, export_source, media_id, playlist_id, transmission_id): + return + logger = logging.getLogger("ApiClient.update_scheduled_item") + + url = self.api_url + 'schedule/update_start_playing.php' \ + + '?playlist_type=' + str(playlist_type) \ + + '&export_source=' + str(export_source) \ + + '&media_id=' + str(media_id) \ + + '&playlist_id=' + str(playlist_id) \ + + '&transmission_id=' + str(transmission_id) + + print url + + try: + response = urllib.urlopen(url, self.api_auth) + response = json.read(response.read()) + logger.info("API-Status %s", response['status']) + logger.info("API-Message %s", response['message']) + logger.info("TXT %s", response['str_dls']) + + except Exception, e: + print e + api_status = False + logger.critical("Unable to connect - %s", e) + + return response + + + def generate_range_dp(self): + logger = logging.getLogger("ApiClient.generate_range_dp") + + url = self.api_url + 'schedule/generate_range_dp.php' + + try: + response = urllib.urlopen(url, self.api_auth) + response = json.read(response.read()) + logger.debug("Trying to contact %s", url) + logger.info("API-Status %s", response['status']) + logger.info("API-Message %s", response['message']) + + except Exception, e: + print e + api_status = False + logger.critical("Unable to handle the request - %s", e) + + return response + + +################################################################################ + +OBP_MIN_VERSION = 2010100101 # required obp version + +class ObpApiClient(): + + def __init__(self, config): + self.config = config + #self.api_url = api_url + #self.api_auth = api_auth + + def check_version(self): + obp_version = self.get_obp_version() + + if obp_version == 0: + print '#################################################' + print 'Unable to get OBP version. Is OBP up and running?' + print '#################################################' + print + sys.exit() + elif obp_version < OBP_MIN_VERSION: + print 'OBP version: ' + str(obp_version) + print 'OBP min-version: ' + str(OBP_MIN_VERSION) + print 'pypo not compatible with this version of OBP' + print + sys.exit() + else: + print 'OBP API: ' + str(API_BASE) + print 'OBP version: ' + str(obp_version) + print 'OBP min-version: ' + str(OBP_MIN_VERSION) + print 'pypo is compatible with this version of OBP' + print + + def get_obp_version(self): + logger = logging.getLogger("ApiClient.get_obp_version") + # lookup OBP version + + url = self.api_url + 'api/pypo/status/json' + + try: + logger.debug("Trying to contact %s", url) + response = urllib.urlopen(url, self.api_auth) + response_json = json.read(response.read()) + obp_version = int(response_json['version']) + logger.debug("OBP Version %s detected", obp_version) + + except Exception, e: + try: + if e[1] == 401: + print '#####################################' + print '# YOUR API KEY SEEMS TO BE INVALID' + print '# ' + self.api_auth + print '#####################################' + sys.exit() + + except Exception, e: + pass + + try: + if e[1] == 404: + print '#####################################' + print '# Unable to contact the OBP-API' + print '# ' + url + print '#####################################' + sys.exit() + + except Exception, e: + pass + + obp_version = 0 + logger.error("Unable to detect OBP Version - %s", e) + + + return obp_version + + + def update_scheduled_item(self, item_id, value): + logger = logging.getLogger("ApiClient.update_shedueled_item") + # lookup OBP version + + url = self.api_url + 'api/pypo/update_scheduled_item/' + str(item_id) + '?played=' + str(value) + + try: + response = urllib.urlopen(url, self.api_auth) + response = json.read(response.read()) + logger.info("API-Status %s", response['status']) + logger.info("API-Message %s", response['message']) + + except Exception, e: + print e + api_status = False + logger.critical("Unable to connect to the OBP API - %s", e) + + + return response + + + def update_start_playing(self, playlist_type, export_source, media_id, playlist_id, transmission_id): + + logger = logging.getLogger("ApiClient.update_shedueled_item") + + url = self.api_url + 'api/pypo/update_start_playing/' \ + + '?playlist_type=' + str(playlist_type) \ + + '&export_source=' + str(export_source) \ + + '&export_source=' + str(export_source) \ + + '&media_id=' + str(media_id) \ + + '&playlist_id=' + str(playlist_id) \ + + '&transmission_id=' + str(transmission_id) + + print url + + try: + response = urllib.urlopen(url, self.api_auth) + response = json.read(response.read()) + logger.info("API-Status %s", response['status']) + logger.info("API-Message %s", response['message']) + logger.info("TXT %s", response['str_dls']) + + except Exception, e: + print e + api_status = False + logger.critical("Unable to connect to the OBP API - %s", e) + + + return response + + + def generate_range_dp(self): + logger = logging.getLogger("ApiClient.generate_range_dp") + + url = self.api_url + 'api/pypo/generate_range_dp/' + + try: + response = urllib.urlopen(url, self.api_auth) + response = json.read(response.read()) + logger.debug("Trying to contact %s", url) + logger.info("API-Status %s", response['status']) + logger.info("API-Message %s", response['message']) + + except Exception, e: + print e + api_status = False + logger.critical("Unable to handle the OBP API request - %s", e) + + + return response diff --git a/3rd_party/pypo/api_clients/api_client_factory.py b/3rd_party/pypo/api_clients/api_client_factory.py new file mode 100644 index 000000000..2bc97dc45 --- /dev/null +++ b/3rd_party/pypo/api_clients/api_client_factory.py @@ -0,0 +1,9 @@ +import campcaster_api_client +import obp_api_client + +def create_api_client(config): + if config["api_client"] == "campcaster": + return campcaster_api_client.CampcasterApiClient(config) + elif config["api_client"] == "obp": + return obp_api_client.ObpApiClient(config) + \ No newline at end of file diff --git a/3rd_party/pypo/api_clients/campcaster_api_client.py b/3rd_party/pypo/api_clients/campcaster_api_client.py new file mode 100755 index 000000000..b82b85990 --- /dev/null +++ b/3rd_party/pypo/api_clients/campcaster_api_client.py @@ -0,0 +1,136 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import sys +import time +import urllib +import logging +from util import json +import os + +class CampcasterApiClient(): + + def __init__(self, config): + self.config = config + #self.api_auth = api_auth + + def check_version(self): + version = self.get_campcaster_version() + if (version == 0): + print 'Unable to get Campcaster version number.' + print + sys.exit() + elif (version[0:4] != "1.6."): + print 'Campcaster version: ' + str(version) + print 'pypo not compatible with this version of Campcaster' + print + sys.exit() + else: + print 'Campcaster version: ' + str(version) + print 'pypo is compatible with this version of OBP' + print + + def get_campcaster_version(self): + logger = logging.getLogger("ApiClient.get_campcaster_version") + url = self.config["base_url"] + self.config["api_base"] + self.config["version_url"] + url = url.replace("%%api_key%%", self.config["api_key"]) + + try: + logger.debug("Trying to contact %s", url) + response = urllib.urlopen(url) + data = response.read() + response_json = json.read(data) + version = response_json['version'] + logger.debug("Campcaster Version %s detected", version) + except Exception, e: + try: + if e[1] == 401: + print '#####################################' + print '# YOUR API KEY SEEMS TO BE INVALID:' + print '# ' + self.config["api_key"] + print '#####################################' + sys.exit() + except Exception, e: + pass + + try: + if e[1] == 404: + print '#####################################' + print '# Unable to contact the OBP-API' + print '# ' + url + print '#####################################' + sys.exit() + except Exception, e: + pass + + version = 0 + logger.error("Unable to detect Campcaster Version - %s", e) + + return version + + + def update_scheduled_item(self, item_id, value): + logger = logging.getLogger("ApiClient.update_scheduled_item") + url = self.api_url + 'schedule/schedule.php?item_id=' + str(item_id) + '&played=' + str(value) + + try: + response = urllib.urlopen(url, self.api_auth) + response = json.read(response.read()) + logger.info("API-Status %s", response['status']) + logger.info("API-Message %s", response['message']) + + except Exception, e: + print e + api_status = False + logger.critical("Unable to connect - %s", e) + + return response + + + def update_start_playing(self, playlist_type, export_source, media_id, playlist_id, transmission_id): + logger = logging.getLogger("ApiClient.update_scheduled_item") + + url = self.api_url + 'schedule/update_start_playing.php' \ + + '?playlist_type=' + str(playlist_type) \ + + '&export_source=' + str(export_source) \ + + '&export_source=' + str(export_source) \ + + '&media_id=' + str(media_id) \ + + '&playlist_id=' + str(playlist_id) \ + + '&transmission_id=' + str(transmission_id) + + print url + + try: + response = urllib.urlopen(url, self.api_auth) + response = json.read(response.read()) + logger.info("API-Status %s", response['status']) + logger.info("API-Message %s", response['message']) + logger.info("TXT %s", response['str_dls']) + + except Exception, e: + print e + api_status = False + logger.critical("Unable to connect - %s", e) + + return response + + + def generate_range_dp(self): + logger = logging.getLogger("ApiClient.generate_range_dp") + + url = self.api_url + 'schedule/generate_range_dp.php' + + try: + response = urllib.urlopen(url, self.api_auth) + response = json.read(response.read()) + logger.debug("Trying to contact %s", url) + logger.info("API-Status %s", response['status']) + logger.info("API-Message %s", response['message']) + + except Exception, e: + print e + api_status = False + logger.critical("Unable to handle the request - %s", e) + + return response + \ No newline at end of file diff --git a/3rd_party/pypo/obp/api_client.py b/3rd_party/pypo/api_clients/obp_api_client.py similarity index 74% rename from 3rd_party/pypo/obp/api_client.py rename to 3rd_party/pypo/api_clients/obp_api_client.py index 9bb5dc6b4..453a49007 100755 --- a/3rd_party/pypo/obp/api_client.py +++ b/3rd_party/pypo/api_clients/obp_api_client.py @@ -6,31 +6,52 @@ import sys import time import urllib - import logging - from util import json - import os - +OBP_MIN_VERSION = 2010100101 # required obp version -class ApiClient(): +class ObpApiClient(): - def __init__(self, api_url, api_auth): - self.api_url = api_url - self.api_auth = api_auth + def __init__(self, config): + self.config = config + #self.api_url = api_url + #self.api_auth = api_auth + def check_version(self): + obp_version = self.get_obp_version() + + if obp_version == 0: + print '#################################################' + print 'Unable to get OBP version. Is OBP up and running?' + print '#################################################' + print + sys.exit() + + elif obp_version < OBP_MIN_VERSION: + print 'OBP version: ' + str(obp_version) + print 'OBP min-version: ' + str(OBP_MIN_VERSION) + print 'pypo not compatible with this version of OBP' + print + sys.exit() + + else: + print 'OBP API: ' + str(API_BASE) + print 'OBP version: ' + str(obp_version) + print 'OBP min-version: ' + str(OBP_MIN_VERSION) + print 'pypo is compatible with this version of OBP' + print + + def get_obp_version(self): logger = logging.getLogger("ApiClient.get_obp_version") # lookup OBP version url = self.api_url + 'api/pypo/status/json' - try: - + try: logger.debug("Trying to contact %s", url) - response = urllib.urlopen(url, self.api_auth) response_json = json.read(response.read()) obp_version = int(response_json['version']) @@ -67,11 +88,11 @@ class ApiClient(): return obp_version - def update_shedueled_item(self, item_id, value): + def update_scheduled_item(self, item_id, value): logger = logging.getLogger("ApiClient.update_shedueled_item") # lookup OBP version - url = self.api_url + 'api/pypo/update_shedueled_item/' + str(item_id) + '?played=' + str(value) + url = self.api_url + 'api/pypo/update_scheduled_item/' + str(item_id) + '?played=' + str(value) try: response = urllib.urlopen(url, self.api_auth) diff --git a/3rd_party/pypo/config.cfg b/3rd_party/pypo/config.cfg index c3353b71d..61630fde2 100644 --- a/3rd_party/pypo/config.cfg +++ b/3rd_party/pypo/config.cfg @@ -2,29 +2,63 @@ # pypo - configuration # ############################################ +# Set the type of client you are using. +# Currently supported types: +# 1) "obp" = Open Broadcast Platform +# 2) "campcaster" +# +api_client = "campcaster" + ############################################ # Directories / Hosts # # _include_ trailing slash !! # ############################################ -cache_dir = '/storage/pypo/cache/' -file_dir = '/storage/pypo/files/' -tmp_dir = '/var/tmp/obp/' +cache_dir = '/opt/pypo/cache/' +schedule_dir = '/opt/pypo/cache/schedule' +file_dir = '/opt/pypo/files/' +tmp_dir = '/tmp/pypo/' ############################################ # API path & co # ############################################ -base_url = 'http://vdeb.openbroadcast.ch/' -obp_api_key = 'AAA-BBB-CCC-EEE' +# Value needed to access the API +api_key = 'AAA' -# stage config -#base_url = 'http://stage.openbroadcast.ch/' -#obp_api_key = 'EMMKM-PMXWV-NIGOA-KHGWPP +# Hostname +base_url = 'http://localhost/' + +##################### +# Campcaster Config # +##################### +# Path to the base of the API +api_base = 'campcaster/' + +# URL to get the version number of the API +version_url = 'schedule/api_version.php?api_key=%%api_key%%' + +# Schedule export path. +# YYYY-MM-DD-hh-mm will be substituted for the tokens %%from%% and %%to%% +export_url = 'schedule/schedule.php?from=%%from%%&to=%%to%%&api_key=%%api_key%%' + +update_item_url = 'schedule/schedule.php?item_id=%%item_id%%&played=%%played%%' + +update_start_playing_url = 'schedule/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 = 'schedule/generate_range_dp.php' + + +############## +# OBP config # +############## +#base_url = 'http://localhost/' +#api_base = BASE_URL +#version_url = api_base + 'api/pypo/status/json' +#update_item_url = api_base + 'api/pypo/update_shedueled_item/$$item_id%%?played=%%played%%' # prod config -#base_url = 'http://openbroadcast.ch/' -#obp_api_key = 'XWQWP-XIHJU-ZHENT-NGSAW' +#base_url = '' +#api_key = '' -export_path = 'api/pypo/export_range/' # YYYY-MM-DD-hh-mm will be added in script, exports json ############################################ # Liquidsoap settings # @@ -41,7 +75,7 @@ cache_for = 24 #how long to hold the cache, in hours poll_interval = 10 # in seconds push_interval = 1 # in seconds -# 'pre' or 'otf'. 'pre' cues while pplaylist preparation +# 'pre' or 'otf'. 'pre' cues while playlist preparation # while 'otf' (on the fly) cues while loading into ls # (needs the post_processor patch) cue_style = 'pre' diff --git a/3rd_party/pypo/logging.cfg b/3rd_party/pypo/logging.cfg index 54a958296..da0800dd1 100644 --- a/3rd_party/pypo/logging.cfg +++ b/3rd_party/pypo/logging.cfg @@ -21,7 +21,7 @@ propagate=0 [handler_consoleHandler] class=StreamHandler -level=ERROR +level=DEBUG formatter=simpleFormatter args=(sys.stdout,) @@ -29,13 +29,13 @@ args=(sys.stdout,) class=FileHandler level=WARNING formatter=simpleFormatter -args=("/var/log/obp/pypo/error.log",) +args=("./error.log",) [handler_fileHandlerDEBUG] class=FileHandler level=DEBUG formatter=simpleFormatter -args=("/var/log/obp/pypo/debug.log",) +args=("./debug.log",) [handler_nullHandler] class=FileHandler @@ -44,8 +44,6 @@ formatter=simpleFormatter args=("/tmp/sessionlog_null.log",) - - [formatter_simpleFormatter] format=%(asctime)s %(levelname)s - [%(name)s] - %(message)s datefmt= diff --git a/3rd_party/pypo/push.py b/3rd_party/pypo/push.py index e222b6c0d..50cde484b 100755 --- a/3rd_party/pypo/push.py +++ b/3rd_party/pypo/push.py @@ -52,8 +52,6 @@ from obp import * PYPO_VERSION = '0.1' -OBP_MIN_VERSION = 2010100101 # required obp version - #set up command-line options parser = OptionParser() @@ -84,13 +82,9 @@ try: FILE_DIR = config['file_dir'] TMP_DIR = config['tmp_dir'] BASE_URL = config['base_url'] - OBP_API_BASE = BASE_URL + 'mod/medialibrary/' - EXPORT_URL = OBP_API_BASE + config['export_path'] + API_BASE = config['api_base'] EXPORT_SOURCE = config['export_source'] - - OBP_STATUS_URL = OBP_API_BASE + 'status/version/json' - OBP_API_KEY = config['obp_api_key'] - + OBP_API_KEY = config['api_key'] POLL_INTERVAL = float(config['poll_interval']) PUSH_INTERVAL = float(config['push_interval']) LS_HOST = config['ls_host'] @@ -106,9 +100,6 @@ except Exception, e: #TIME = time.localtime(time.time()) TIME = (2010, 6, 26, 15, 33, 23, 2, 322, 0) - - - class Global: def __init__(self): @@ -117,33 +108,9 @@ class Global: def selfcheck(self): - self.api_auth = urllib.urlencode({'api_key': OBP_API_KEY}) - self.api_client = ApiClient(OBP_API_BASE, self.api_auth) - - obp_version = self.api_client.get_obp_version() - - - if obp_version == 0: - print '#################################################' - print 'Unable to get OBP version. Is OBP up and running?' - print '#################################################' - print - sys.exit() - - elif obp_version < OBP_MIN_VERSION: - print 'OBP version: ' + str(obp_version) - print 'OBP min-version: ' + str(OBP_MIN_VERSION) - print 'pypo not compatible with this version of OBP' - print - sys.exit() - - else: - print 'OBP API: ' + str(OBP_API_BASE) - print 'OBP version: ' + str(obp_version) - print 'OBP min-version: ' + str(OBP_MIN_VERSION) - print 'pypo is compatible with this version of OBP' - print - + self.api_auth = urllib.urlencode({'api_key': API_KEY}) + self.api_client = ApiClient(API_BASE, self.api_auth) + self.api_client.check_version() """ Uncomment the following lines to let pypo check if @@ -165,42 +132,32 @@ class Playout: self.cache_dir = CACHE_DIR self.file_dir = FILE_DIR self.tmp_dir = TMP_DIR - self.export_url = EXPORT_URL self.export_source = EXPORT_SOURCE - self.api_auth = urllib.urlencode({'api_key': OBP_API_KEY}) - self.api_client = ApiClient(OBP_API_BASE, self.api_auth) + self.api_auth = urllib.urlencode({'api_key': API_KEY}) + self.api_client = ApiClient(API_BASE, self.api_auth) self.cue_file = CueFile() self.schedule_file = CACHE_DIR + 'schedule' # set initial state self.range_updated = False - - def push_liquidsoap(self,options): logger = logging.getLogger("push_liquidsoap") - print options - #pkey = '2010-10-26-21-00-00' - pkey = options - src = self.cache_dir + str(pkey) + '/list.lsp' - print src - - +s if True == os.access(src, os.R_OK): print 'OK - Can read' pl_file = open(src, "r") - """ i know this could be wrapped, maybe later.. """ @@ -209,30 +166,21 @@ class Playout: for line in pl_file.readlines(): print line.strip() - #tn.write('q.push ' + pl_entry) #tn.write("\n") - tn.write('scheduler.push %s' % (line.strip())) tn.write("\n") - - tn.write("scheduler_q0.queue \n") - tn.write("scheduler_q1.queue \n") #time.sleep(2) - #print tn.read_all() print 'sending "flip"' tn.write('scheduler.flip') tn.write("\n") - - - #tn.write("live_in.stop\n") #tn.write("stream_disable\n") @@ -263,9 +211,7 @@ class Playout: tn.write("exit\n") - print tn.read_all() - status = 1 sys.exit() diff --git a/3rd_party/pypo/pypo_cli.py b/3rd_party/pypo/pypo_cli.py index 19b2dd95a..f5996e107 100755 --- a/3rd_party/pypo/pypo_cli.py +++ b/3rd_party/pypo/pypo_cli.py @@ -6,7 +6,7 @@ """ Python part of radio playout (pypo) -The main functionas are "fetch" (./pypo_cli.py -f) and "push" (./pypo_cli.py -p) +The main functions are "fetch" (./pypo_cli.py -f) and "push" (./pypo_cli.py -p) Also check out the php counterpart that handles the api requests: https://lab.digris.ch/svn/elgg/trunk/unstable/mod/medialibrary/application/controllers/api/pypo.php @@ -20,7 +20,7 @@ Attention & ToDos made for python version 2.5!! should work with 2.6 as well with a bit of adaption. for sure the json parsing has to be changed -(2.6 has an parser, pypo brigs it's own -> util/json.py) +(2.6 has an parser, pypo brings it's own -> util/json.py) """ # python defaults (debian default) @@ -41,36 +41,35 @@ import telnetlib import random import string import operator +import inspect # additional modules (should be checked) from configobj import ConfigObj # custom imports from util import * -from obp import * +from api_clients import * +PYPO_VERSION = '0.2' - -PYPO_VERSION = '0.1' -OBP_MIN_VERSION = 2010100101 # required obp version - - -#set up command-line options +# Set up command-line options parser = OptionParser() # help screeen / info usage = "%prog [options]" + " - python playout system" parser = OptionParser(usage=usage) -#options +# Options +parser.add_option("-v", "--compat", help="Check compatibility with server API version", default=False, action="store_true", dest="check_compat") + 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("-p", "--push-scheduler", help="Push scheduler to Liquidsoap (loop, interval in config file)", 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("-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="Faeili Butzae aka cleanup", default=False, action="store_true", dest="cleanup") -parser.add_option("-j", "--jingles", help="Get new jungles from obp, comma separated list if jingle-id's as argument", metavar="LIST") +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("-c", "--check", help="Check the cached schedule and exit", default=False, action="store_true", dest="check") # parse options @@ -85,66 +84,37 @@ try: CACHE_DIR = config['cache_dir'] FILE_DIR = config['file_dir'] TMP_DIR = config['tmp_dir'] - BASE_URL = config['base_url'] - OBP_API_BASE = BASE_URL + 'mod/medialibrary/' - EXPORT_URL = OBP_API_BASE + config['export_path'] - - OBP_STATUS_URL = OBP_API_BASE + 'status/version/json' - OBP_API_KEY = config['obp_api_key'] - + API_BASE = config['api_base'] + API_KEY = config['api_key'] POLL_INTERVAL = float(config['poll_interval']) PUSH_INTERVAL = float(config['push_interval']) LS_HOST = config['ls_host'] LS_PORT = config['ls_port'] - PREPARE_AHEAD = config['prepare_ahead'] + #PREPARE_AHEAD = config['prepare_ahead'] CACHE_FOR = config['cache_for'] CUE_STYLE = config['cue_style'] - + #print config except Exception, e: - print 'error: ', e + print 'Error loading config file: ', e sys.exit() #TIME = time.localtime(time.time()) TIME = (2010, 6, 26, 15, 33, 23, 2, 322, 0) - - - +# to help with debugging - get the current line number +def lineno(): + """Returns the current function name and line number in our program.""" + return "File " +inspect.currentframe().f_code.co_filename + " / Line " + str(inspect.currentframe().f_back.f_lineno) + ": " class Global: def __init__(self): #print '# global initialisation' print - def selfcheck(self): - - self.api_auth = urllib.urlencode({'api_key': OBP_API_KEY}) - self.api_client = ApiClient(OBP_API_BASE, self.api_auth) - - obp_version = self.api_client.get_obp_version() - - - if obp_version == 0: - print '#################################################' - print 'Unable to get OBP version. Is OBP up and running?' - print '#################################################' - print - sys.exit() - - elif obp_version < OBP_MIN_VERSION: - print 'OBP version: ' + str(obp_version) - print 'OBP min-version: ' + str(OBP_MIN_VERSION) - print 'pypo not compatible with this version of OBP' - print - sys.exit() - - else: - print 'OBP API: ' + str(OBP_API_BASE) - print 'OBP version: ' + str(obp_version) - print 'OBP min-version: ' + str(OBP_MIN_VERSION) - print 'pypo is compatible with this version of OBP' - print - + def selfcheck(self): + self.api_auth = urllib.urlencode({'api_key': API_KEY}) + self.api_client = api_client.api_client_factory(config) + self.api_client.check_version() """ Uncomment the following lines to let pypo check if @@ -153,8 +123,7 @@ class Global: # while self.status.check_ls(LS_HOST, LS_PORT) == 0: # print 'Unable to connect to liquidsoap. Is it up and running?' # time.sleep(2) - - + """ @@ -162,39 +131,31 @@ class Global: class Playout: def __init__(self): #print '# init fallback' - self.file_dir = FILE_DIR self.tmp_dir = TMP_DIR - self.export_url = EXPORT_URL - self.api_auth = urllib.urlencode({'api_key': OBP_API_KEY}) - self.api_client = ApiClient(OBP_API_BASE, self.api_auth) + self.api_auth = urllib.urlencode({'api_key': API_KEY}) + self.api_client = api_client.api_client_factory(config) self.cue_file = CueFile() - - # set initial state self.range_updated = False - - - """ Fetching part of pypo - Reads the scheduled entries of a given range (actual time +/- "prepare_ahead" / "cache_for") - Saves a serialized file of the schedule - - playlists are prepared. (brought to ls format) and, if not mounted via nsf, files are copied + - playlists are prepared. (brought to liquidsoap format) and, if not mounted via nsf, files are copied to the cache dir (Folder-structure: cache/YYYY-MM-DD-hh-mm-ss) - runs the cleanup routine, to get rid of unused cashed files """ def fetch(self, export_source): """ - wrapper script for fetchin whole shedule (in json) + wrapper script for fetching the whole schedule (in json) """ logger = logging.getLogger("fetch") - self.export_source = export_source self.cache_dir = CACHE_DIR + self.export_source + '/' self.schedule_file = self.cache_dir + 'schedule' @@ -215,34 +176,30 @@ class Playout: try: self.generate_range_dp() except Exception, e: - logger.error("%s", e) + logger.error(lineno() + "%s", e) - - # get shedule + # get schedule try: - while self.get_schedule(self.export_source) != 1: + while self.get_schedule() != 1: logger.warning("failed to read from export url") time.sleep(1) - except Exception, e: logger.error("%s", e) + except Exception, e: logger.error(lineno() +"%s", e) # prepare the playlists if CUE_STYLE == 'pre': try: self.prepare_playlists_cue(self.export_source) - except Exception, e: logger.error("%s", e) + except Exception, e: logger.error(lineno() + "%s", e) elif CUE_STYLE == 'otf': try: self.prepare_playlists(self.export_source) - except Exception, e: logger.error("%s", e) + except Exception, e: logger.error(lineno() + "%s", e) # cleanup try: self.cleanup(self.export_source) - except Exception, e: logger.error("%s", e) + except Exception, e: logger.error(lineno() + "%s", e) logger.info("fetch loop completed") - - - """ This is actually a bit ugly (again feel free to improve!!) @@ -250,9 +207,7 @@ class Playout: we do this at 18h. The hour before the state is set back to 'False' """ def generate_range_dp(self): - logger = logging.getLogger("generate_range_dp") - logger.debug("trying to trigger daypart update") tnow = time.localtime(time.time()) @@ -261,7 +216,6 @@ class Playout: self.range_updated = False if(tnow[3] == 17 and self.range_updated == False): - try: print self.api_client.generate_range_dp() logger.info("daypart updated") @@ -269,61 +223,25 @@ class Playout: except Exception, e: print e - - def get_schedule(self, export_source): - - logger = logging.getLogger("fetch.get_schedule") - - """ - calculate start/end time range (format: YYYY-DD-MM-hh-mm-ss,YYYY-DD-MM-hh-mm-ss) - (seconds are ignored, just here for consistency) - """ - - - self.export_source = export_source - - tnow = time.localtime(time.time()) - tstart = time.localtime(time.time() - 3600 * int(CACHE_FOR)) - tend = time.localtime(time.time() + 3600 * int(PREPARE_AHEAD)) - - range = {} - range['start'] = "%04d-%02d-%02d-%02d-%02d" % (tstart[0], tstart[1], tstart[2], tstart[3], tstart[4]) - range['end'] = "%04d-%02d-%02d-%02d-%02d" % (tend[0], tend[1], tend[2], tend[3], tend[4]) - - - export_url = self.export_url + range['start'] + ',' + range['end'] + '/' + self.export_source - logger.info("export from %s", export_url) - - try: - response_json = urllib.urlopen(export_url, self.api_auth).read() - response = json.read(response_json) - logger.info("export status %s", response['check']) - status = response['check'] - schedule = response['playlists'] - - except Exception, e: - print e - status = 0 - + def get_schedule(self): + logger = logging.getLogger("Playout.get_schedule") + status, response = self.api_client.get_schedule(); + if status == 1: - - logger.info("dump serialized shedule to %s", self.schedule_file) - + logger.info("dump serialized schedule to %s", self.schedule_file) + schedule = response['playlists'] try: schedule_file = open(self.schedule_file, "w") pickle.dump(schedule, schedule_file) schedule_file.close() except Exception, e: - print e + print lineno() + e status = 0 return status - - - """ @@ -674,13 +592,12 @@ class Playout: """ The counterpart - the push loop periodically (minimal 1/2 of the playlist-grid) - checks if there is a playlist that should be sheduled at the current time. + checks if there is a playlist that should be scheduled at the current time. If yes, the temporary liquidsoap playlist gets replaced with the corresponding one, - then liquid is asked (via telnet) to reload and immediately play it + then liquidsoap is asked (via telnet) to reload and immediately play it. """ def push(self, export_source): logger = logging.getLogger("push") - self.export_source = export_source self.cache_dir = CACHE_DIR + self.export_source + '/' @@ -710,12 +627,10 @@ class Playout: 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]) - print '--' print str_tnow_s + ' now' print str_tcomming_s + ' comming' - playnow = None if self.schedule == None: @@ -731,19 +646,15 @@ class Playout: playlist = self.schedule[pkey] if int(playlist['played']) != 1: - print '!!!!!!!!!!!!!!!!!!!' print 'MATCH' - """ 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'] try: @@ -757,17 +668,15 @@ class Playout: transmission_id = 0 print e - print 'Playlist id:', - if(self.push_liquidsoap(pkey, ptype, user_id, playlist_id, transmission_id, self.push_ahead) == 1): self.schedule[pkey]['played'] = 1 """ Call api to update schedule states and write changes back to cache file """ - self.api_client.update_shedueled_item(int(playlist['schedule_id']), 1) + self.api_client.update_scheduled_item(int(playlist['schedule_id']), 1) schedule_file = open(self.schedule_file, "w") pickle.dump(self.schedule, schedule_file) schedule_file.close() @@ -779,7 +688,6 @@ class Playout: def push_init(self, export_source): - logger = logging.getLogger("push_init") self.export_source = export_source @@ -800,7 +708,6 @@ class Playout: return schedule - def push_liquidsoap(self, pkey, ptype, user_id, playlist_id, transmission_id, push_ahead): logger = logging.getLogger("push_liquidsoap") @@ -841,17 +748,9 @@ class Playout: tn.write("exit\n") print tn.read_all() - - - - - - - print 'sleeping for %s s' % (self.push_ahead) time.sleep(self.push_ahead) - print 'sending "flip"' tn = telnetlib.Telnet(LS_HOST, 1234) @@ -868,7 +767,6 @@ class Playout: tn.write("vars.transmission_id %s\n" % transmission_id) tn.write("vars.playlist_type %s\n" % ptype) - # if(int(ptype) < 5): # tn.write(self.export_source + '.flip') # tn.write("\n") @@ -885,7 +783,6 @@ class Playout: tn.write("live_in.stop") tn.write("\n") - tn.write("exit\n") print tn.read_all() @@ -899,7 +796,6 @@ class Playout: def push_liquidsoap_legacy(self, pkey, ptype, p_id, user_id): logger = logging.getLogger("push_liquidsoap") - logger.debug('trying to push %s to liquidsoap', pkey) self.export_source = export_source @@ -957,9 +853,6 @@ class Playout: """ tn.write("pl.pl_id '%s'\n" % p_id) tn.write("pl.user_id '%s'\n" % user_id) - - - tn.write("exit\n") print tn.read_all() @@ -976,7 +869,7 @@ class Playout: """ - Updates the jinles. Give comma separated list of jingle tracks + Updates the jingles. Give comma separated list of jingle tracks. """ def update_jingles(self, options): print 'jingles' @@ -985,7 +878,7 @@ class Playout: print jingle_list for media_id in jingle_list: # api path maybe should not be hard-coded - src = OBP_API_BASE + 'api/pypo/get_media/' + str(media_id) + src = API_BASE + 'api/pypo/get_media/' + str(media_id) print src # include the hourly jungles for the moment dst = "%s%s/%s.mp3" % (self.file_dir, 'jingles/hourly', str(media_id)) @@ -1001,9 +894,6 @@ class Playout: print e logger.error("%s", e) - - - def check_schedule(self, export_source): logger = logging.getLogger("check_schedule") @@ -1021,8 +911,6 @@ class Playout: logger.error("%s", e) schedule = None - - #for pkey in schedule: for pkey in sorted(schedule.iterkeys()): @@ -1042,18 +930,17 @@ class Playout: for media in playlist['medias']: print media - print - if __name__ == '__main__': print - print '#########################################' - print '# *** pypo *** #' - print '# obp python playout #' - print '#########################################' + print '###########################################' + print '# *** pypo *** #' + print '# Liquidsoap + External Scheduler #' + print '# Playout System #' + print '###########################################' print # initialize @@ -1141,5 +1028,5 @@ while run == True: print e sys.exit() - + sys.exit() diff --git a/3rd_party/pypo/pypo_dls.py b/3rd_party/pypo/pypo_dls.py index 8e200d24b..6ed030ea3 100755 --- a/3rd_party/pypo/pypo_dls.py +++ b/3rd_party/pypo/pypo_dls.py @@ -10,8 +10,8 @@ This function acts as a gateway between liquidsoap and the obp-api. Mainliy used to tell the plattform what pypo/LS does. Main case: - - 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 + - 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 with the currently starting filename as parameter - 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 @@ -42,11 +42,7 @@ from configobj import ConfigObj from util import * from obp import * - - PYPO_VERSION = '0.9' -OBP_MIN_VERSION = 2010040501 # required obp version - #set up command-line options parser = OptionParser() @@ -69,11 +65,9 @@ try: config = ConfigObj('config.cfg') TMP_DIR = config['tmp_dir'] BASE_URL = config['base_url'] - OBP_API_BASE = BASE_URL + 'mod/medialibrary/' + API_BASE = BASE_URL + 'mod/medialibrary/' EXPORT_SOURCE = config['export_source'] - - OBP_STATUS_URL = OBP_API_BASE + 'status/version/json' - OBP_API_KEY = config['obp_api_key'] + API_KEY = config['api_key'] except Exception, e: print 'error: ', e @@ -86,31 +80,9 @@ class Global: def selfcheck(self): - self.api_auth = urllib.urlencode({'api_key': OBP_API_KEY}) - self.api_client = ApiClient(OBP_API_BASE, self.api_auth) - - obp_version = self.api_client.get_obp_version() - - if obp_version == 0: - print '#################################################' - print 'Unable to get OBP version. Is OBP up and running?' - print '#################################################' - print - sys.exit() - - elif obp_version < OBP_MIN_VERSION: - print 'OBP version: ' + str(obp_version) - print 'OBP min-version: ' + str(OBP_MIN_VERSION) - print 'pypo not compatible with this version of OBP' - print - sys.exit() - - else: - print 'OBP API: ' + str(OBP_API_BASE) - print 'OBP version: ' + str(obp_version) - print 'OBP min-version: ' + str(OBP_MIN_VERSION) - print 'pypo is compatible with this version of OBP' - print + self.api_auth = urllib.urlencode({'api_key': API_KEY}) + self.api_client = api_client.api_client_factory(config) + self.api_client.check_version() class Notify: def __init__(self): @@ -118,8 +90,8 @@ class Notify: self.tmp_dir = TMP_DIR self.export_source = EXPORT_SOURCE - self.api_auth = urllib.urlencode({'api_key': OBP_API_KEY}) - self.api_client = ApiClient(OBP_API_BASE, self.api_auth) + self.api_auth = urllib.urlencode({'api_key': API_KEY}) + self.api_client = api_client.api_client_factory(config) def start_playing(self, options): @@ -127,7 +99,6 @@ class Notify: tnow = time.localtime(time.time()) - path = options try: @@ -151,17 +122,10 @@ class Notify: print "Media ID: ", print id - - # self.api_client.update_start_playing(id, self.export_source, path) - txt = "test this update" - - - + # Echo client program - - HOST = '172.16.16.128' # The remote host PORT = 50008 # The same port as used by the server s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) @@ -200,12 +164,7 @@ class Notify: if data == "session": print 'KKK' - time.sleep(0.1) - - - - print 'DONE' @@ -237,7 +196,4 @@ while run == True: print e sys.exit() - - - sys.exit() diff --git a/3rd_party/pypo/pypo_notify.py b/3rd_party/pypo/pypo_notify.py index 70f1aeae9..a50f622a9 100755 --- a/3rd_party/pypo/pypo_notify.py +++ b/3rd_party/pypo/pypo_notify.py @@ -41,27 +41,20 @@ from util import * from obp import * from dls import * - - PYPO_VERSION = '0.9' -OBP_MIN_VERSION = 2010040501 # required obp version -#set up command-line options +# Set up command-line options parser = OptionParser() # help screeen / info usage = "%prog [options]" + " - notification gateway" 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("-p", "--playing", help="Tell daddy 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("-M", "--media-id", help="Tell daddy what is playing right now", metavar="media_id") parser.add_option("-U", "--user-id", help="Tell daddy what is playing right now", metavar="user_id") parser.add_option("-P", "--playlist-id", help="Tell daddy what is playing right now", metavar="playlist_id") @@ -79,10 +72,8 @@ try: config = ConfigObj('config.cfg') TMP_DIR = config['tmp_dir'] BASE_URL = config['base_url'] - OBP_API_BASE = BASE_URL + 'mod/medialibrary/' - - OBP_STATUS_URL = OBP_API_BASE + 'status/version/json' - OBP_API_KEY = config['obp_api_key'] + API_BASE = BASE_URL + 'mod/medialibrary/' + API_KEY = config['api_key'] except Exception, e: print 'error: ', e @@ -95,54 +86,24 @@ class Global: def selfcheck(self): - self.api_auth = urllib.urlencode({'api_key': OBP_API_KEY}) - self.api_client = ApiClient(OBP_API_BASE, self.api_auth) + self.api_auth = urllib.urlencode({'api_key': API_KEY}) + self.api_client = api_client.api_client_factory(config) + self.api_client.check_version() - obp_version = self.api_client.get_obp_version() - - if obp_version == 0: - print '#################################################' - print 'Unable to get OBP version. Is OBP up and running?' - print '#################################################' - print - sys.exit() - - elif obp_version < OBP_MIN_VERSION: - print 'OBP version: ' + str(obp_version) - print 'OBP min-version: ' + str(OBP_MIN_VERSION) - print 'pypo not compatible with this version of OBP' - print - sys.exit() - - else: - print 'OBP API: ' + str(OBP_API_BASE) - print 'OBP version: ' + str(obp_version) - print 'OBP min-version: ' + str(OBP_MIN_VERSION) - print 'pypo is compatible with this version of OBP' - print - class Notify: def __init__(self): - - self.tmp_dir = TMP_DIR - - self.api_auth = urllib.urlencode({'api_key': OBP_API_KEY}) - self.api_client = ApiClient(OBP_API_BASE, self.api_auth) - + self.tmp_dir = TMP_DIR + self.api_auth = urllib.urlencode({'api_key': API_KEY}) + self.api_client = api_client.api_client_factory(config) self.dls_client = DlsClient('127.0.0.128', 50008, 'myusername', 'mypass') - - def start_playing(self, options): logger = logging.getLogger("start_playing") - tnow = time.localtime(time.time()) #print options - - print '#################################################' print '# calling obp to tell about what\'s playing #' print '#################################################' @@ -170,23 +131,13 @@ class Notify: 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_legacy(self, options): logger = logging.getLogger("start_playing") - tnow = time.localtime(time.time()) - print '#################################################' print '# calling obp to tell about what\'s playing #' @@ -248,10 +199,6 @@ class Notify: except Exception, e: print e - - - - if __name__ == '__main__': @@ -270,7 +217,6 @@ if __name__ == '__main__': run = True while run == True: - logger = logging.getLogger("pypo notify") if options.playing: @@ -278,8 +224,5 @@ while run == True: except Exception, e: print e sys.exit() - - - sys.exit() diff --git a/3rd_party/pypo/scripts/silence.mp3 b/3rd_party/pypo/scripts/silence.mp3 new file mode 100644 index 000000000..bb955c331 Binary files /dev/null and b/3rd_party/pypo/scripts/silence.mp3 differ diff --git a/backend/Schedule.php b/backend/Schedule.php index 54162a0b8..b0b9fffe7 100644 --- a/backend/Schedule.php +++ b/backend/Schedule.php @@ -1,4 +1,6 @@ input->post('api_key'); -// if(!in_array($api_key, $CFG->ml_api_keys)) -// { -// //header('HTTP/1.0 401 Unauthorized'); -// //print 'You are not allowed to access this ressource. Sorry.'; -// //exit; -// } - $range_start = Schedule::CcTimeToPypoTime($p_fromDateTime); - $range_end = Schedule::CcTimeToPypoTime($p_toDateTime); - $range_dt = array('start' => $range_start, 'end' => $range_end); - + global $CC_CONFIG, $CC_DBC; + $range_start = Schedule::PypoTimeToCcTime($p_fromDateTime); + $range_end = Schedule::PypoTimeToCcTime($p_toDateTime); + $range_dt = array('start' => $range_start, 'end' => $range_end); + //var_dump($range_dt); + // Scheduler wants everything in a playlist - $data = Schedule::GetItems($p_fromDateTime, $p_toDateTime, true); - //var_dump($data); - $playlists = array(); + $data = Schedule::GetItems($range_start, $range_end, true); + //echo "
";var_dump($data);
+	  	$playlists = array();
 
 		if (is_array($data) && count($data) > 0)
 		{
 			foreach ($data as $dx)
 			{
-			  // Is this the first item in the playlist?
+			    // Is this the first item in the playlist?
 				$start = $dx['start'];
 				// chop off subseconds
-        $start = substr($start, 0, 19);
-
-        // Start time is the array key, needs to be in the format "YYYY-MM-DD-HH-mm-ss"
-        $pkey = Schedule::CcTimeToPypoTime($start);
-        $timestamp =  strtotime($start);
+		        $start = substr($start, 0, 19);
+		
+		        // Start time is the array key, needs to be in the format "YYYY-MM-DD-HH-mm-ss"
+		        $pkey = Schedule::CcTimeToPypoTime($start);
+		        $timestamp =  strtotime($start);
 				$playlists[$pkey]['source'] = "PLAYLIST";
 				$playlists[$pkey]['x_ident'] = $dx["playlist_id"];
 				$playlists[$pkey]['subtype'] = '1'; // Just needs to be between 1 and 4 inclusive
@@ -371,14 +372,14 @@ class Schedule {
 
 		foreach ($playlists as &$playlist)
 		{
-		  $scheduleGroup = new ScheduleGroup($playlist["schedule_id"]);
-      $items = $scheduleGroup->getItems();
+		    $scheduleGroup = new ScheduleGroup($playlist["schedule_id"]);
+      		$items = $scheduleGroup->getItems();
 			$medias = array();
 			$playlist['subtype'] = '1';
 			foreach ($items as $item)
 			{
-			  $storedFile = StoredFile::Recall($item["file_id"]);
-  			$uri = $storedFile->getFileUrl();
+			  	$storedFile = StoredFile::Recall($item["file_id"]);
+  				$uri = $storedFile->getFileUrl();
 				$medias[] = array(
 					'id' => $item["file_id"],
 					'uri' => $uri,
@@ -393,7 +394,7 @@ class Schedule {
 		}
 
 		$result = array();
-		$result['status'] = array('range' => $range_dt, 'version' => 0.1);
+		$result['status'] = array('range' => $range_dt, 'version' => 0.2);
 		$result['playlists'] = $playlists;
 		$result['check'] = 1;
 
diff --git a/conf.php b/conf.php
index b51d364f0..a2e2f3013 100644
--- a/conf.php
+++ b/conf.php
@@ -23,6 +23,8 @@ $CC_CONFIG = array(
 
     /* ================================================ storage configuration */
 
+    'apiKey' => array('AAA'),
+    
     // main directory for storing binary media files
     'storageDir'    =>  dirname(__FILE__).'/stor',
 
@@ -40,7 +42,8 @@ $CC_CONFIG = array(
     "smartyTemplate" => dirname(__FILE__)."/htmlUI/templates",
     "smartyTemplateCompiled" => dirname(__FILE__)."/htmlUI/templates_c",
     'pearPath'      =>  dirname(__FILE__).'/3rd_party/php/pear',
-
+    'zendPath'      =>  dirname(__FILE__).'/3rd_party/php/Zend',
+    
      // secret token cookie name
     'authCookieName'=> 'campcaster_session_id',
 
@@ -148,14 +151,16 @@ $CC_CONFIG['permSequence'] = $CC_CONFIG['permTable'].'_id';
 $CC_CONFIG['subjSequence'] = $CC_CONFIG['subjTable'].'_id';
 $CC_CONFIG['smembSequence'] = $CC_CONFIG['smembTable'].'_id';
 
-// system users/groups - cannot be deleted
+// System users/groups - they cannot be deleted
 $CC_CONFIG['sysSubjs'] = array(
     'root', /*$CC_CONFIG['AdminsGr'],*/ /*$CC_CONFIG['AllGr'],*/ $CC_CONFIG['StationPrefsGr']
 );
 
-// Add PEAR to the PHP path
+// Add libs to the PHP path
 $old_include_path = get_include_path();
-set_include_path('.'.PATH_SEPARATOR.$CC_CONFIG['pearPath'].PATH_SEPARATOR.$old_include_path);
+set_include_path('.'.PATH_SEPARATOR.$CC_CONFIG['pearPath']
+					.PATH_SEPARATOR.$CC_CONFIG['zendPath']
+					.PATH_SEPARATOR.$old_include_path);
 
 // Check that all the required directories exist.
 //foreach (array('storageDir', 'bufferDir', 'transDir', 'accessDir', 'cronDir') as $d) {
diff --git a/utils/campcaster-import.php b/utils/campcaster-import.php
index 50e1735f7..34d308bb6 100644
--- a/utils/campcaster-import.php
+++ b/utils/campcaster-import.php
@@ -237,12 +237,12 @@ $start = intval(date('U'));
 if ($DEBUG_IMPORT) {
     $testonly = false;
     $importMode = "link";
-    $files = array("/home/paul/music/Tom Petty/Anthology - Through the Years disc 2/13 - Into The Great Wide Open.ogg");
-    $dsn =  array('username' => 'test',
-                  'password' => 'test',
+    $files = array("/path/to/your/test/file.mp3");
+    $dsn =  array('username' => 'campcaster',
+                  'password' => 'campcaster',
                   'hostspec' => 'localhost',
                   'phptype' => 'pgsql',
-                  'database' => 'Campcaster-paul');
+                  'database' => 'campcaster');
 } else {
     $dsn = $CC_CONFIG['dsn'];
 }