diff --git a/airtime_mvc/application/models/Block.php b/airtime_mvc/application/models/Block.php
index d8f75fcb0..640389bbe 100644
--- a/airtime_mvc/application/models/Block.php
+++ b/airtime_mvc/application/models/Block.php
@@ -1148,7 +1148,7 @@ EOT;
// e.g 192kps is stored as 192000
$spCriteriaValue = $criteria['value']*1000;
} else {
- $spCriteriaValue = $criteria['value'];
+ $spCriteriaValue = addslashes($criteria['value']);
}
if ($spCriteriaModifier == "starts with") {
@@ -1158,15 +1158,15 @@ EOT;
} else if ($spCriteriaModifier == "contains" || $spCriteriaModifier == "does not contain") {
$spCriteriaValue = "%$spCriteriaValue%";
} 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];
try{
if ($i > 0) {
- $qry->addOr($spCriteria, addslashes($spCriteriaValue), $spCriteriaModifier);
+ $qry->addOr($spCriteria, $spCriteriaValue, $spCriteriaModifier);
} else {
- $qry->add($spCriteria, addslashes($spCriteriaValue), $spCriteriaModifier);
+ $qry->add($spCriteria, $spCriteriaValue, $spCriteriaModifier);
}
}catch (Exception $e){
Logging::log($e);
diff --git a/airtime_mvc/application/models/Schedule.php b/airtime_mvc/application/models/Schedule.php
index 863417751..f7f518f4c 100644
--- a/airtime_mvc/application/models/Schedule.php
+++ b/airtime_mvc/application/models/Schedule.php
@@ -698,6 +698,23 @@ SQL;
);
if ($type == "stream") {
+ //create an event to start stream buffering 5 seconds ahead of the streams actual time.
+ $buffer_start = new DateTime($item["start"], new DateTimeZone('UTC'));
+ $buffer_start->sub(new DateInterval("PT5S"));
+
+ $stream_buffer_start = Application_Model_Schedule::AirtimeTimeToPypoTime($buffer_start->format("Y-m-d H:i:s"));
+
+ //TODO: Make sure no other media is being overwritten!
+ $data["media"][$stream_buffer_start] = array(
+ 'start' => $stream_buffer_start,
+ 'end' => $stream_buffer_start,
+ 'uri' => $uri,
+ 'row_id' => $item["id"],
+ 'type' => 'stream_buffer_start',
+ 'independent_event' => true
+ );
+
+
//since a stream never ends we have to insert an additional "kick stream" event. The "start"
//time of this event is the "end" time of the stream minus 1 second.
$dt = new DateTime($item["end"], new DateTimeZone('UTC'));
@@ -920,7 +937,7 @@ SQL;
$hValue = trim(substr($data["add_show_duration"], 0, $hPos));
}
if ($mPos !== false) {
- $hPos = $hPos === FALSE ? 0 : $hPos+1;
+ $hPos = $hPos === false ? 0 : $hPos+1;
$mValue = trim(substr($data["add_show_duration"], $hPos, -1 ));
}
diff --git a/airtime_mvc/application/models/StoredFile.php b/airtime_mvc/application/models/StoredFile.php
index 144cfef73..d0194b54c 100644
--- a/airtime_mvc/application/models/StoredFile.php
+++ b/airtime_mvc/application/models/StoredFile.php
@@ -634,7 +634,7 @@ class Application_Model_StoredFile
$streamSelect[] = "EXTRACT(YEAR FROM utime)::varchar AS ".$key;
}
//need to cast certain data as ints for the union to search on.
- else if (in_array($key, array("track_number", "bit_rate", "sample_rate"))) {
+ else if (in_array($key, array("track_number", "bit_rate", "sample_rate", "bpm"))) {
$plSelect[] = "NULL::int AS ".$key;
$blSelect[] = "NULL::int AS ".$key;
$fileSelect[] = $key;
diff --git a/airtime_mvc/application/models/airtime/map/CcFilesTableMap.php b/airtime_mvc/application/models/airtime/map/CcFilesTableMap.php
index 99d2ab18d..0f0707722 100644
--- a/airtime_mvc/application/models/airtime/map/CcFilesTableMap.php
+++ b/airtime_mvc/application/models/airtime/map/CcFilesTableMap.php
@@ -64,7 +64,7 @@ class CcFilesTableMap extends TableMap {
$this->addColumn('TRACK_NUMBER', 'DbTrackNumber', 'INTEGER', false, null, null);
$this->addColumn('CHANNELS', 'DbChannels', 'INTEGER', false, null, null);
$this->addColumn('URL', 'DbUrl', 'VARCHAR', false, 1024, null);
- $this->addColumn('BPM', 'DbBpm', 'VARCHAR', false, 8, null);
+ $this->addColumn('BPM', 'DbBpm', 'INTEGER', false, null, null);
$this->addColumn('RATING', 'DbRating', 'VARCHAR', false, 8, null);
$this->addColumn('ENCODED_BY', 'DbEncodedBy', 'VARCHAR', false, 255, null);
$this->addColumn('DISC_NUMBER', 'DbDiscNumber', 'VARCHAR', false, 8, null);
diff --git a/airtime_mvc/application/models/airtime/om/BaseCcFiles.php b/airtime_mvc/application/models/airtime/om/BaseCcFiles.php
index 57228452f..3b8daf54f 100644
--- a/airtime_mvc/application/models/airtime/om/BaseCcFiles.php
+++ b/airtime_mvc/application/models/airtime/om/BaseCcFiles.php
@@ -189,7 +189,7 @@ abstract class BaseCcFiles extends BaseObject implements Persistent
/**
* The value for the bpm field.
- * @var string
+ * @var int
*/
protected $bpm;
@@ -814,7 +814,7 @@ abstract class BaseCcFiles extends BaseObject implements Persistent
/**
* Get the [bpm] column value.
*
- * @return string
+ * @return int
*/
public function getDbBpm()
{
@@ -1822,13 +1822,13 @@ abstract class BaseCcFiles extends BaseObject implements Persistent
/**
* Set the value of [bpm] column.
*
- * @param string $v new value
+ * @param int $v new value
* @return CcFiles The current object (for fluent API support)
*/
public function setDbBpm($v)
{
if ($v !== null) {
- $v = (string) $v;
+ $v = (int) $v;
}
if ($this->bpm !== $v) {
@@ -2678,7 +2678,7 @@ abstract class BaseCcFiles extends BaseObject implements Persistent
$this->track_number = ($row[$startcol + 23] !== null) ? (int) $row[$startcol + 23] : null;
$this->channels = ($row[$startcol + 24] !== null) ? (int) $row[$startcol + 24] : null;
$this->url = ($row[$startcol + 25] !== null) ? (string) $row[$startcol + 25] : null;
- $this->bpm = ($row[$startcol + 26] !== null) ? (string) $row[$startcol + 26] : null;
+ $this->bpm = ($row[$startcol + 26] !== null) ? (int) $row[$startcol + 26] : null;
$this->rating = ($row[$startcol + 27] !== null) ? (string) $row[$startcol + 27] : null;
$this->encoded_by = ($row[$startcol + 28] !== null) ? (string) $row[$startcol + 28] : null;
$this->disc_number = ($row[$startcol + 29] !== null) ? (string) $row[$startcol + 29] : null;
diff --git a/airtime_mvc/application/models/airtime/om/BaseCcFilesQuery.php b/airtime_mvc/application/models/airtime/om/BaseCcFilesQuery.php
index 42d2f42f2..1dce43d8d 100644
--- a/airtime_mvc/application/models/airtime/om/BaseCcFilesQuery.php
+++ b/airtime_mvc/application/models/airtime/om/BaseCcFilesQuery.php
@@ -191,7 +191,7 @@
* @method CcFiles findOneByDbTrackNumber(int $track_number) Return the first CcFiles filtered by the track_number column
* @method CcFiles findOneByDbChannels(int $channels) Return the first CcFiles filtered by the channels column
* @method CcFiles findOneByDbUrl(string $url) Return the first CcFiles filtered by the url column
- * @method CcFiles findOneByDbBpm(string $bpm) Return the first CcFiles filtered by the bpm column
+ * @method CcFiles findOneByDbBpm(int $bpm) Return the first CcFiles filtered by the bpm column
* @method CcFiles findOneByDbRating(string $rating) Return the first CcFiles filtered by the rating column
* @method CcFiles findOneByDbEncodedBy(string $encoded_by) Return the first CcFiles filtered by the encoded_by column
* @method CcFiles findOneByDbDiscNumber(string $disc_number) Return the first CcFiles filtered by the disc_number column
@@ -255,7 +255,7 @@
* @method array findByDbTrackNumber(int $track_number) Return CcFiles objects filtered by the track_number column
* @method array findByDbChannels(int $channels) Return CcFiles objects filtered by the channels column
* @method array findByDbUrl(string $url) Return CcFiles objects filtered by the url column
- * @method array findByDbBpm(string $bpm) Return CcFiles objects filtered by the bpm column
+ * @method array findByDbBpm(int $bpm) Return CcFiles objects filtered by the bpm column
* @method array findByDbRating(string $rating) Return CcFiles objects filtered by the rating column
* @method array findByDbEncodedBy(string $encoded_by) Return CcFiles objects filtered by the encoded_by column
* @method array findByDbDiscNumber(string $disc_number) Return CcFiles objects filtered by the disc_number column
@@ -1061,20 +1061,29 @@ abstract class BaseCcFilesQuery extends ModelCriteria
/**
* Filter the query on the bpm column
*
- * @param string $dbBpm The value to use as filter.
- * Accepts wildcards (* and % trigger a LIKE)
+ * @param int|array $dbBpm The value to use as filter.
+ * Accepts an associative array('min' => $minValue, 'max' => $maxValue)
* @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL
*
* @return CcFilesQuery The current query, for fluid interface
*/
public function filterByDbBpm($dbBpm = null, $comparison = null)
{
- if (null === $comparison) {
- if (is_array($dbBpm)) {
+ if (is_array($dbBpm)) {
+ $useMinMax = false;
+ if (isset($dbBpm['min'])) {
+ $this->addUsingAlias(CcFilesPeer::BPM, $dbBpm['min'], Criteria::GREATER_EQUAL);
+ $useMinMax = true;
+ }
+ if (isset($dbBpm['max'])) {
+ $this->addUsingAlias(CcFilesPeer::BPM, $dbBpm['max'], Criteria::LESS_EQUAL);
+ $useMinMax = true;
+ }
+ if ($useMinMax) {
+ return $this;
+ }
+ if (null === $comparison) {
$comparison = Criteria::IN;
- } elseif (preg_match('/[\%\*]/', $dbBpm)) {
- $dbBpm = str_replace('*', '%', $dbBpm);
- $comparison = Criteria::LIKE;
}
}
return $this->addUsingAlias(CcFilesPeer::BPM, $dbBpm, $comparison);
diff --git a/airtime_mvc/build/schema.xml b/airtime_mvc/build/schema.xml
index 6486208ed..6a81f5ae4 100644
--- a/airtime_mvc/build/schema.xml
+++ b/airtime_mvc/build/schema.xml
@@ -38,7 +38,7 @@
-
+
diff --git a/airtime_mvc/build/sql/schema.sql b/airtime_mvc/build/sql/schema.sql
index 421b4cff4..2fb1bd978 100644
--- a/airtime_mvc/build/sql/schema.sql
+++ b/airtime_mvc/build/sql/schema.sql
@@ -56,7 +56,7 @@ CREATE TABLE "cc_files"
"track_number" INTEGER,
"channels" INTEGER,
"url" VARCHAR(1024),
- "bpm" VARCHAR(8),
+ "bpm" INTEGER,
"rating" VARCHAR(8),
"encoded_by" VARCHAR(255),
"disc_number" VARCHAR(8),
diff --git a/python_apps/pypo/liquidsoap_scripts/ls_lib.liq b/python_apps/pypo/liquidsoap_scripts/ls_lib.liq
index ed5085e12..172ba77b1 100644
--- a/python_apps/pypo/liquidsoap_scripts/ls_lib.liq
+++ b/python_apps/pypo/liquidsoap_scripts/ls_lib.liq
@@ -1,5 +1,5 @@
def notify(m)
- current_media_id := string_of(m['schedule_table_id'])
+ #current_media_id := string_of(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)
@@ -7,7 +7,7 @@ end
def notify_stream(m)
json_str = string.replace(pattern="\n",(fun (s) -> ""), json_of(m))
- command = "/usr/lib/airtime/pypo/bin/liquidsoap_scripts/notify.sh --webstream='#{json_str}' --media-id=#{!current_media_id} &"
+ command = "/usr/lib/airtime/pypo/bin/liquidsoap_scripts/notify.sh --webstream='#{json_str}' --media-id=#{!current_dyn_id} &"
log(command)
system(command)
end
@@ -253,7 +253,7 @@ end
# Function to create a playlist source and output it.
def create_dynamic_source(uri) =
# The playlist source
- s = input.http(uri)
+ s = input.http(buffer=2., max=12., uri)
# The output
active_dyn_out = dyn_out(s)
diff --git a/python_apps/pypo/liquidsoap_scripts/ls_script.liq b/python_apps/pypo/liquidsoap_scripts/ls_script.liq
index 540bd29fa..ddc7ae1a1 100644
--- a/python_apps/pypo/liquidsoap_scripts/ls_script.liq
+++ b/python_apps/pypo/liquidsoap_scripts/ls_script.liq
@@ -8,9 +8,9 @@ set("server.telnet.port", 1234)
#Dynamic source list
dyn_sources = ref []
+webstream_enabled = ref false
time = ref string_of(gettimeofday())
-
queue = audio_to_stereo(id="queue_src", request.equeue(id="queue", length=0.5))
queue = cue_cut(queue)
queue = amplify(1., override="replay_gain", queue)
@@ -27,7 +27,7 @@ stream_metadata_type = ref 0
default_dj_fade = ref 0.
station_name = ref ''
show_name = ref ''
-current_media_id = ref ''
+#current_media_id = ref ''
s1_connected = ref ''
s2_connected = ref ''
@@ -39,7 +39,7 @@ just_switched = ref false
%include "ls_lib.liq"
-web_stream = input.harbor("test-harbor",port=8999,password="hackme")
+web_stream = mksafe(input.harbor("test-harbor", port=8999, password="hackme"))
web_stream = on_metadata(notify_stream, web_stream)
queue = on_metadata(notify, queue)
@@ -47,16 +47,43 @@ queue = map_metadata(append_title, queue)
# the crossfade function controls fade in/out
queue = crossfade(queue)
-queue = fallback([web_stream, queue])
+queue = switch(id="stream_queue_switch", track_sensitive=false, [({!webstream_enabled},web_stream), ({true}, queue)])
+
ignore(output.dummy(queue, fallible=true))
-server.register(namespace="vars", "pypo_data", fun (s) -> begin pypo_data := s "Done" end)
-server.register(namespace="vars", "stream_metadata_type", fun (s) -> begin stream_metadata_type := int_of_string(s) s end)
-server.register(namespace="vars", "show_name", fun (s) -> begin show_name := s s end)
-server.register(namespace="vars", "station_name", fun (s) -> begin station_name := s s end)
-server.register(namespace="vars", "bootup_time", fun (s) -> begin time := s s end)
-server.register(namespace="streams", "connection_status", fun (s) -> begin "1:#{!s1_connected},2:#{!s2_connected},3:#{!s3_connected}" end)
-server.register(namespace="vars", "default_dj_fade", fun (s) -> begin default_dj_fade := float_of_string(s) s end)
+server.register(namespace="vars",
+ "pypo_data",
+ fun (s) -> begin pypo_data := s "Done" end)
+server.register(namespace="vars",
+ "stream_metadata_type",
+ fun (s) -> begin stream_metadata_type := int_of_string(s) s end)
+server.register(namespace="vars",
+ "show_name",
+ fun (s) -> begin show_name := s s end)
+server.register(namespace="vars",
+ "station_name",
+ fun (s) -> begin station_name := s s end)
+server.register(namespace="vars",
+ "bootup_time",
+ fun (s) -> begin time := s s end)
+server.register(namespace="streams",
+ "connection_status",
+ fun (s) -> begin "1:#{!s1_connected},2:#{!s2_connected},3:#{!s3_connected}" end)
+server.register(namespace="vars",
+ "default_dj_fade",
+ fun (s) -> begin default_dj_fade := float_of_string(s) s end)
+
+server.register(namespace="dynamic_source",
+ description="Enable webstream output",
+ usage='start',
+ "output_start",
+ fun (s) -> begin webstream_enabled := true "enabled" end)
+server.register(namespace="dynamic_source",
+ description="Enable webstream output",
+ usage='stop',
+ "output_stop",
+ fun (s) -> begin webstream_enabled := false "disabled" end)
+
server.register(namespace="dynamic_source",
description="Set the cc_schedule row id",
usage="id ",
@@ -65,12 +92,12 @@ server.register(namespace="dynamic_source",
server.register(namespace="dynamic_source",
description="Start a new dynamic source.",
usage="start ",
- "start",
+ "read_start",
create_dynamic_source)
server.register(namespace="dynamic_source",
description="Stop a dynamic source.",
usage="stop ",
- "stop",
+ "read_stop",
destroy_dynamic_source)
default = amplify(id="silence_src", 0.00001, noise())
diff --git a/python_apps/pypo/pypopush.py b/python_apps/pypo/pypopush.py
index 09dd7de37..b04c60d82 100644
--- a/python_apps/pypo/pypopush.py
+++ b/python_apps/pypo/pypopush.py
@@ -386,31 +386,46 @@ class PypoPush(Thread):
PypoFetch.disconnect_source(self.logger, self.telnet_lock, "live_dj")
elif media_item['event_type'] == "switch_off":
PypoFetch.switch_source(self.logger, self.telnet_lock, "live_dj", "off")
+ elif media_item['type'] == 'stream_buffer_start':
+ self.start_web_stream_buffer(media_item)
elif media_item['type'] == "stream":
- """
- Source is a stream that we need to being downloading to a file. Then we may simply
- point Liquidsoap to play this file.
- """
self.start_web_stream(media_item)
elif media_item['type'] == "stream_end":
self.stop_web_stream(media_item)
except Exception, e:
self.logger.error('Pypo Push Exception: %s', e)
+ def start_web_stream_buffer(self, media_item):
+ try:
+ self.telnet_lock.acquire()
+ tn = telnetlib.Telnet(LS_HOST, LS_PORT)
+
+ msg = 'dynamic_source.id %s\n' % media_item['row_id']
+ tn.write(msg)
+
+ #example: dynamic_source.read_start http://87.230.101.24:80/top100station.mp3
+ msg = 'dynamic_source.read_start %s\n' % media_item['uri'].encode('latin-1')
+ self.logger.debug(msg)
+ tn.write(msg)
+
+ tn.write("exit\n")
+ self.logger.debug(tn.read_all())
+ except Exception, e:
+ self.logger.error(str(e))
+ finally:
+ self.telnet_lock.release()
+
+
def start_web_stream(self, media_item):
try:
self.telnet_lock.acquire()
tn = telnetlib.Telnet(LS_HOST, LS_PORT)
- #dynamic_source.start http://87.230.101.24:80/top100station.mp3
-
- msg = 'dynamic_source.id %s\n' % media_item['row_id']
- tn.write(msg)
#TODO: DO we need this?
msg = 'streams.scheduled_play_start\n'
tn.write(msg)
- msg = 'dynamic_source.start %s\n' % media_item['uri'].encode('latin-1')
+ msg = 'dynamic_source.output_start\n'
self.logger.debug(msg)
tn.write(msg)
@@ -429,7 +444,11 @@ class PypoPush(Thread):
tn = telnetlib.Telnet(LS_HOST, LS_PORT)
#dynamic_source.stop http://87.230.101.24:80/top100station.mp3
- msg = 'dynamic_source.stop %s\n' % media_item['uri'].encode('latin-1')
+ msg = 'dynamic_source.read_stop %s\n' % media_item['uri'].encode('latin-1')
+ self.logger.debug(msg)
+ tn.write(msg)
+
+ msg = 'dynamic_source.output_stop\n'
self.logger.debug(msg)
tn.write(msg)