Merge branch 'master' of dev.sourcefabric.org:campcaster
This commit is contained in:
commit
1e0cba6a63
Binary file not shown.
|
@ -1,3 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from api_client import *
|
||||
__all__ = ["api_client"]
|
|
@ -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
|
|
@ -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)
|
||||
|
|
@ -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
|
||||
|
|
@ -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)
|
|
@ -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'
|
||||
|
|
|
@ -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=
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
Binary file not shown.
|
@ -1,4 +1,6 @@
|
|||
<?php
|
||||
require_once("StoredFile.php");
|
||||
require_once("BasicStor.php");
|
||||
|
||||
class ScheduleGroup {
|
||||
|
||||
|
@ -320,6 +322,11 @@ class Schedule {
|
|||
return $p_time;
|
||||
}
|
||||
|
||||
private static function PypoTimeToCcTime($p_time) {
|
||||
$t = explode("-", $p_time);
|
||||
return $t[0]."-".$t[1]."-".$t[2]." ".$t[3].":".$t[4].":00";
|
||||
}
|
||||
|
||||
/**
|
||||
* Export the schedule in json formatted for pypo (the liquidsoap scheduler)
|
||||
*
|
||||
|
@ -330,35 +337,29 @@ class Schedule {
|
|||
*/
|
||||
public static function ExportRangeAsJson($p_fromDateTime, $p_toDateTime)
|
||||
{
|
||||
global $CC_CONFIG, $CC_DBC;
|
||||
// $api_key = $this->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 "<pre>";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;
|
||||
|
||||
|
|
13
conf.php
13
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) {
|
||||
|
|
|
@ -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'];
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue