Merge branch 'master' of dev.sourcefabric.org:airtime
Conflicts: python_apps/api_clients/api_client.py
This commit is contained in:
commit
eb74c5718f
13 changed files with 124 additions and 47 deletions
24
CREDITS
24
CREDITS
|
@ -2,11 +2,30 @@
|
||||||
CREDITS
|
CREDITS
|
||||||
=======
|
=======
|
||||||
|
|
||||||
|
Version 1.7.0
|
||||||
|
-------------
|
||||||
|
Naomi Aro (naomi.aro@sourcefabric.org)
|
||||||
|
Role: Software Developer
|
||||||
|
|
||||||
|
Martin Konecny (martin.konecny@sourcefabric.org)
|
||||||
|
Role: Software Developer
|
||||||
|
|
||||||
|
Ofir Gal (ofir.gal@sourcefabric.org)
|
||||||
|
Role: QA
|
||||||
|
|
||||||
|
Daniel James
|
||||||
|
Role: Documentor & QA
|
||||||
|
|
||||||
|
Paul Baranowski (paul.baranowski@sourcefabric.org)
|
||||||
|
Role: Project Manager
|
||||||
|
|
||||||
|
|
||||||
Version 1.6.1
|
Version 1.6.1
|
||||||
-------------
|
-------------
|
||||||
Version 1.6.1 fixes a problem with playout being interrupted after 48
|
Version 1.6.1 fixes a problem with playout being interrupted after 48
|
||||||
hours. It also fixes some security issues.
|
hours. It also fixes some security issues.
|
||||||
|
|
||||||
|
|
||||||
Version 1.6.0
|
Version 1.6.0
|
||||||
-------------
|
-------------
|
||||||
This version marks a major change to the project, completely replacing the
|
This version marks a major change to the project, completely replacing the
|
||||||
|
@ -27,11 +46,14 @@ Naomi Aro (naomi.aro@sourcefabric.org)
|
||||||
- Conversion to Propel DB backend
|
- Conversion to Propel DB backend
|
||||||
|
|
||||||
Martin Konecny (martin.konecny@sourcefabric.org)
|
Martin Konecny (martin.konecny@sourcefabric.org)
|
||||||
Role:Software Developer
|
Role: Software Developer
|
||||||
Highlights:
|
Highlights:
|
||||||
- New User Interface
|
- New User Interface
|
||||||
- Scheduler/Backend
|
- Scheduler/Backend
|
||||||
|
|
||||||
|
Ofir Gal (ofir.gal@sourcefabric.org)
|
||||||
|
Role: QA
|
||||||
|
|
||||||
Daniel James
|
Daniel James
|
||||||
Role: Documentor & QA
|
Role: Documentor & QA
|
||||||
|
|
||||||
|
|
25
INSTALL
25
INSTALL
|
@ -1,23 +1,22 @@
|
||||||
--------------------------------------------------------------------------------
|
Airtime is the open radio software for scheduling and remote station management.
|
||||||
|
Home page: http://airtime.sourcefabric.org/
|
||||||
|
|
||||||
Copyright (c) 2010-2011 Sourcefabric O.P.S.
|
Installation instructions are here:
|
||||||
|
http://wiki.sourcefabric.org/x/BQBF
|
||||||
|
|
||||||
This file is part of the Airtime project.
|
Here is the manual:
|
||||||
http://airtime.sourcefabric.org/
|
http://new.flossmanuals.net/airtime/index
|
||||||
|
|
||||||
To report bugs, visit our bug tracker at:
|
To report bugs, visit our bug tracker at:
|
||||||
http://dev.sourcefabric.org/browse/CC
|
http://dev.sourcefabric.org/browse/CC
|
||||||
|
|
||||||
Visit our community support forum here:
|
Visit our community support forum here:
|
||||||
http://forum.sourcefabric.org/index.php/f/14/
|
http://forum.sourcefabric.org/index.php/f/14/
|
||||||
|
|
||||||
For commercial support, see http://sourcefabric.org/en/services/about/347/Support.htm
|
For commercial support, see:
|
||||||
|
http://sourcefabric.org/en/services/about/347/Support.htm
|
||||||
or send an e-mail to contact@sourcefabric.org
|
or send an e-mail to contact@sourcefabric.org
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
If you are a developer and want to hack on Airtime, go here:
|
||||||
|
http://wiki.sourcefabric.org/display/CC
|
||||||
|
|
||||||
Please see this page for install instructions:
|
|
||||||
http://wiki.sourcefabric.org/display/CC/Installing+Airtime+%28v1.6%29
|
|
||||||
|
|
||||||
If you are a developer, see this page:
|
|
||||||
http://wiki.sourcefabric.org/display/CC
|
|
||||||
|
|
2
README
2
README
|
@ -4,6 +4,8 @@
|
||||||
Airtime is an open source application that provides remote automation
|
Airtime is an open source application that provides remote automation
|
||||||
of a radio station.
|
of a radio station.
|
||||||
|
|
||||||
|
Home page: http://airtime.sourcefabric.org/
|
||||||
|
|
||||||
Major features:
|
Major features:
|
||||||
* Web-based remote station management. Authorized personnel can add
|
* Web-based remote station management. Authorized personnel can add
|
||||||
program material, create playlists, and schedule programming all via
|
program material, create playlists, and schedule programming all via
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
echo
|
||||||
|
echo "This will tail the pypo-liquidsoap log file."
|
||||||
|
echo "Type in password for pypo user (default password is 'pypo'):"
|
||||||
su -l pypo -c "tail -F /etc/service/pypo-liquidsoap/log/main/current"
|
su -l pypo -c "tail -F /etc/service/pypo-liquidsoap/log/main/current"
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "This will tail the recorder log file."
|
||||||
|
echo "Type in password for pypo user (default password is 'pypo'):"
|
||||||
|
|
||||||
su -l pypo -c "tail -F /etc/service/recorder/log/main/current"
|
su -l pypo -c "tail -F /etc/service/recorder/log/main/current"
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "This will output the pypo log file."
|
||||||
|
echo "Type in password for pypo user (default password is 'pypo'):"
|
||||||
|
|
||||||
su -l pypo -c "less /etc/service/pypo/log/main/current"
|
su -l pypo -c "less /etc/service/pypo/log/main/current"
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "This will tail the pypo log file."
|
||||||
|
echo "Type in password for pypo user (default password is 'pypo'):"
|
||||||
|
|
||||||
su -l pypo -c "tail -F /etc/service/pypo/log/main/current"
|
su -l pypo -c "tail -F /etc/service/pypo/log/main/current"
|
||||||
|
|
|
@ -21,30 +21,30 @@ AirtimeInstall::UpdateIniValue('../build/build.properties', 'project.home', real
|
||||||
|
|
||||||
echo PHP_EOL."*** Database Installation ***".PHP_EOL;
|
echo PHP_EOL."*** Database Installation ***".PHP_EOL;
|
||||||
|
|
||||||
echo "* Creating Airtime Database User".PHP_EOL;
|
echo "* Creating Airtime database user".PHP_EOL;
|
||||||
AirtimeInstall::CreateDatabaseUser();
|
AirtimeInstall::CreateDatabaseUser();
|
||||||
|
|
||||||
echo "* Creating Airtime Database".PHP_EOL;
|
echo "* Creating Airtime database".PHP_EOL;
|
||||||
AirtimeInstall::CreateDatabase();
|
AirtimeInstall::CreateDatabase();
|
||||||
|
|
||||||
AirtimeInstall::DbConnect(true);
|
AirtimeInstall::DbConnect(true);
|
||||||
|
|
||||||
echo "* Install Postgresql Scripting Language".PHP_EOL;
|
echo "* Installing Postgresql scripting language".PHP_EOL;
|
||||||
AirtimeInstall::InstallPostgresScriptingLanguage();
|
AirtimeInstall::InstallPostgresScriptingLanguage();
|
||||||
|
|
||||||
echo "* Creating Database Tables".PHP_EOL;
|
echo "* Creating database tables".PHP_EOL;
|
||||||
AirtimeInstall::CreateDatabaseTables();
|
AirtimeInstall::CreateDatabaseTables();
|
||||||
|
|
||||||
echo "* Storage Directory Setup".PHP_EOL;
|
echo "* Storage directory setup".PHP_EOL;
|
||||||
AirtimeInstall::SetupStorageDirectory($CC_CONFIG);
|
AirtimeInstall::SetupStorageDirectory($CC_CONFIG);
|
||||||
|
|
||||||
echo "* Setting Dir Permissions".PHP_EOL;
|
echo "* Giving Apache permission to access the storage directory".PHP_EOL;
|
||||||
AirtimeInstall::ChangeDirOwnerToWebserver($CC_CONFIG["storageDir"]);
|
AirtimeInstall::ChangeDirOwnerToWebserver($CC_CONFIG["storageDir"]);
|
||||||
|
|
||||||
echo "* Creating /usr/bin symlinks".PHP_EOL;
|
echo "* Creating /usr/bin symlinks".PHP_EOL;
|
||||||
AirtimeInstall::CreateSymlinks($CC_CONFIG["storageDir"]);
|
AirtimeInstall::CreateSymlinks($CC_CONFIG["storageDir"]);
|
||||||
|
|
||||||
echo "* Importing Sample Audio Clips".PHP_EOL;
|
echo "* Importing sample audio clips".PHP_EOL;
|
||||||
system(__DIR__."/../utils/airtime-import --copy ../audio_samples/ > /dev/null");
|
system(__DIR__."/../utils/airtime-import --copy ../audio_samples/ > /dev/null");
|
||||||
|
|
||||||
echo PHP_EOL."*** Pypo Installation ***".PHP_EOL;
|
echo PHP_EOL."*** Pypo Installation ***".PHP_EOL;
|
||||||
|
|
|
@ -132,9 +132,15 @@ class AirtimeInstall {
|
||||||
|
|
||||||
@exec($command, $output, $results);
|
@exec($command, $output, $results);
|
||||||
if ($results == 0) {
|
if ($results == 0) {
|
||||||
echo "* User {$CC_CONFIG['dsn']['username']} created.".PHP_EOL;
|
echo "* Database user '{$CC_CONFIG['dsn']['username']}' created.".PHP_EOL;
|
||||||
} else {
|
} else {
|
||||||
echo "* Could not create user {$CC_CONFIG['dsn']['username']}: $output".PHP_EOL;
|
if (count($output) > 0) {
|
||||||
|
echo "* Could not create user '{$CC_CONFIG['dsn']['username']}': ".PHP_EOL;
|
||||||
|
echo implode(PHP_EOL, $output);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
echo "* Database user '{$CC_CONFIG['dsn']['username']}' already exists.".PHP_EOL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,7 +153,13 @@ class AirtimeInstall {
|
||||||
if ($results == 0) {
|
if ($results == 0) {
|
||||||
echo "* Database '{$CC_CONFIG['dsn']['database']}' created.".PHP_EOL;
|
echo "* Database '{$CC_CONFIG['dsn']['database']}' created.".PHP_EOL;
|
||||||
} else {
|
} else {
|
||||||
echo "* Could not create database '{$CC_CONFIG['dsn']['database']}': $output".PHP_EOL;
|
if (count($output) > 0) {
|
||||||
|
echo "* Could not create database '{$CC_CONFIG['dsn']['database']}': ".PHP_EOL;
|
||||||
|
echo implode(PHP_EOL, $output);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
echo "* Database '{$CC_CONFIG['dsn']['database']}' already exists.".PHP_EOL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -295,7 +295,7 @@ class AirTimeApiClient(ApiClientInterface):
|
||||||
|
|
||||||
def get_shows_to_record(self):
|
def get_shows_to_record(self):
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
response = ''
|
response = None
|
||||||
try:
|
try:
|
||||||
url = "http://%s:%s/%s/%s" % (self.config["base_url"], str(self.config["base_port"]), self.config["api_base"], self.config["show_schedule_url"])
|
url = "http://%s:%s/%s/%s" % (self.config["base_url"], str(self.config["base_port"]), self.config["api_base"], self.config["show_schedule_url"])
|
||||||
#url = self.config["base_url"] + self.config["api_base"] + self.config["show_schedule_url"]
|
#url = self.config["base_url"] + self.config["api_base"] + self.config["show_schedule_url"]
|
||||||
|
@ -309,26 +309,41 @@ class AirTimeApiClient(ApiClientInterface):
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
logger.error("Exception: %s", e)
|
logger.error("Exception: %s", e)
|
||||||
|
|
||||||
return response[u'shows']
|
return response
|
||||||
|
|
||||||
def upload_recorded_show(self, data, headers):
|
def upload_recorded_show(self, data, headers):
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
response = ''
|
response = ''
|
||||||
try:
|
|
||||||
|
retries = int(self.config["upload_retries"])
|
||||||
|
retries_wait = int(self.config["upload_wait"])
|
||||||
|
|
||||||
#url = self.config["base_url"] + self.config["api_base"] + self.config["upload_file_url"]
|
#url = self.config["base_url"] + self.config["api_base"] + self.config["upload_file_url"]
|
||||||
url = "http://%s:%s/%s/%s" % (self.config["base_url"], str(self.config["base_port"]), self.config["api_base"], self.config["upload_file_url"])
|
url = "http://%s:%s/%s/%s" % (self.config["base_url"], str(self.config["base_port"]), self.config["api_base"], self.config["upload_file_url"])
|
||||||
|
|
||||||
logger.debug(url)
|
logger.debug(url)
|
||||||
url = url.replace("%%api_key%%", self.config["api_key"])
|
url = url.replace("%%api_key%%", self.config["api_key"])
|
||||||
|
|
||||||
|
for i in range(0, retries):
|
||||||
|
logger.debug("Upload attempt: %s", i+1)
|
||||||
|
|
||||||
|
try:
|
||||||
request = urllib2.Request(url, data, headers)
|
request = urllib2.Request(url, data, headers)
|
||||||
response = urllib2.urlopen(request).read().strip()
|
response = urllib2.urlopen(request).read().strip()
|
||||||
|
|
||||||
logger.info("uploaded show result %s", response)
|
logger.info("uploaded show result %s", response)
|
||||||
|
break
|
||||||
|
|
||||||
|
except urllib2.HTTPError, e:
|
||||||
|
logger.error("Http error code: %s", e.code)
|
||||||
|
except urllib2.URLError, e:
|
||||||
|
logger.error("Server is down: %s", e.args)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
logger.error("Exception: %s", e)
|
logger.error("Exception: %s", e)
|
||||||
|
|
||||||
|
#wait some time before next retry
|
||||||
|
time.sleep(retries_wait)
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -84,9 +84,12 @@ class PypoFetch(Thread):
|
||||||
pypo_timezone = (process.communicate()[0]).strip(' \r\n\t')
|
pypo_timezone = (process.communicate()[0]).strip(' \r\n\t')
|
||||||
|
|
||||||
if server_timezone != pypo_timezone:
|
if server_timezone != pypo_timezone:
|
||||||
logger.error("Server and pypo timezone offsets do not match. Audio playback may not start when expected!")
|
logger.error("ERROR: Airtime server and pypo timezone offsets do not match. Audio playback will not start when expected!!!")
|
||||||
logger.error("Server timezone offset: %s", server_timezone)
|
logger.error(" * Server timezone offset: %s", server_timezone)
|
||||||
logger.error("Pypo timezone offset: %s", pypo_timezone)
|
logger.error(" * Pypo timezone offset: %s", pypo_timezone)
|
||||||
|
logger.error(" * To fix this, you need to set the 'date.timezone' value in your php.ini file and restart apache.")
|
||||||
|
logger.error(" * See this page for more info (v1.7): http://wiki.sourcefabric.org/x/BQBF")
|
||||||
|
logger.error(" * and also the 'FAQ and Support' page underneath it.")
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Process the schedule
|
Process the schedule
|
||||||
|
|
|
@ -20,3 +20,9 @@ show_schedule_url = 'recorded-shows/format/json/api_key/%%api_key%%'
|
||||||
|
|
||||||
# URL to upload the recorded show's file to Airtime
|
# URL to upload the recorded show's file to Airtime
|
||||||
upload_file_url = 'upload-recorded/format/json/api_key/%%api_key%%'
|
upload_file_url = 'upload-recorded/format/json/api_key/%%api_key%%'
|
||||||
|
|
||||||
|
#number of retries to upload file if connection problem
|
||||||
|
upload_retries = 3
|
||||||
|
|
||||||
|
#time to wait between attempts to upload file if connection problem (in seconds)
|
||||||
|
upload_wait = 60
|
||||||
|
|
|
@ -61,7 +61,7 @@ class ShowRecorder(Thread):
|
||||||
filename = self.filename.replace(" ", "-")
|
filename = self.filename.replace(" ", "-")
|
||||||
filepath = "%s%s.%s" % (config["base_recorded_files"], filename, self.filetype)
|
filepath = "%s%s.%s" % (config["base_recorded_files"], filename, self.filetype)
|
||||||
|
|
||||||
command = "ecasound -i alsa -o %s -t:%s -ge:3,1,0,-1" % (filepath, length)
|
command = "ecasound -i alsa -o %s -t:%s -ge:0.1,0.1,0,-1" % (filepath, length)
|
||||||
args = command.split(" ")
|
args = command.split(" ")
|
||||||
|
|
||||||
print "starting record"
|
print "starting record"
|
||||||
|
@ -145,6 +145,10 @@ class Record():
|
||||||
def get_shows(self):
|
def get_shows(self):
|
||||||
|
|
||||||
shows = self.api_client.get_shows_to_record()
|
shows = self.api_client.get_shows_to_record()
|
||||||
|
if shows is not None:
|
||||||
|
shows = shows[u'shows']
|
||||||
|
else:
|
||||||
|
shows = []
|
||||||
|
|
||||||
if len(shows):
|
if len(shows):
|
||||||
self.process_shows(shows)
|
self.process_shows(shows)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue