Merge branch 'devel' of dev.sourcefabric.org:airtime into devel

This commit is contained in:
James 2012-08-15 16:23:15 -04:00
commit 4783bf121a
28 changed files with 311 additions and 99 deletions

View File

@ -34,6 +34,7 @@ class ApiController extends Zend_Controller_Action
->addActionContext('get-bootstrap-info', 'json') ->addActionContext('get-bootstrap-info', 'json')
->addActionContext('get-files-without-replay-gain', 'json') ->addActionContext('get-files-without-replay-gain', 'json')
->addActionContext('reload-metadata-group', 'json') ->addActionContext('reload-metadata-group', 'json')
->addActionContext('notify-webstream-data', 'json')
->initContext(); ->initContext();
} }
@ -349,12 +350,15 @@ class ApiController extends Zend_Controller_Action
//set a 'last played' timestamp for media item //set a 'last played' timestamp for media item
//needed for smart playlists //needed for smart playlists
try{ try {
$file_id = Application_Model_Schedule::GetFileId($media_id); $file_id = Application_Model_Schedule::GetFileId($media_id);
$file = Application_Model_StoredFile::Recall($file_id); if (!is_null($file_id)) {
$now = new DateTime("now", new DateTimeZone("UTC")); //we are dealing with a file not a stream
$file->setLastPlayedTime($now); $file = Application_Model_StoredFile::Recall($file_id);
}catch(Exception $e){ $now = new DateTime("now", new DateTimeZone("UTC"));
$file->setLastPlayedTime($now);
}
} catch (Exception $e) {
Logging::log($e); Logging::log($e);
} }
@ -368,9 +372,11 @@ class ApiController extends Zend_Controller_Action
$end_timestamp = $now->add(new DateInterval("PT2H")); $end_timestamp = $now->add(new DateInterval("PT2H"));
$end_timestamp = $end_timestamp->format("Y-m-d H:i:s"); $end_timestamp = $end_timestamp->format("Y-m-d H:i:s");
$this->view->shows = Application_Model_Show::getShows(Application_Common_DateHelper::ConvertToUtcDateTime($today_timestamp, date_default_timezone_get()), $this->view->shows =
Application_Common_DateHelper::ConvertToUtcDateTime($end_timestamp, date_default_timezone_get()), Application_Model_Show::getShows(
$excludeInstance=NULL, $onlyRecord=TRUE); Application_Common_DateHelper::ConvertToUtcDateTime($today_timestamp, date_default_timezone_get()),
Application_Common_DateHelper::ConvertToUtcDateTime($end_timestamp, date_default_timezone_get()),
$excludeInstance = null, $onlyRecord = true);
$this->view->is_recording = false; $this->view->is_recording = false;
@ -394,11 +400,12 @@ class ApiController extends Zend_Controller_Action
$result = Application_Model_StoredFile::copyFileToStor($upload_dir, $fileName, $tempFileName); $result = Application_Model_StoredFile::copyFileToStor($upload_dir, $fileName, $tempFileName);
if (!is_null($result)) { if (!is_null($result)) {
die('{"jsonrpc" : "2.0", "error" : {"code": '.$result[code].', "message" : "'.$result[message].'"}}'); die('{"jsonrpc" : "2.0", "error" : {"code": '.$result['code'].', "message" : "'.$result['message'].'"}}');
} }
} }
public function uploadRecordedAction() { public function uploadRecordedAction()
{
$show_instance_id = $this->_getParam('showinstanceid'); $show_instance_id = $this->_getParam('showinstanceid');
$file_id = $this->_getParam('fileid'); $file_id = $this->_getParam('fileid');
$this->view->fileid = $file_id; $this->view->fileid = $file_id;
@ -422,7 +429,7 @@ class ApiController extends Zend_Controller_Action
$show_genre = $show_inst->getGenre(); $show_genre = $show_inst->getGenre();
$show_start_time = Application_Common_DateHelper::ConvertToLocalDateTimeString($show_inst->getShowInstanceStart()); $show_start_time = Application_Common_DateHelper::ConvertToLocalDateTimeString($show_inst->getShowInstanceStart());
} catch (Exception $e) { } catch (Exception $e) {
//we've reached here probably because the show was //we've reached here probably because the show was
//cancelled, and therefore the show instance does not //cancelled, and therefore the show instance does not
//exist anymore (ShowInstance constructor threw this error). //exist anymore (ShowInstance constructor threw this error).
@ -1015,4 +1022,34 @@ class ApiController extends Zend_Controller_Action
$file->save(); $file->save();
} }
} }
public function notifyWebstreamDataAction()
{
$request = $this->getRequest();
$data = $request->getParam("data");
$media_id = $request->getParam("media_id");
$schedule = CcScheduleQuery::create()->findPK($media_id);
$stream_id = $schedule->getDbStreamId();
if (!is_null($stream_id)) {
$webstream = CcWebstreamQuery::create()->findPK($stream_id);
if (strlen($data) <= 1024) {
$data_arr = json_decode($data);
if (isset($data_arr->title)) {
$webstream->setDbLiquidsoapData($data_arr->title);
} else {
$webstream->setDbLiquidsoapData('');
}
$webstream->save();
}
} else {
throw new Error("Unexpected error. media_id $media_id has a null stream value in cc_schedule!");
}
Logging::log(json_decode($data));
$this->view->response = $data;
$this->view->media_id = $media_id;
}
} }

View File

@ -191,8 +191,14 @@ class AudiopreviewController extends Zend_Controller_Action
'element_id' => isset($track['id'])?$track['id']:"", 'element_id' => isset($track['id'])?$track['id']:"",
'element_position' => isset($track['position'])?$track['position']:"", 'element_position' => isset($track['position'])?$track['position']:"",
); );
/* If the track type is static we know it must be
* a track because static blocks can only contain
* tracks
*/
if ($track['type'] == 'static') {
$track['type'] = 0;
}
$elementMap['type'] = $track['type']; $elementMap['type'] = $track['type'];
if ($track['type'] == 0) { if ($track['type'] == 0) {

View File

@ -1160,12 +1160,13 @@ EOT;
} else if ($spCriteriaModifier == "is in the range") { } else if ($spCriteriaModifier == "is in the range") {
$spCriteriaValue = "$spCriteria > '$spCriteriaValue' AND $spCriteria < '$criteria[extra]'"; $spCriteriaValue = "$spCriteria > '$spCriteriaValue' AND $spCriteria < '$criteria[extra]'";
} }
$spCriteriaModifier = self::$modifier2CriteriaMap[$spCriteriaModifier]; $spCriteriaModifier = self::$modifier2CriteriaMap[$spCriteriaModifier];
try{ try{
if ($i > 0) { if ($i > 0) {
$qry->addOr($spCriteria, $spCriteriaValue, $spCriteriaModifier); $qry->addOr($spCriteria, addslashes($spCriteriaValue), $spCriteriaModifier);
} else { } else {
$qry->add($spCriteria, $spCriteriaValue, $spCriteriaModifier); $qry->add($spCriteria, addslashes($spCriteriaValue), $spCriteriaModifier);
} }
}catch (Exception $e){ }catch (Exception $e){
Logging::log($e); Logging::log($e);

View File

@ -95,6 +95,11 @@ class Application_Model_Datatables
$r['length'] = $pl->getLength(); $r['length'] = $pl->getLength();
} else if ($r['ftype'] == "block") { } else if ($r['ftype'] == "block") {
$bl = new Application_Model_Block($r['id']); $bl = new Application_Model_Block($r['id']);
if ($bl->isStatic()) {
$r['bl_type'] = 'static';
} else {
$r['bl_type'] = 'dynamic';
}
$r['length'] = $bl->getLength(); $r['length'] = $bl->getLength();
} }
} }

View File

@ -80,12 +80,10 @@ class Application_Model_Schedule
%%tables%% WHERE "; %%tables%% WHERE ";
$fileColumns = "ft.artist_name, ft.track_title, "; $fileColumns = "ft.artist_name, ft.track_title, ";
//$fileJoin = "cc_files ft ON st.file_id = ft.id";
$fileJoin = "FROM cc_schedule st JOIN cc_files ft ON st.file_id = ft.id $fileJoin = "FROM cc_schedule st JOIN cc_files ft ON st.file_id = ft.id
LEFT JOIN cc_show_instances si ON st.instance_id = si.id"; LEFT JOIN cc_show_instances si ON st.instance_id = si.id";
$streamColumns = "sub.login as artist_name, ws.name as track_title, "; $streamColumns = "ws.name as artist_name, ws.liquidsoap_data as track_title, ";
//$streamJoin = "cc_webstream ws ON st.stream_id = ws.id";
$streamJoin = "FROM cc_schedule st JOIN cc_webstream ws ON st.stream_id = ws.id $streamJoin = "FROM cc_schedule st JOIN cc_webstream ws ON st.stream_id = ws.id
LEFT JOIN cc_show_instances si ON st.instance_id = si.id LEFT JOIN cc_show_instances si ON st.instance_id = si.id
LEFT JOIN cc_subjs as sub on sub.id = ws.creator_id"; LEFT JOIN cc_subjs as sub on sub.id = ws.creator_id";

View File

@ -47,6 +47,7 @@ class CcWebstreamTableMap extends TableMap {
$this->addColumn('MTIME', 'DbMtime', 'TIMESTAMP', true, 6, null); $this->addColumn('MTIME', 'DbMtime', 'TIMESTAMP', true, 6, null);
$this->addColumn('UTIME', 'DbUtime', 'TIMESTAMP', true, 6, null); $this->addColumn('UTIME', 'DbUtime', 'TIMESTAMP', true, 6, null);
$this->addColumn('MIME', 'DbMime', 'VARCHAR', false, 255, null); $this->addColumn('MIME', 'DbMime', 'VARCHAR', false, 255, null);
$this->addColumn('LIQUIDSOAP_DATA', 'DbLiquidsoapData', 'VARCHAR', false, 1024, null);
// validators // validators
} // initialize() } // initialize()

View File

@ -79,6 +79,12 @@ abstract class BaseCcWebstream extends BaseObject implements Persistent
*/ */
protected $mime; protected $mime;
/**
* The value for the liquidsoap_data field.
* @var string
*/
protected $liquidsoap_data;
/** /**
* @var array CcSchedule[] Collection to store aggregation of CcSchedule objects. * @var array CcSchedule[] Collection to store aggregation of CcSchedule objects.
*/ */
@ -255,6 +261,16 @@ abstract class BaseCcWebstream extends BaseObject implements Persistent
return $this->mime; return $this->mime;
} }
/**
* Get the [liquidsoap_data] column value.
*
* @return string
*/
public function getDbLiquidsoapData()
{
return $this->liquidsoap_data;
}
/** /**
* Set the value of [id] column. * Set the value of [id] column.
* *
@ -493,6 +509,26 @@ abstract class BaseCcWebstream extends BaseObject implements Persistent
return $this; return $this;
} // setDbMime() } // setDbMime()
/**
* Set the value of [liquidsoap_data] column.
*
* @param string $v new value
* @return CcWebstream The current object (for fluent API support)
*/
public function setDbLiquidsoapData($v)
{
if ($v !== null) {
$v = (string) $v;
}
if ($this->liquidsoap_data !== $v) {
$this->liquidsoap_data = $v;
$this->modifiedColumns[] = CcWebstreamPeer::LIQUIDSOAP_DATA;
}
return $this;
} // setDbLiquidsoapData()
/** /**
* Indicates whether the columns in this object are only set to default values. * Indicates whether the columns in this object are only set to default values.
* *
@ -538,6 +574,7 @@ abstract class BaseCcWebstream extends BaseObject implements Persistent
$this->mtime = ($row[$startcol + 6] !== null) ? (string) $row[$startcol + 6] : null; $this->mtime = ($row[$startcol + 6] !== null) ? (string) $row[$startcol + 6] : null;
$this->utime = ($row[$startcol + 7] !== null) ? (string) $row[$startcol + 7] : null; $this->utime = ($row[$startcol + 7] !== null) ? (string) $row[$startcol + 7] : null;
$this->mime = ($row[$startcol + 8] !== null) ? (string) $row[$startcol + 8] : null; $this->mime = ($row[$startcol + 8] !== null) ? (string) $row[$startcol + 8] : null;
$this->liquidsoap_data = ($row[$startcol + 9] !== null) ? (string) $row[$startcol + 9] : null;
$this->resetModified(); $this->resetModified();
$this->setNew(false); $this->setNew(false);
@ -546,7 +583,7 @@ abstract class BaseCcWebstream extends BaseObject implements Persistent
$this->ensureConsistency(); $this->ensureConsistency();
} }
return $startcol + 9; // 9 = CcWebstreamPeer::NUM_COLUMNS - CcWebstreamPeer::NUM_LAZY_LOAD_COLUMNS). return $startcol + 10; // 10 = CcWebstreamPeer::NUM_COLUMNS - CcWebstreamPeer::NUM_LAZY_LOAD_COLUMNS).
} catch (Exception $e) { } catch (Exception $e) {
throw new PropelException("Error populating CcWebstream object", $e); throw new PropelException("Error populating CcWebstream object", $e);
@ -890,6 +927,9 @@ abstract class BaseCcWebstream extends BaseObject implements Persistent
case 8: case 8:
return $this->getDbMime(); return $this->getDbMime();
break; break;
case 9:
return $this->getDbLiquidsoapData();
break;
default: default:
return null; return null;
break; break;
@ -922,6 +962,7 @@ abstract class BaseCcWebstream extends BaseObject implements Persistent
$keys[6] => $this->getDbMtime(), $keys[6] => $this->getDbMtime(),
$keys[7] => $this->getDbUtime(), $keys[7] => $this->getDbUtime(),
$keys[8] => $this->getDbMime(), $keys[8] => $this->getDbMime(),
$keys[9] => $this->getDbLiquidsoapData(),
); );
return $result; return $result;
} }
@ -980,6 +1021,9 @@ abstract class BaseCcWebstream extends BaseObject implements Persistent
case 8: case 8:
$this->setDbMime($value); $this->setDbMime($value);
break; break;
case 9:
$this->setDbLiquidsoapData($value);
break;
} // switch() } // switch()
} }
@ -1013,6 +1057,7 @@ abstract class BaseCcWebstream extends BaseObject implements Persistent
if (array_key_exists($keys[6], $arr)) $this->setDbMtime($arr[$keys[6]]); if (array_key_exists($keys[6], $arr)) $this->setDbMtime($arr[$keys[6]]);
if (array_key_exists($keys[7], $arr)) $this->setDbUtime($arr[$keys[7]]); if (array_key_exists($keys[7], $arr)) $this->setDbUtime($arr[$keys[7]]);
if (array_key_exists($keys[8], $arr)) $this->setDbMime($arr[$keys[8]]); if (array_key_exists($keys[8], $arr)) $this->setDbMime($arr[$keys[8]]);
if (array_key_exists($keys[9], $arr)) $this->setDbLiquidsoapData($arr[$keys[9]]);
} }
/** /**
@ -1033,6 +1078,7 @@ abstract class BaseCcWebstream extends BaseObject implements Persistent
if ($this->isColumnModified(CcWebstreamPeer::MTIME)) $criteria->add(CcWebstreamPeer::MTIME, $this->mtime); if ($this->isColumnModified(CcWebstreamPeer::MTIME)) $criteria->add(CcWebstreamPeer::MTIME, $this->mtime);
if ($this->isColumnModified(CcWebstreamPeer::UTIME)) $criteria->add(CcWebstreamPeer::UTIME, $this->utime); if ($this->isColumnModified(CcWebstreamPeer::UTIME)) $criteria->add(CcWebstreamPeer::UTIME, $this->utime);
if ($this->isColumnModified(CcWebstreamPeer::MIME)) $criteria->add(CcWebstreamPeer::MIME, $this->mime); if ($this->isColumnModified(CcWebstreamPeer::MIME)) $criteria->add(CcWebstreamPeer::MIME, $this->mime);
if ($this->isColumnModified(CcWebstreamPeer::LIQUIDSOAP_DATA)) $criteria->add(CcWebstreamPeer::LIQUIDSOAP_DATA, $this->liquidsoap_data);
return $criteria; return $criteria;
} }
@ -1102,6 +1148,7 @@ abstract class BaseCcWebstream extends BaseObject implements Persistent
$copyObj->setDbMtime($this->mtime); $copyObj->setDbMtime($this->mtime);
$copyObj->setDbUtime($this->utime); $copyObj->setDbUtime($this->utime);
$copyObj->setDbMime($this->mime); $copyObj->setDbMime($this->mime);
$copyObj->setDbLiquidsoapData($this->liquidsoap_data);
if ($deepCopy) { if ($deepCopy) {
// important: temporarily setNew(false) because this affects the behavior of // important: temporarily setNew(false) because this affects the behavior of
@ -1332,6 +1379,7 @@ abstract class BaseCcWebstream extends BaseObject implements Persistent
$this->mtime = null; $this->mtime = null;
$this->utime = null; $this->utime = null;
$this->mime = null; $this->mime = null;
$this->liquidsoap_data = null;
$this->alreadyInSave = false; $this->alreadyInSave = false;
$this->alreadyInValidation = false; $this->alreadyInValidation = false;
$this->clearAllReferences(); $this->clearAllReferences();

View File

@ -26,7 +26,7 @@ abstract class BaseCcWebstreamPeer {
const TM_CLASS = 'CcWebstreamTableMap'; const TM_CLASS = 'CcWebstreamTableMap';
/** The total number of columns. */ /** The total number of columns. */
const NUM_COLUMNS = 9; const NUM_COLUMNS = 10;
/** The number of lazy-loaded columns. */ /** The number of lazy-loaded columns. */
const NUM_LAZY_LOAD_COLUMNS = 0; const NUM_LAZY_LOAD_COLUMNS = 0;
@ -58,6 +58,9 @@ abstract class BaseCcWebstreamPeer {
/** the column name for the MIME field */ /** the column name for the MIME field */
const MIME = 'cc_webstream.MIME'; const MIME = 'cc_webstream.MIME';
/** the column name for the LIQUIDSOAP_DATA field */
const LIQUIDSOAP_DATA = 'cc_webstream.LIQUIDSOAP_DATA';
/** /**
* An identiy map to hold any loaded instances of CcWebstream objects. * An identiy map to hold any loaded instances of CcWebstream objects.
* This must be public so that other peer classes can access this when hydrating from JOIN * This must be public so that other peer classes can access this when hydrating from JOIN
@ -74,12 +77,12 @@ abstract class BaseCcWebstreamPeer {
* e.g. self::$fieldNames[self::TYPE_PHPNAME][0] = 'Id' * e.g. self::$fieldNames[self::TYPE_PHPNAME][0] = 'Id'
*/ */
private static $fieldNames = array ( private static $fieldNames = array (
BasePeer::TYPE_PHPNAME => array ('DbId', 'DbName', 'DbDescription', 'DbUrl', 'DbLength', 'DbCreatorId', 'DbMtime', 'DbUtime', 'DbMime', ), BasePeer::TYPE_PHPNAME => array ('DbId', 'DbName', 'DbDescription', 'DbUrl', 'DbLength', 'DbCreatorId', 'DbMtime', 'DbUtime', 'DbMime', 'DbLiquidsoapData', ),
BasePeer::TYPE_STUDLYPHPNAME => array ('dbId', 'dbName', 'dbDescription', 'dbUrl', 'dbLength', 'dbCreatorId', 'dbMtime', 'dbUtime', 'dbMime', ), BasePeer::TYPE_STUDLYPHPNAME => array ('dbId', 'dbName', 'dbDescription', 'dbUrl', 'dbLength', 'dbCreatorId', 'dbMtime', 'dbUtime', 'dbMime', 'dbLiquidsoapData', ),
BasePeer::TYPE_COLNAME => array (self::ID, self::NAME, self::DESCRIPTION, self::URL, self::LENGTH, self::CREATOR_ID, self::MTIME, self::UTIME, self::MIME, ), BasePeer::TYPE_COLNAME => array (self::ID, self::NAME, self::DESCRIPTION, self::URL, self::LENGTH, self::CREATOR_ID, self::MTIME, self::UTIME, self::MIME, self::LIQUIDSOAP_DATA, ),
BasePeer::TYPE_RAW_COLNAME => array ('ID', 'NAME', 'DESCRIPTION', 'URL', 'LENGTH', 'CREATOR_ID', 'MTIME', 'UTIME', 'MIME', ), BasePeer::TYPE_RAW_COLNAME => array ('ID', 'NAME', 'DESCRIPTION', 'URL', 'LENGTH', 'CREATOR_ID', 'MTIME', 'UTIME', 'MIME', 'LIQUIDSOAP_DATA', ),
BasePeer::TYPE_FIELDNAME => array ('id', 'name', 'description', 'url', 'length', 'creator_id', 'mtime', 'utime', 'mime', ), BasePeer::TYPE_FIELDNAME => array ('id', 'name', 'description', 'url', 'length', 'creator_id', 'mtime', 'utime', 'mime', 'liquidsoap_data', ),
BasePeer::TYPE_NUM => array (0, 1, 2, 3, 4, 5, 6, 7, 8, ) BasePeer::TYPE_NUM => array (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, )
); );
/** /**
@ -89,12 +92,12 @@ abstract class BaseCcWebstreamPeer {
* e.g. self::$fieldNames[BasePeer::TYPE_PHPNAME]['Id'] = 0 * e.g. self::$fieldNames[BasePeer::TYPE_PHPNAME]['Id'] = 0
*/ */
private static $fieldKeys = array ( private static $fieldKeys = array (
BasePeer::TYPE_PHPNAME => array ('DbId' => 0, 'DbName' => 1, 'DbDescription' => 2, 'DbUrl' => 3, 'DbLength' => 4, 'DbCreatorId' => 5, 'DbMtime' => 6, 'DbUtime' => 7, 'DbMime' => 8, ), BasePeer::TYPE_PHPNAME => array ('DbId' => 0, 'DbName' => 1, 'DbDescription' => 2, 'DbUrl' => 3, 'DbLength' => 4, 'DbCreatorId' => 5, 'DbMtime' => 6, 'DbUtime' => 7, 'DbMime' => 8, 'DbLiquidsoapData' => 9, ),
BasePeer::TYPE_STUDLYPHPNAME => array ('dbId' => 0, 'dbName' => 1, 'dbDescription' => 2, 'dbUrl' => 3, 'dbLength' => 4, 'dbCreatorId' => 5, 'dbMtime' => 6, 'dbUtime' => 7, 'dbMime' => 8, ), BasePeer::TYPE_STUDLYPHPNAME => array ('dbId' => 0, 'dbName' => 1, 'dbDescription' => 2, 'dbUrl' => 3, 'dbLength' => 4, 'dbCreatorId' => 5, 'dbMtime' => 6, 'dbUtime' => 7, 'dbMime' => 8, 'dbLiquidsoapData' => 9, ),
BasePeer::TYPE_COLNAME => array (self::ID => 0, self::NAME => 1, self::DESCRIPTION => 2, self::URL => 3, self::LENGTH => 4, self::CREATOR_ID => 5, self::MTIME => 6, self::UTIME => 7, self::MIME => 8, ), BasePeer::TYPE_COLNAME => array (self::ID => 0, self::NAME => 1, self::DESCRIPTION => 2, self::URL => 3, self::LENGTH => 4, self::CREATOR_ID => 5, self::MTIME => 6, self::UTIME => 7, self::MIME => 8, self::LIQUIDSOAP_DATA => 9, ),
BasePeer::TYPE_RAW_COLNAME => array ('ID' => 0, 'NAME' => 1, 'DESCRIPTION' => 2, 'URL' => 3, 'LENGTH' => 4, 'CREATOR_ID' => 5, 'MTIME' => 6, 'UTIME' => 7, 'MIME' => 8, ), BasePeer::TYPE_RAW_COLNAME => array ('ID' => 0, 'NAME' => 1, 'DESCRIPTION' => 2, 'URL' => 3, 'LENGTH' => 4, 'CREATOR_ID' => 5, 'MTIME' => 6, 'UTIME' => 7, 'MIME' => 8, 'LIQUIDSOAP_DATA' => 9, ),
BasePeer::TYPE_FIELDNAME => array ('id' => 0, 'name' => 1, 'description' => 2, 'url' => 3, 'length' => 4, 'creator_id' => 5, 'mtime' => 6, 'utime' => 7, 'mime' => 8, ), BasePeer::TYPE_FIELDNAME => array ('id' => 0, 'name' => 1, 'description' => 2, 'url' => 3, 'length' => 4, 'creator_id' => 5, 'mtime' => 6, 'utime' => 7, 'mime' => 8, 'liquidsoap_data' => 9, ),
BasePeer::TYPE_NUM => array (0, 1, 2, 3, 4, 5, 6, 7, 8, ) BasePeer::TYPE_NUM => array (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, )
); );
/** /**
@ -175,6 +178,7 @@ abstract class BaseCcWebstreamPeer {
$criteria->addSelectColumn(CcWebstreamPeer::MTIME); $criteria->addSelectColumn(CcWebstreamPeer::MTIME);
$criteria->addSelectColumn(CcWebstreamPeer::UTIME); $criteria->addSelectColumn(CcWebstreamPeer::UTIME);
$criteria->addSelectColumn(CcWebstreamPeer::MIME); $criteria->addSelectColumn(CcWebstreamPeer::MIME);
$criteria->addSelectColumn(CcWebstreamPeer::LIQUIDSOAP_DATA);
} else { } else {
$criteria->addSelectColumn($alias . '.ID'); $criteria->addSelectColumn($alias . '.ID');
$criteria->addSelectColumn($alias . '.NAME'); $criteria->addSelectColumn($alias . '.NAME');
@ -185,6 +189,7 @@ abstract class BaseCcWebstreamPeer {
$criteria->addSelectColumn($alias . '.MTIME'); $criteria->addSelectColumn($alias . '.MTIME');
$criteria->addSelectColumn($alias . '.UTIME'); $criteria->addSelectColumn($alias . '.UTIME');
$criteria->addSelectColumn($alias . '.MIME'); $criteria->addSelectColumn($alias . '.MIME');
$criteria->addSelectColumn($alias . '.LIQUIDSOAP_DATA');
} }
} }

View File

@ -15,6 +15,7 @@
* @method CcWebstreamQuery orderByDbMtime($order = Criteria::ASC) Order by the mtime column * @method CcWebstreamQuery orderByDbMtime($order = Criteria::ASC) Order by the mtime column
* @method CcWebstreamQuery orderByDbUtime($order = Criteria::ASC) Order by the utime column * @method CcWebstreamQuery orderByDbUtime($order = Criteria::ASC) Order by the utime column
* @method CcWebstreamQuery orderByDbMime($order = Criteria::ASC) Order by the mime column * @method CcWebstreamQuery orderByDbMime($order = Criteria::ASC) Order by the mime column
* @method CcWebstreamQuery orderByDbLiquidsoapData($order = Criteria::ASC) Order by the liquidsoap_data column
* *
* @method CcWebstreamQuery groupByDbId() Group by the id column * @method CcWebstreamQuery groupByDbId() Group by the id column
* @method CcWebstreamQuery groupByDbName() Group by the name column * @method CcWebstreamQuery groupByDbName() Group by the name column
@ -25,6 +26,7 @@
* @method CcWebstreamQuery groupByDbMtime() Group by the mtime column * @method CcWebstreamQuery groupByDbMtime() Group by the mtime column
* @method CcWebstreamQuery groupByDbUtime() Group by the utime column * @method CcWebstreamQuery groupByDbUtime() Group by the utime column
* @method CcWebstreamQuery groupByDbMime() Group by the mime column * @method CcWebstreamQuery groupByDbMime() Group by the mime column
* @method CcWebstreamQuery groupByDbLiquidsoapData() Group by the liquidsoap_data column
* *
* @method CcWebstreamQuery leftJoin($relation) Adds a LEFT JOIN clause to the query * @method CcWebstreamQuery leftJoin($relation) Adds a LEFT JOIN clause to the query
* @method CcWebstreamQuery rightJoin($relation) Adds a RIGHT JOIN clause to the query * @method CcWebstreamQuery rightJoin($relation) Adds a RIGHT JOIN clause to the query
@ -46,6 +48,7 @@
* @method CcWebstream findOneByDbMtime(string $mtime) Return the first CcWebstream filtered by the mtime column * @method CcWebstream findOneByDbMtime(string $mtime) Return the first CcWebstream filtered by the mtime column
* @method CcWebstream findOneByDbUtime(string $utime) Return the first CcWebstream filtered by the utime column * @method CcWebstream findOneByDbUtime(string $utime) Return the first CcWebstream filtered by the utime column
* @method CcWebstream findOneByDbMime(string $mime) Return the first CcWebstream filtered by the mime column * @method CcWebstream findOneByDbMime(string $mime) Return the first CcWebstream filtered by the mime column
* @method CcWebstream findOneByDbLiquidsoapData(string $liquidsoap_data) Return the first CcWebstream filtered by the liquidsoap_data column
* *
* @method array findByDbId(int $id) Return CcWebstream objects filtered by the id column * @method array findByDbId(int $id) Return CcWebstream objects filtered by the id column
* @method array findByDbName(string $name) Return CcWebstream objects filtered by the name column * @method array findByDbName(string $name) Return CcWebstream objects filtered by the name column
@ -56,6 +59,7 @@
* @method array findByDbMtime(string $mtime) Return CcWebstream objects filtered by the mtime column * @method array findByDbMtime(string $mtime) Return CcWebstream objects filtered by the mtime column
* @method array findByDbUtime(string $utime) Return CcWebstream objects filtered by the utime column * @method array findByDbUtime(string $utime) Return CcWebstream objects filtered by the utime column
* @method array findByDbMime(string $mime) Return CcWebstream objects filtered by the mime column * @method array findByDbMime(string $mime) Return CcWebstream objects filtered by the mime column
* @method array findByDbLiquidsoapData(string $liquidsoap_data) Return CcWebstream objects filtered by the liquidsoap_data column
* *
* @package propel.generator.airtime.om * @package propel.generator.airtime.om
*/ */
@ -385,6 +389,28 @@ abstract class BaseCcWebstreamQuery extends ModelCriteria
return $this->addUsingAlias(CcWebstreamPeer::MIME, $dbMime, $comparison); return $this->addUsingAlias(CcWebstreamPeer::MIME, $dbMime, $comparison);
} }
/**
* Filter the query on the liquidsoap_data column
*
* @param string $dbLiquidsoapData The value to use as filter.
* Accepts wildcards (* and % trigger a LIKE)
* @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL
*
* @return CcWebstreamQuery The current query, for fluid interface
*/
public function filterByDbLiquidsoapData($dbLiquidsoapData = null, $comparison = null)
{
if (null === $comparison) {
if (is_array($dbLiquidsoapData)) {
$comparison = Criteria::IN;
} elseif (preg_match('/[\%\*]/', $dbLiquidsoapData)) {
$dbLiquidsoapData = str_replace('*', '%', $dbLiquidsoapData);
$comparison = Criteria::LIKE;
}
}
return $this->addUsingAlias(CcWebstreamPeer::LIQUIDSOAP_DATA, $dbLiquidsoapData, $comparison);
}
/** /**
* Filter the query by a related CcSchedule object * Filter the query by a related CcSchedule object
* *

View File

@ -19,6 +19,10 @@ class BitrateFormatter {
{ {
$Kbps = bcdiv($this->_bitrate, 1000, 0); $Kbps = bcdiv($this->_bitrate, 1000, 0);
return "{$Kbps} Kbps"; if($Kbps == 0) {
return "";
} else {
return "{$Kbps} Kbps";
}
} }
} }

View File

@ -423,5 +423,6 @@
<column name="mtime" phpName="DbMtime" type="TIMESTAMP" size="6" required="true" /> <column name="mtime" phpName="DbMtime" type="TIMESTAMP" size="6" required="true" />
<column name="utime" phpName="DbUtime" type="TIMESTAMP" size="6" required="true" /> <column name="utime" phpName="DbUtime" type="TIMESTAMP" size="6" required="true" />
<column name="mime" phpName="DbMime" type="VARCHAR" /> <column name="mime" phpName="DbMime" type="VARCHAR" />
<column name="liquidsoap_data" phpName="DbLiquidsoapData" type="VARCHAR" size="1024" required="false"/>
</table> </table>
</database> </database>

View File

@ -639,6 +639,7 @@ CREATE TABLE "cc_webstream"
"mtime" TIMESTAMP(6) NOT NULL, "mtime" TIMESTAMP(6) NOT NULL,
"utime" TIMESTAMP(6) NOT NULL, "utime" TIMESTAMP(6) NOT NULL,
"mime" VARCHAR(255), "mime" VARCHAR(255),
"liquidsoap_data" VARCHAR(1024),
PRIMARY KEY ("id") PRIMARY KEY ("id")
); );

View File

@ -40,6 +40,10 @@ var AIRTIME = (function(AIRTIME){
$nRow.attr("id", aData["tr_id"]) $nRow.attr("id", aData["tr_id"])
.data("aData", aData) .data("aData", aData)
.data("screen", "playlist"); .data("screen", "playlist");
if (aData["bl_type"] !== undefined) {
$nRow.attr("bl_type", aData["bl_type"]);
}
}; };
mod.fnDrawCallback = function() { mod.fnDrawCallback = function() {

View File

@ -426,6 +426,9 @@ var AIRTIME = (function(AIRTIME) {
open_audio_preview(aData.ftype, aData.audioFile, aData.track_title, aData.artist_name); open_audio_preview(aData.ftype, aData.audioFile, aData.track_title, aData.artist_name);
} else if (aData.ftype == 'stream') { } else if (aData.ftype == 'stream') {
open_audio_preview(aData.ftype, aData.audioFile, aData.track_title, aData.artist_name); open_audio_preview(aData.ftype, aData.audioFile, aData.track_title, aData.artist_name);
} else if (aData.ftype == 'block' && aData.bl_type == 'static') {
blockIndex = $(this).parent().attr('id').substring(3); //remove the bl_
open_block_preview(blockIndex, 0);
} }
return false; return false;
}); });

View File

@ -414,7 +414,8 @@ function sizeTextBoxes(ele, classToRemove, classToAdd) {
function populateModifierSelect(e) { function populateModifierSelect(e) {
var criteria_type = getCriteriaOptionType(e), var criteria_type = getCriteriaOptionType(e),
index = getRowIndex($(e).parent()), index = getRowIndex($(e).parent()),
divs = $(e).parents().find('select[id^="sp_criteria_modifier_'+index+'"]'); critIndex = index.substring(0, 1),
divs = $(e).parents().find('select[id^="sp_criteria_modifier_'+critIndex+'"]');
$.each(divs, function(i, div){ $.each(divs, function(i, div){
$(div).children().remove(); $(div).children().remove();

View File

@ -115,3 +115,5 @@ get_bootstrap_info = 'get-bootstrap-info/format/json/api_key/%%api_key%%'
get_files_without_replay_gain = 'get-files-without-replay-gain/api_key/%%api_key%%/dir_id/%%dir_id%%' get_files_without_replay_gain = 'get-files-without-replay-gain/api_key/%%api_key%%/dir_id/%%dir_id%%'
update_replay_gain_value = 'update-replay-gain-value/api_key/%%api_key%%' update_replay_gain_value = 'update-replay-gain-value/api_key/%%api_key%%'
notify_webstream_data = 'notify-webstream-data/api_key/%%api_key%%/media_id/%%media_id%%/format/json'

View File

@ -81,9 +81,17 @@ class AirtimeApiClient():
successful_response = True successful_response = True
except IOError, e: except IOError, e:
logger.error('Error Authenticating with remote server: %s', e) logger.error('Error Authenticating with remote server: %s', e)
if isinstance(url, urllib2.Request):
logger.debug(url.get_full_url())
else:
logger.debug(url)
except Exception, e: except Exception, e:
logger.error('Couldn\'t connect to remote server. Is it running?') logger.error('Couldn\'t connect to remote server. Is it running?')
logger.error("%s" % e) logger.error("%s" % e)
if isinstance(url, urllib2.Request):
logger.debug(url.get_full_url())
else:
logger.debug(url)
if not successful_response: if not successful_response:
logger.error("Error connecting to server, waiting 5 seconds and trying again.") logger.error("Error connecting to server, waiting 5 seconds and trying again.")
@ -684,7 +692,25 @@ class AirtimeApiClient():
data = urllib.urlencode({'data': json.dumps(pairs)}) data = urllib.urlencode({'data': json.dumps(pairs)})
request = urllib2.Request(url, data) request = urllib2.Request(url, data)
self.get_response_from_server(request) self.logger.debug(self.get_response_from_server(request))
except Exception, e: except Exception, e:
self.logger.error("Exception: %s", e) self.logger.error("Exception: %s", e)
raise raise
def notify_webstream_data(self, data, media_id):
"""
Update the server with the latest metadata we've received from the
external webstream
"""
try:
url = "http://%(base_url)s:%(base_port)s/%(api_base)s/%(notify_webstream_data)s/" % (self.config)
url = url.replace("%%media_id%%", str(media_id))
url = url.replace("%%api_key%%", self.config["api_key"])
data = urllib.urlencode({'data': data})
self.logger.debug(url)
request = urllib2.Request(url, data)
self.logger.info(self.get_response_from_server(request))
except Exception, e:
self.logger.error("Exception: %s", e)

View File

@ -8,8 +8,7 @@ import media.monitor.pure as mmp
class MMConfig(object): class MMConfig(object):
def __init__(self, path): def __init__(self, path):
if not os.path.exists(path): if not os.path.exists(path): raise NoConfigFile(path)
raise NoConfigFile(path)
self.cfg = ConfigObj(path) self.cfg = ConfigObj(path)
def __getitem__(self, key): def __getitem__(self, key):
@ -29,6 +28,10 @@ class MMConfig(object):
def save(self): self.cfg.write() def save(self): self.cfg.write()
def last_ran(self): def last_ran(self):
"""
Returns the last time media monitor was ran by looking at the time when
the file at 'index_path' was modified
"""
return mmp.last_modified(self.cfg['index_path']) return mmp.last_modified(self.cfg['index_path'])
# Remove this after debugging... # Remove this after debugging...

View File

@ -46,7 +46,6 @@ class EventContractor(Loggable):
self.store[ evt.path ] = evt self.store[ evt.path ] = evt
return True # We actually added something, hence we return true. return True # We actually added something, hence we return true.
# events are unregistered automatically no need to screw around with them
def __unregister(self, evt): def __unregister(self, evt):
try: del self.store[evt.path] try: del self.store[evt.path]
except Exception as e: self.unexpected_exception(e) except Exception as e: self.unexpected_exception(e)

View File

@ -51,7 +51,7 @@ airtime_special = {
"MDATA_KEY_DURATION" : "MDATA_KEY_DURATION" :
lambda m: format_length(getattr(m.info, u'length', 0.0)), lambda m: format_length(getattr(m.info, u'length', 0.0)),
"MDATA_KEY_BITRATE" : "MDATA_KEY_BITRATE" :
lambda m: getattr(m.info, "bitrate", 0), lambda m: getattr(m.info, "bitrate", ''),
"MDATA_KEY_SAMPLERATE" : "MDATA_KEY_SAMPLERATE" :
lambda m: getattr(m.info, u'sample_rate', 0), lambda m: getattr(m.info, u'sample_rate', 0),
"MDATA_KEY_MIME" : "MDATA_KEY_MIME" :
@ -110,8 +110,7 @@ class Metadata(Loggable):
""" """
Writes 'md' metadata into 'path' through mutagen Writes 'md' metadata into 'path' through mutagen
""" """
if not os.path.exists(path): if not os.path.exists(path): raise BadSongFile(path)
raise BadSongFile(path)
song_file = mutagen.File(path, easy=True) song_file = mutagen.File(path, easy=True)
for airtime_k, airtime_v in md.iteritems(): for airtime_k, airtime_v in md.iteritems():
if airtime_k in airtime2mutagen: if airtime_k in airtime2mutagen:
@ -120,7 +119,6 @@ class Metadata(Loggable):
song_file[ airtime2mutagen[airtime_k] ] = unicode(airtime_v) song_file[ airtime2mutagen[airtime_k] ] = unicode(airtime_v)
song_file.save() song_file.save()
def __init__(self, fpath): def __init__(self, fpath):
# Forcing the unicode through # Forcing the unicode through
try: fpath = fpath.decode("utf-8") try: fpath = fpath.decode("utf-8")

View File

@ -18,8 +18,8 @@ class Organizer(ReportHandler,Loggable):
_instance = None _instance = None
def __new__(cls, channel, target_path, recorded_path): def __new__(cls, channel, target_path, recorded_path):
if cls._instance: if cls._instance:
cls._instance.channel = channel cls._instance.channel = channel
cls._instance.target_path = target_path cls._instance.target_path = target_path
cls._instance.recorded_path = recorded_path cls._instance.recorded_path = recorded_path
else: else:
cls._instance = super(Organizer, cls).__new__( cls, channel, cls._instance = super(Organizer, cls).__new__( cls, channel,
@ -27,8 +27,8 @@ class Organizer(ReportHandler,Loggable):
return cls._instance return cls._instance
def __init__(self, channel, target_path, recorded_path): def __init__(self, channel, target_path, recorded_path):
self.channel = channel self.channel = channel
self.target_path = target_path self.target_path = target_path
self.recorded_path = recorded_path self.recorded_path = recorded_path
super(Organizer, self).__init__(signal=self.channel, weak=False) super(Organizer, self).__init__(signal=self.channel, weak=False)

View File

@ -17,6 +17,9 @@ supported_extensions = [u"mp3", u"ogg", u"oga"]
#supported_extensions = [u"mp3", u"ogg", u"oga", u"flac", u"aac", u"bwf"] #supported_extensions = [u"mp3", u"ogg", u"oga", u"flac", u"aac", u"bwf"]
unicode_unknown = u'unknown' unicode_unknown = u'unknown'
path_md = ['MDATA_KEY_TITLE', 'MDATA_KEY_CREATOR', 'MDATA_KEY_SOURCE',
'MDATA_KEY_TRACKNUMBER', 'MDATA_KEY_BITRATE']
class LazyProperty(object): class LazyProperty(object):
""" """
meant to be used for lazy evaluation of an object attribute. meant to be used for lazy evaluation of an object attribute.
@ -59,7 +62,7 @@ def partition(f, alist):
Partition is very similar to filter except that it also returns the Partition is very similar to filter except that it also returns the
elements for which f return false but in a tuple. elements for which f return false but in a tuple.
>>> partition(lambda x : x > 3, [1,2,3,4,5,6]) >>> partition(lambda x : x > 3, [1,2,3,4,5,6])
[4,5,6],[1,2,3] ([4, 5, 6], [1, 2, 3])
""" """
return (filter(f, alist), filter(lambda x: not f(x), alist)) return (filter(f, alist), filter(lambda x: not f(x), alist))
@ -101,6 +104,8 @@ def extension(path):
I.e. interpreter won't enforce None checks on the programmer I.e. interpreter won't enforce None checks on the programmer
>>> extension("testing.php") >>> extension("testing.php")
'php' 'php'
>>> extension("a.b.c.d.php")
'php'
>>> extension('/no/extension') >>> extension('/no/extension')
'' ''
>>> extension('/path/extension.ml') >>> extension('/path/extension.ml')
@ -114,15 +119,17 @@ def no_extension_basename(path):
""" """
returns the extensionsless basename of a filepath returns the extensionsless basename of a filepath
>>> no_extension_basename("/home/test.mp3") >>> no_extension_basename("/home/test.mp3")
'test' u'test'
>>> no_extension_basename("/home/test") >>> no_extension_basename("/home/test")
'test' u'test'
>>> no_extension_basename('blah.ml') >>> no_extension_basename('blah.ml')
'blah' u'blah'
>>> no_extension_basename('a.b.c.d.mp3')
u'a.b.c.d'
""" """
base = unicode(os.path.basename(path)) base = unicode(os.path.basename(path))
if extension(base) == "": return base if extension(base) == "": return base
else: return base.split(".")[-2] else: return '.'.join(base.split(".")[0:-1])
def walk_supported(directory, clean_empties=False): def walk_supported(directory, clean_empties=False):
""" """
@ -163,15 +170,23 @@ def apply_rules_dict(d, rules):
if k in d: new_d[k] = rule(d[k]) if k in d: new_d[k] = rule(d[k])
return new_d return new_d
def default_to_f(dictionary, keys, default, condition):
new_d = copy.deepcopy(dictionary)
for k in keys:
if condition(dictionary=new_d, key=k): new_d[k] = default
return new_d
def default_to(dictionary, keys, default): def default_to(dictionary, keys, default):
""" """
Checks if the list of keys 'keys' exists in 'dictionary'. If not then it Checks if the list of keys 'keys' exists in 'dictionary'. If not then it
returns a new dictionary with all those missing keys defaults to 'default' returns a new dictionary with all those missing keys defaults to 'default'
""" """
new_d = copy.deepcopy(dictionary) cnd = lambda dictionary, key: key not in dictionary
for k in keys: return default_to_f(dictionary, keys, default, cnd)
if not (k in new_d): new_d[k] = default #new_d = copy.deepcopy(dictionary)
return new_d #for k in keys:
#if not (k in new_d): new_d[k] = default
#return new_d
def remove_whitespace(dictionary): def remove_whitespace(dictionary):
""" """
@ -192,16 +207,16 @@ def parse_int(s):
Tries very hard to get some sort of integer result from s. Defaults to 0 Tries very hard to get some sort of integer result from s. Defaults to 0
when it failes when it failes
>>> parse_int("123") >>> parse_int("123")
123 '123'
>>> parse_int("123saf") >>> parse_int("123saf")
123 '123'
>>> parse_int("asdf") >>> parse_int("asdf")
0 ''
""" """
if s.isdigit(): return s if s.isdigit(): return s
else: else:
try : return reduce(op.add, takewhile(lambda x: x.isdigit(), s)) try : return str(reduce(op.add, takewhile(lambda x: x.isdigit(), s)))
except: return 0 except: return ''
def normalized_metadata(md, original_path): def normalized_metadata(md, original_path):
""" """
@ -223,20 +238,18 @@ def normalized_metadata(md, original_path):
'MDATA_KEY_MIME' : lambda x: x.replace('-','/'), 'MDATA_KEY_MIME' : lambda x: x.replace('-','/'),
'MDATA_KEY_BPM' : lambda x: x[0:8], 'MDATA_KEY_BPM' : lambda x: x[0:8],
} }
path_md = ['MDATA_KEY_TITLE', 'MDATA_KEY_CREATOR', 'MDATA_KEY_SOURCE',
'MDATA_KEY_TRACKNUMBER', 'MDATA_KEY_BITRATE']
# note that we could have saved a bit of code by rewriting new_md using # note that we could have saved a bit of code by rewriting new_md using
# defaultdict(lambda x: "unknown"). But it seems to be too implicit and # defaultdict(lambda x: "unknown"). But it seems to be too implicit and
# could possibly lead to subtle bugs down the road. Plus the following # could possibly lead to subtle bugs down the road. Plus the following
# approach gives us the flexibility to use different defaults for different # approach gives us the flexibility to use different defaults for different
# attributes # attributes
new_md = remove_whitespace(new_md)
new_md = apply_rules_dict(new_md, format_rules) new_md = apply_rules_dict(new_md, format_rules)
new_md = default_to(dictionary=new_md, keys=['MDATA_KEY_TITLE'], new_md = default_to(dictionary=new_md, keys=['MDATA_KEY_TITLE'],
default=no_extension_basename(original_path)) default=no_extension_basename(original_path))
new_md = default_to(dictionary=new_md, keys=path_md, new_md = default_to(dictionary=new_md, keys=path_md, default=u'')
default=unicode_unknown)
new_md = default_to(dictionary=new_md, keys=['MDATA_KEY_FTYPE'], new_md = default_to(dictionary=new_md, keys=['MDATA_KEY_FTYPE'],
default=u'audioclip') default=u'audioclip')
# In the case where the creator is 'Airtime Show Recorder' we would like to # In the case where the creator is 'Airtime Show Recorder' we would like to
# format the MDATA_KEY_TITLE slightly differently # format the MDATA_KEY_TITLE slightly differently
# Note: I don't know why I'm doing a unicode string comparison here # Note: I don't know why I'm doing a unicode string comparison here
@ -251,13 +264,13 @@ def normalized_metadata(md, original_path):
# be set to the original path of the file for airtime recorded shows # be set to the original path of the file for airtime recorded shows
# (before it was "organized"). We will skip this procedure for now # (before it was "organized"). We will skip this procedure for now
# because it's not clear why it was done # because it's not clear why it was done
return remove_whitespace(new_md) return new_md
def organized_path(old_path, root_path, normal_md): def organized_path(old_path, root_path, orig_md):
""" """
old_path - path where file is store at the moment <= maybe not necessary? old_path - path where file is store at the moment <= maybe not necessary?
root_path - the parent directory where all organized files go root_path - the parent directory where all organized files go
normal_md - original meta data of the file as given by mutagen AFTER being orig_md - original meta data of the file as given by mutagen AFTER being
normalized normalized
return value: new file path return value: new file path
""" """
@ -265,6 +278,8 @@ def organized_path(old_path, root_path, normal_md):
ext = extension(old_path) ext = extension(old_path)
# The blocks for each if statement look awfully similar. Perhaps there is a # The blocks for each if statement look awfully similar. Perhaps there is a
# way to simplify this code # way to simplify this code
normal_md = default_to_f(orig_md, path_md, unicode_unknown,
lambda dictionary, key: len(dictionary[key]) == 0)
if is_airtime_recorded(normal_md): if is_airtime_recorded(normal_md):
fname = u'%s-%s-%s.%s' % ( normal_md['MDATA_KEY_YEAR'], fname = u'%s-%s-%s.%s' % ( normal_md['MDATA_KEY_YEAR'],
normal_md['MDATA_KEY_TITLE'], normal_md['MDATA_KEY_TITLE'],
@ -321,8 +336,7 @@ def get_system_locale(locale_path='/etc/default/locale'):
try: try:
config = ConfigObj(locale_path) config = ConfigObj(locale_path)
return config return config
except Exception as e: except Exception as e: raise FailedToSetLocale(locale_path,cause=e)
raise FailedToSetLocale(locale_path,cause=e)
else: raise ValueError("locale path '%s' does not exist. \ else: raise ValueError("locale path '%s' does not exist. \
permissions issue?" % locale_path) permissions issue?" % locale_path)
@ -336,8 +350,7 @@ def configure_locale(config):
if default_locale[1] is None: if default_locale[1] is None:
lang = config.get('LANG') lang = config.get('LANG')
new_locale = lang new_locale = lang
else: else: new_locale = default_locale
new_locale = default_locale
locale.setlocale(locale.LC_ALL, new_locale) locale.setlocale(locale.LC_ALL, new_locale)
reload(sys) reload(sys)
sys.setdefaultencoding("UTF-8") sys.setdefaultencoding("UTF-8")
@ -394,7 +407,7 @@ def sub_path(directory,f):
the paths. the paths.
""" """
normalized = normpath(directory) normalized = normpath(directory)
common = os.path.commonprefix([ directory, normpath(f) ]) common = os.path.commonprefix([ normalized, normpath(f) ])
return common == normalized return common == normalized
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -2,7 +2,6 @@
import threading import threading
import time import time
import copy import copy
import traceback
from media.monitor.handler import ReportHandler from media.monitor.handler import ReportHandler
from media.monitor.log import Loggable from media.monitor.log import Loggable
@ -47,9 +46,7 @@ class RequestSync(threading.Thread,Loggable):
except BadSongFile as e: except BadSongFile as e:
self.logger.info("This should never occur anymore!!!") self.logger.info("This should never occur anymore!!!")
self.logger.info("Bad song file: '%s'" % e.path) self.logger.info("Bad song file: '%s'" % e.path)
except Exception as e: except Exception as e: self.unexpected_exception( e )
self.logger.info("An evil exception occured")
self.logger.error( traceback.format_exc() )
def make_req(): def make_req():
self.apiclient.send_media_monitor_requests( packed_requests ) self.apiclient.send_media_monitor_requests( packed_requests )
for try_index in range(0,self.retries): for try_index in range(0,self.retries):
@ -102,16 +99,14 @@ class TimeoutWatcher(threading.Thread,Loggable):
class WatchSyncer(ReportHandler,Loggable): class WatchSyncer(ReportHandler,Loggable):
def __init__(self, signal, chunking_number = 100, timeout=15): def __init__(self, signal, chunking_number = 100, timeout=15):
self.timeout = float(timeout) self.timeout = float(timeout)
self.chunking_number = int(chunking_number) self.chunking_number = int(chunking_number)
self.__reset_queue() self.request_running = False
# Even though we are not blocking on the http requests, we are still
# trying to send the http requests in order
self.__requests = []
self.request_running = False
# we don't actually use this "private" instance variable anywhere
self.__current_thread = None self.__current_thread = None
self.contractor = EventContractor() self.__requests = []
self.contractor = EventContractor()
self.__reset_queue()
tc = TimeoutWatcher(self, self.timeout) tc = TimeoutWatcher(self, self.timeout)
tc.daemon = True tc.daemon = True
tc.start() tc.start()

View File

@ -122,6 +122,8 @@ def main(global_config, api_client_config, log_config,
# Launch the toucher that updates the last time when the script was # Launch the toucher that updates the last time when the script was
# ran every n seconds. # ran every n seconds.
# TODO : verify that this does not interfere with bootstrapping because the
# toucher thread might update the last_ran variable too fast
tt = ToucherThread(path=config['index_path'], tt = ToucherThread(path=config['index_path'],
interval=int(config['touch_interval'])) interval=int(config['touch_interval']))

View File

@ -60,4 +60,16 @@ class TestMMP(unittest.TestCase):
self.assertRaises( ValueError, lambda : mmp.file_md5('/bull/shit/path') ) self.assertRaises( ValueError, lambda : mmp.file_md5('/bull/shit/path') )
self.assertTrue( m1 == mmp.file_md5(p) ) self.assertTrue( m1 == mmp.file_md5(p) )
def test_sub_path(self):
f1 = "/home/testing/123.mp3"
d1 = "/home/testing"
d2 = "/home/testing/"
self.assertTrue( mmp.sub_path(d1, f1) )
self.assertTrue( mmp.sub_path(d2, f1) )
def test_parse_int(self):
self.assertEqual( mmp.parse_int("123"), "123" )
self.assertEqual( mmp.parse_int("123asf"), "123" )
self.assertEqual( mmp.parse_int("asdf"), "" )
if __name__ == '__main__': unittest.main() if __name__ == '__main__': unittest.main()

View File

@ -1,11 +1,15 @@
def notify(m) def notify(m)
log("/usr/lib/airtime/pypo/bin/liquidsoap_scripts/notify.sh --data='#{!pypo_data}' --media-id=#{m['schedule_table_id']} &") current_media_id := string_of(m['schedule_table_id'])
system("/usr/lib/airtime/pypo/bin/liquidsoap_scripts/notify.sh --data='#{!pypo_data}' --media-id=#{m['schedule_table_id']} &") command = "/usr/lib/airtime/pypo/bin/liquidsoap_scripts/notify.sh --data='#{!pypo_data}' --media-id=#{m['schedule_table_id']} &"
log(command)
system(command)
end end
def notify_stream(m) def notify_stream(m)
log("/usr/lib/airtime/pypo/bin/liquidsoap_scripts/notify.sh --stream --uri=#{base64.encode(m['uri'])} --title=#{base64.encode(m['title'])} &") json_str = string.replace(pattern="\n",(fun (s) -> ""), json_of(m))
#system("/usr/lib/airtime/pypo/bin/liquidsoap_scripts/notify.sh --stream --uri=#{base64.encode(m['uri'])} --title=#{base64.encode(m['title'])} &") command = "/usr/lib/airtime/pypo/bin/liquidsoap_scripts/notify.sh --webstream='#{json_str}' --media-id=#{!current_media_id} &"
log(command)
system(command)
end end
# A function applied to each metadata chunk # A function applied to each metadata chunk

View File

@ -27,6 +27,7 @@ stream_metadata_type = ref 0
default_dj_fade = ref 0. default_dj_fade = ref 0.
station_name = ref '' station_name = ref ''
show_name = ref '' show_name = ref ''
current_media_id = ref ''
s1_connected = ref '' s1_connected = ref ''
s2_connected = ref '' s2_connected = ref ''

View File

@ -6,10 +6,10 @@ Python part of radio playout (pypo)
This function acts as a gateway between liquidsoap and the server API. This function acts as a gateway between liquidsoap and the server API.
Mainly used to tell the platform what pypo/liquidsoap does. Mainly used to tell the platform what pypo/liquidsoap does.
Main case: Main case:
- whenever LS starts playing a new track, its on_metadata callback calls - whenever LS starts playing a new track, its on_metadata callback calls
a function in ls (notify(m)) which then calls the python script here a function in ls (notify(m)) which then calls the python script here
with the currently starting filename as parameter with the currently starting filename as parameter
- this python script takes this parameter, tries to extract the actual - this python script takes this parameter, tries to extract the actual
media id from it, and then calls back to the API to tell about it about it. media id from it, and then calls back to the API to tell about it about it.
@ -33,14 +33,15 @@ usage = "%prog [options]" + " - notification gateway"
parser = OptionParser(usage=usage) parser = OptionParser(usage=usage)
# Options # Options
parser.add_option("-d", "--data", help="Pass JSON data from liquidsoap into this script.", metavar="data") parser.add_option("-d", "--data", help="Pass JSON data from Liquidsoap into this script.", metavar="data")
parser.add_option("-m", "--media-id", help="ID of the file that is currently playing.", metavar="media_id") parser.add_option("-m", "--media-id", help="ID of the file that is currently playing.", metavar="media_id")
parser.add_option("-e", "--error", action="store", dest="error", type="string", help="liquidsoap error msg.", metavar="error_msg") parser.add_option("-e", "--error", action="store", dest="error", type="string", help="Liquidsoap error msg.", metavar="error_msg")
parser.add_option("-s", "--stream-id", help="ID stream", metavar="stream_id") parser.add_option("-s", "--stream-id", help="ID stream", metavar="stream_id")
parser.add_option("-c", "--connect", help="liquidsoap connected", action="store_true", metavar="connect") parser.add_option("-c", "--connect", help="Liquidsoap connected", action="store_true", metavar="connect")
parser.add_option("-t", "--time", help="liquidsoap boot up time", action="store", dest="time", metavar="time", type="string") parser.add_option("-t", "--time", help="Liquidsoap boot up time", action="store", dest="time", metavar="time", type="string")
parser.add_option("-x", "--source-name", help="source connection name", metavar="source_name") parser.add_option("-x", "--source-name", help="source connection name", metavar="source_name")
parser.add_option("-y", "--source-status", help="source connection stauts", metavar="source_status") parser.add_option("-y", "--source-status", help="source connection status", metavar="source_status")
parser.add_option("-w", "--webstream", help="JSON metadata associated with webstream", metavar="json_data")
# parse options # parse options
(options, args) = parser.parse_args() (options, args) = parser.parse_args()
@ -97,6 +98,15 @@ class Notify:
response = self.api_client.notify_source_status(source_name, status) response = self.api_client.notify_source_status(source_name, status)
logger.debug("Response: " + json.dumps(response)) logger.debug("Response: " + json.dumps(response))
def notify_webstream_data(self, data, media_id):
logger = logging.getLogger("notify")
logger.debug('#################################################')
logger.debug('# Calling server to update webstream data #')
logger.debug('#################################################')
response = self.api_client.notify_webstream_data(data, media_id)
pass
if __name__ == '__main__': if __name__ == '__main__':
print print
print '#########################################' print '#########################################'
@ -124,6 +134,12 @@ if __name__ == '__main__':
n.notify_source_status(options.source_name, options.source_status) n.notify_source_status(options.source_name, options.source_status)
except Exception, e: except Exception, e:
print e print e
elif options.webstream:
try:
n = Notify()
n.notify_webstream_data(options.webstream, options.media_id)
except Exception, e:
print e
else: else:
if not options.data: if not options.data:
print "NOTICE: 'data' command-line argument not given." print "NOTICE: 'data' command-line argument not given."