1
0
Fork 0
mirror of https://github.com/Yetangitu/ampache synced 2025-10-06 03:49:56 +02:00

Working Broadcast feature

This commit is contained in:
Afterster 2014-02-09 23:00:50 +01:00
parent 916057fda7
commit 6cdb33ae32
19 changed files with 333 additions and 131 deletions

View file

@ -50,7 +50,9 @@ if ($cargv > 1) {
} }
$app = new Ratchet\App('localhost', $port); $app = new Ratchet\App('localhost', $port);
$app->route('/broadcast', new Broadcast_Server()); $brserver = new Broadcast_Server();
$brserver->verbose = $verbose;
$app->route('/broadcast', $brserver);
$app->route('/echo', new Ratchet\Server\EchoServer, array('*')); $app->route('/echo', new Ratchet\Server\EchoServer, array('*'));
$app->run(); $app->run();

View file

@ -7,12 +7,18 @@
; if this config file is up to date ; if this config file is up to date
; this is compared against a value hard-coded ; this is compared against a value hard-coded
; into the init script ; into the init script
config_version = 13 config_version = 14
;################### ;###################
; Path Vars # ; Path Vars #
;################### ;###################
; The http host of your server.
; If not set, retrieved automatically from client request.
; This setting is required for WebSocket server
; DEFAULT: ""
;http_host = "localhost"
; The path to your ampache install ; The path to your ampache install
; Do not put a trailing / on this path ; Do not put a trailing / on this path
; For example if your site is located at http://localhost ; For example if your site is located at http://localhost

View file

@ -42,10 +42,10 @@ class Broadcast extends database_object
public function update_state($started, $key='') public function update_state($started, $key='')
{ {
$sql = "UPDATE `broadcast` SET `started` = ?, `key` = ? `song` = '0', `song_position` = '0', `listeners` = '0' WHERE `id` = ?"; $sql = "UPDATE `broadcast` SET `started` = ?, `key` = ?, `song` = '0', `listeners` = '0' WHERE `id` = ?";
Dba::write($sql, array($started, $key, $this->id)); Dba::write($sql, array($started, $key, $this->id));
$this->started = $start_date; $this->started = $started;
} }
public function update_listeners($listeners) public function update_listeners($listeners)
@ -56,6 +56,15 @@ class Broadcast extends database_object
$this->listeners = $listeners; $this->listeners = $listeners;
} }
public function update_song($song_id)
{
$sql = "UPDATE `broadcast` SET `song` = ? " .
"WHERE `id` = ?";
Dba::write($sql, array($song_id, $this->id));
$this->song = $song_id;
$this->song_position = 0;
}
public function delete() public function delete()
{ {
$sql = "DELETE FROM `broadcast` WHERE `id` = ?"; $sql = "DELETE FROM `broadcast` WHERE `id` = ?";
@ -65,7 +74,7 @@ class Broadcast extends database_object
public static function create($name, $description='') public static function create($name, $description='')
{ {
if (!empty($name)) { if (!empty($name)) {
$sql = "INSERT INTO `broadcast` (`user`, `name`, `description`) VALUES (?, ?, ?)"; $sql = "INSERT INTO `broadcast` (`user`, `name`, `description`, `is_private`) VALUES (?, ?, ?, '1')";
$params = array($GLOBALS['user']->id, $name, $description); $params = array($GLOBALS['user']->id, $name, $description);
Dba::write($sql, $params); Dba::write($sql, $params);
return Dba::insert_id(); return Dba::insert_id();
@ -77,12 +86,12 @@ class Broadcast extends database_object
public function update($data) public function update($data)
{ {
if (isset($data['edit_tags'])) { if (isset($data['edit_tags'])) {
Tag::update_tag_list($data['edit_tags'], 'channel', $this->id); Tag::update_tag_list($data['edit_tags'], 'broadcast', $this->id);
} }
$sql = "UPDATE `broadcast` SET `name` = ?, `description` = ? " . $sql = "UPDATE `broadcast` SET `name` = ?, `description` = ?, `is_private` = ? " .
"WHERE `id` = ?"; "WHERE `id` = ?";
$params = array($data['name'], $data['description'], $this->id); $params = array($data['name'], $data['description'], !empty($data['private']), $this->id);
return Dba::write($sql, $params); return Dba::write($sql, $params);
} }
@ -90,7 +99,7 @@ class Broadcast extends database_object
{ {
$this->f_name = $this->name; $this->f_name = $this->name;
$this->f_link = '<a href="' . AmpConfig::get('web_path') . '/broadcast.php?id=' . $this->id . '">' . scrub_out($this->f_name) . '</a>'; $this->f_link = '<a href="' . AmpConfig::get('web_path') . '/broadcast.php?id=' . $this->id . '">' . scrub_out($this->f_name) . '</a>';
$this->tags = Tag::get_top_tags('broadcast',$this->id); $this->tags = Tag::get_top_tags('broadcast', $this->id);
$this->f_tags = Tag::get_display($this->tags, $this->id, 'broadcast'); $this->f_tags = Tag::get_display($this->tags, $this->id, 'broadcast');
} }
@ -125,7 +134,7 @@ class Broadcast extends database_object
$sql = "SELECT `id` FROM `broadcast` WHERE `key` = ?"; $sql = "SELECT `id` FROM `broadcast` WHERE `key` = ?";
$db_results = Dba::read($sql, array($key)); $db_results = Dba::read($sql, array($key));
if ($results = Dba::featch_assoc($db_results)) { if ($results = Dba::fetch_assoc($db_results)) {
return new Broadcast($results['id']); return new Broadcast($results['id']);
} }
@ -171,4 +180,9 @@ class Broadcast extends database_object
return $broadcasts; return $broadcasts;
} }
public static function play_url($oid, $additional_params='')
{
return $oid;
}
} // end of broadcast class } // end of broadcast class

View file

@ -33,58 +33,100 @@ class Broadcast_Server implements MessageComponentInterface
const BROADCAST_ENDED = "ENDED"; const BROADCAST_ENDED = "ENDED";
const BROADCAST_INFO = "INFO"; const BROADCAST_INFO = "INFO";
const BROADCAST_NB_LISTENERS = "NB_LISTENERS"; const BROADCAST_NB_LISTENERS = "NB_LISTENERS";
const BROADCAST_AUTH_SID = "AUTH_SID";
public $verbose;
protected $clients; protected $clients;
protected $sids;
protected $listeners; protected $listeners;
protected $broadcasters; protected $broadcasters;
public function __construct() public function __construct()
{ {
$this->clients = new \SplObjectStorage; $this->verbose = false;
$this->clients = array();
$this->sids = array();
$this->listeners = array();
$this->broadcasters = array();
} }
public function onOpen(ConnectionInterface $conn) public function onOpen(ConnectionInterface $conn)
{ {
$this->clients->attach($conn); $this->clients[$conn->resourceId] = $conn;
} }
public function onMessage(ConnectionInterface $from, $msg) public function onMessage(ConnectionInterface $from, $msg)
{ {
$commands = explode(';', $msg); $commands = explode(';', $msg);
foreach ($commands as $command) { foreach ($commands as $command) {
$cmdinfo = explode('=', $msg, 2); $command = trim($command);
if (!empty($command)) {
$cmdinfo = explode(':', $command, 2);
if (count($cmdinfo) == 2) { if (count($cmdinfo) == 2) {
switch ($cmdinfo[0]) { switch ($cmdinfo[0]) {
case self::BROADCAST_SONG: case self::BROADCAST_SONG:
$this->notifySong($from, $cmdinfo[1]); $this->notifySong($from, $cmdinfo[1]);
break; break;
case self::BROADCAST_SONG_POSITION: case self::BROADCAST_SONG_POSITION:
$this->notifySongPosition($from, $cmdinfo[1]); $this->notifySongPosition($from, $cmdinfo[1]);
break; break;
case self::BROADCAST_PLAYER_PLAY: case self::BROADCAST_PLAYER_PLAY:
$this->notifyPlayerPlay($from, $cmdinfo[1]); $this->notifyPlayerPlay($from, $cmdinfo[1]);
break; break;
case self::BROADCAST_ENDED: case self::BROADCAST_ENDED:
$this->notifyEnded($from); $this->notifyEnded($from);
break; break;
case self::BROADCAST_REGISTER_BROADCAST: case self::BROADCAST_REGISTER_BROADCAST:
$this->registerBroadcast($from, $cmdinfo[1]); $this->registerBroadcast($from, $cmdinfo[1]);
break; break;
case self::BROADCAST_REGISTER_LISTENER: case self::BROADCAST_REGISTER_LISTENER:
$this->registerListener($from, $cmdinfo[1]); $this->registerListener($from, $cmdinfo[1]);
break; break;
case self::BROADCAST_AUTH_SID:
$this->authSid($from, $cmdinfo[1]);
break;
default:
if ($this->verbose) {
echo "[" . time() ."][warning]Unknown message code." . "\r\n";
}
break;
}
} else {
if ($this->verbose) {
echo "[" . time() ."][error]Wrong message format (" . $command . ")." . "\r\n";
}
} }
} }
} }
} }
protected function getSongJS($song_id)
{
$media = array();
$media[] = array(
'object_type' => 'song',
'object_id' => $song_id
);
$item = Stream_Playlist::media_to_urlarray($media);
return WebPlayer::get_media_js_param($item[0]);
}
protected function notifySong($from, $song_id) protected function notifySong($from, $song_id)
{ {
if ($this->isBroadcaster($from)) { if ($this->isBroadcaster($from)) {
$broadcast = $broadcasters[$from]; $broadcast = $this->broadcasters[$from->resourceId];
$clients = $this->getListeners($broadcast); $clients = $this->getListeners($broadcast);
$this->broadcastMessage($clients, self::BROADCAST_SONG, $song_id);
Session::extend(Stream::$session, 'stream');
$broadcast->update_song($song_id);
$this->broadcastMessage($clients, self::BROADCAST_SONG, base64_encode($this->getSongJS($song_id)));
if ($this->verbose) {
echo "[" . time() ."][info]Broadcast " . $broadcast->id . " now playing song " . $song_id . "." . "\r\n";
}
} else { } else {
debug_event('broadcast', 'Action unauthorized.', '3'); debug_event('broadcast', 'Action unauthorized.', '3');
} }
@ -93,9 +135,17 @@ class Broadcast_Server implements MessageComponentInterface
protected function notifySongPosition($from, $song_position) protected function notifySongPosition($from, $song_position)
{ {
if ($this->isBroadcaster($from)) { if ($this->isBroadcaster($from)) {
$broadcast = $broadcasters[$from]; $broadcast = $this->broadcasters[$from->resourceId];
$clients = $this->getListeners($broadcast); $seekdiff = $broadcast->song_position - $song_position;
$this->broadcastMessage($clients, self::BROADCAST_SONG_POSITION, $song_position); if ($seekdiff > 2 || $seekdiff < -2) {
$clients = $this->getListeners($broadcast);
$this->broadcastMessage($clients, self::BROADCAST_SONG_POSITION, $song_position);
}
$broadcast->song_position = $song_position;
if ($this->verbose) {
echo "[" . time() ."][info]Broadcast " . $broadcast->id . " has song position to " . $song_position . "." . "\r\n";
}
} else { } else {
debug_event('broadcast', 'Action unauthorized.', '3'); debug_event('broadcast', 'Action unauthorized.', '3');
} }
@ -104,9 +154,13 @@ class Broadcast_Server implements MessageComponentInterface
protected function notifyPlayerPlay($from, $play) protected function notifyPlayerPlay($from, $play)
{ {
if ($this->isBroadcaster($from)) { if ($this->isBroadcaster($from)) {
$broadcast = $broadcasters[$from]; $broadcast = $this->broadcasters[$from->resourceId];
$clients = $this->getListeners($broadcast); $clients = $this->getListeners($broadcast);
$this->broadcastMessage($clients, self::BROADCAST_PLAYER_PLAY, $play); $this->broadcastMessage($clients, self::BROADCAST_PLAYER_PLAY, $play);
if ($this->verbose) {
echo "[" . time() ."][info]Broadcast " . $broadcast->id . " player state: " . $play . "." . "\r\n";
}
} else { } else {
debug_event('broadcast', 'Action unauthorized.', '3'); debug_event('broadcast', 'Action unauthorized.', '3');
} }
@ -116,28 +170,37 @@ class Broadcast_Server implements MessageComponentInterface
{ {
$broadcast = Broadcast::get_broadcast($broadcast_key); $broadcast = Broadcast::get_broadcast($broadcast_key);
if ($broadcast) { if ($broadcast) {
$broadcasters[$from] = $broadcast; $this->broadcasters[$from->resourceId] = $broadcast;
$listeners[$broadcast] = array(); $this->listeners[$broadcast->id] = array();
if ($this->verbose) {
echo "[info]Broadcast " . $broadcast->id . " registered." . "\r\n";
}
} }
} }
protected function unregisterBroadcast($conn) protected function unregisterBroadcast($conn)
{ {
$broadcast = $broadcasters[$conn]; $broadcast = $this->broadcasters[$conn->resourceId];
$clients = $this->getListeners($broadcast); $clients = $this->getListeners($broadcast);
$this->broadcastMessage($clients, self::BROADCAST_ENDED); $this->broadcastMessage($clients, self::BROADCAST_ENDED);
$broadcast->update_state(false);
unset($listeners[$broadcast]); unset($this->listeners[$broadcast->id]);
unset($broadcasters[$conn]); unset($this->broadcasters[$conn->resourceId]);
if ($this->verbose) {
echo "[" . time() ."][info]Broadcast " . $broadcast->id . " unregistered." . "\r\n";
}
} }
protected function getRunningBroadcast($broadcast_id) protected function getRunningBroadcast($broadcast_id)
{ {
$broadcast = null; $broadcast = null;
foreach ($broadcasters as $conn => $br) { foreach ($this->broadcasters as $conn_id => $br) {
if ($br->id == $broadcast_id) { if ($br->id == $broadcast_id) {
$broadcast = $br; $broadcast = $br;
exit; break;
} }
} }
return $broadcast; return $broadcast;
@ -145,16 +208,44 @@ class Broadcast_Server implements MessageComponentInterface
protected function registerListener($from, $broadcast_id) protected function registerListener($from, $broadcast_id)
{ {
$broadcast = $this->getRunningBroadcast(); $broadcast = $this->getRunningBroadcast($broadcast_id);
$listeners[$broadcast][] = $from;
if (!$broadcast->is_private || !AmpConfig::get('require_session') || Session::exists('stream', $this->sids[$from->resourceId])) {
$this->listeners[$broadcast->id][] = $from;
// Send current song and song position to
$this->broadcastMessage(array($from), self::BROADCAST_SONG, base64_encode($this->getSongJS($broadcast->song)));
$this->broadcastMessage(array($from), self::BROADCAST_SONG_POSITION, $broadcast->song_position);
$this->notifyNbListeners($broadcast);
if ($this->verbose) {
echo "[info]New listener on broadcast " . $broadcast->id . "." . "\r\n";
}
} else {
debug_event('broadcast', 'Listener unauthorized.', '3');
}
}
protected function authSid($conn, $sid)
{
} }
protected function unregisterListener($conn) protected function unregisterListener($conn)
{ {
foreach ($listeners as $broadcast => $brlisteners) { foreach ($this->listeners as $broadcast_id => $brlisteners) {
$lindex = array_search($brlisteners, $conn); $lindex = array_search($conn, $brlisteners);
if ($lindex) { if ($lindex) {
unset($brlisteners[$lindex]); unset($this->listeners[$broadcast_id][$lindex]);
echo "[info]Listener leaved broadcast " . $broadcast_id . "." . "\r\n";
foreach ($broadcasters as $broadcaster_id => $broadcast) {
if ($broadcast->id == $broadcast_id) {
$this->notifyNbListeners($broadcast);
break;
}
}
break; break;
} }
} }
@ -162,26 +253,34 @@ class Broadcast_Server implements MessageComponentInterface
protected function notifyNbListeners($broadcast) protected function notifyNbListeners($broadcast)
{ {
$broadcaster = array_search(broadcasters, $broadcast); $broadcaster_id = array_search($broadcast, $this->broadcasters);
$clients = $listeners[$broadcast]; if ($broadcaster_id) {
$clients[] = $broadcaster; $clients = $this->listeners[$broadcast->id];
$this->broadcastMessage($clients, self::BROADCAST_NB_LISTENERS, count($listeners[$broadcast])); $clients[] = $this->clients[$broadcaster_id];
$nb_listeners = count($this->listeners[$broadcast->id]);
$broadcast->update_listeners($nb_listeners);
$this->broadcastMessage($clients, self::BROADCAST_NB_LISTENERS, $nb_listeners);
}
} }
protected function getListeners($broadcast) protected function getListeners($broadcast)
{ {
return $listeners[$broadcast]; return $this->listeners[$broadcast->id];
} }
protected function isBroadcaster($conn) protected function isBroadcaster($conn)
{ {
return bool(array_search($conn, $broadcasters)); return array_key_exists($conn->resourceId, $this->broadcasters);
} }
protected function broadcastMessage($clients, $cmd, $value='') protected function broadcastMessage($clients, $cmd, $value='')
{ {
$msg = $cmd . '=' . $value . ';'; $msg = $cmd . ':' . $value . ';';
foreach ($clients as $client) { foreach ($clients as $client) {
$sid = $this->sids[$client->resourceId];
if ($sid) {
Session::extend($sid, 'stream');
}
$client->send($msg); $client->send($msg);
} }
} }
@ -194,7 +293,8 @@ class Broadcast_Server implements MessageComponentInterface
$this->unregisterListener($conn); $this->unregisterListener($conn);
} }
$this->clients->detach($conn); unset($this->clients[$conn->resourceId]);
unset($this->sids[$conn->resourceId]);
} }
public function onError(ConnectionInterface $conn, \Exception $e) public function onError(ConnectionInterface $conn, \Exception $e)

View file

@ -114,7 +114,7 @@ class Channel extends database_object
{ {
if (!empty($name)) { if (!empty($name)) {
$sql = "INSERT INTO `channel` (`name`, `description`, `url`, `object_type`, `object_id`, `interface`, `port`, `fixed_endpoint`, `admin_password`, `is_private`, `max_listeners`, `random`, `loop`, `stream_type`, `bitrate`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; $sql = "INSERT INTO `channel` (`name`, `description`, `url`, `object_type`, `object_id`, `interface`, `port`, `fixed_endpoint`, `admin_password`, `is_private`, `max_listeners`, `random`, `loop`, `stream_type`, `bitrate`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
$params = array($name, $description, $url, $object_type, $object_id, $interface, $port, (!empty($interface) && !empty($port)), $admin_password, $private, $max_listeners, $random, $loop, $stream_type, $bitrate); $params = array($name, $description, $url, $object_type, $object_id, $interface, $port, (!empty($interface) && !empty($port)), $admin_password, !empty($private), $max_listeners, $random, $loop, $stream_type, $bitrate);
return Dba::write($sql, $params); return Dba::write($sql, $params);
} }
@ -129,7 +129,7 @@ class Channel extends database_object
$sql = "UPDATE `channel` SET `name` = ?, `description` = ?, `url` = ?, `interface` = ?, `port` = ?, `fixed_endpoint` = ?, `admin_password` = ?, `is_private` = ?, `max_listeners` = ?, `random` = ?, `loop` = ?, `stream_type` = ?, `bitrate` = ? " . $sql = "UPDATE `channel` SET `name` = ?, `description` = ?, `url` = ?, `interface` = ?, `port` = ?, `fixed_endpoint` = ?, `admin_password` = ?, `is_private` = ?, `max_listeners` = ?, `random` = ?, `loop` = ?, `stream_type` = ?, `bitrate` = ? " .
"WHERE `id` = ?"; "WHERE `id` = ?";
$params = array($data['name'], $data['description'], $data['url'], $data['interface'], $data['port'], (!empty($data['interface']) && !empty($data['port'])), $data['admin_password'], $data['private'], $data['max_listeners'], $data['random'], $data['loop'], $data['stream_type'], $data['bitrate'], $this->id); $params = array($data['name'], $data['description'], $data['url'], $data['interface'], $data['port'], (!empty($data['interface']) && !empty($data['port'])), $data['admin_password'], !empty($data['private']), $data['max_listeners'], $data['random'], $data['loop'], $data['stream_type'], $data['bitrate'], $this->id);
return Dba::write($sql, $params); return Dba::write($sql, $params);
} }

View file

@ -360,7 +360,7 @@ class Stream
if (preg_match("/:(\d+)/",$web_path,$matches)) { if (preg_match("/:(\d+)/",$web_path,$matches)) {
$web_path = str_replace(':' . $matches['1'],':' . AmpConfig::get('http_port'),$web_path); $web_path = str_replace(':' . $matches['1'],':' . AmpConfig::get('http_port'),$web_path);
} else { } else {
$web_path = str_replace($_SERVER['HTTP_HOST'],$_SERVER['HTTP_HOST'] . ':' . AmpConfig::get('http_port'),$web_path); $web_path = str_replace(AmpConfig::get('http_host'), AmpConfig::get('http_host') . ':' . AmpConfig::get('http_port'), $web_path);
} }
} }

View file

@ -97,10 +97,10 @@ class Stream_Playlist
} }
/** /**
* _media_to_urlarray * media_to_urlarray
* Formats the URL and media information and adds it to the object * Formats the URL and media information and adds it to the object
*/ */
private static function _media_to_urlarray($media, $additional_params='') public static function media_to_urlarray($media, $additional_params='')
{ {
$urls = array(); $urls = array();
foreach ($media as $medium) { foreach ($media as $medium) {
@ -108,6 +108,7 @@ class Stream_Playlist
$url = array(); $url = array();
$type = $medium['object_type']; $type = $medium['object_type'];
//$url['object_id'] = $medium['object_id'];
$url['type'] = $type; $url['type'] = $type;
$object = new $type($medium['object_id']); $object = new $type($medium['object_id']);
@ -230,7 +231,7 @@ class Stream_Playlist
*/ */
public function add($media = array(), $additional_params = '') public function add($media = array(), $additional_params = '')
{ {
$urls = $this->_media_to_urlarray($media, $additional_params); $urls = $this->media_to_urlarray($media, $additional_params);
foreach ($urls as $url) { foreach ($urls as $url) {
$this->_add_url($url); $this->_add_url($url);
} }

View file

@ -643,7 +643,7 @@ class Tag extends database_object
*/ */
public static function validate_type($type) public static function validate_type($type)
{ {
$valid_array = array('song','artist','album','video','playlist','live_stream','channel'); $valid_array = array('song','artist','album','video','playlist','live_stream','channel','broadcast');
if (in_array($type,$valid_array)) { return $type; } if (in_array($type,$valid_array)) { return $type; }

View file

@ -2206,7 +2206,6 @@ class Update
"`description` varchar(256) CHARACTER SET utf8 NULL," . "`description` varchar(256) CHARACTER SET utf8 NULL," .
"`is_private` tinyint(1) unsigned NOT NULL DEFAULT '0'," . "`is_private` tinyint(1) unsigned NOT NULL DEFAULT '0'," .
"`song` int(11) unsigned NOT NULL DEFAULT '0'," . "`song` int(11) unsigned NOT NULL DEFAULT '0'," .
"`song_position` int(11) unsigned NOT NULL DEFAULT '0'," .
"`started` tinyint(1) unsigned NOT NULL DEFAULT '0'," . "`started` tinyint(1) unsigned NOT NULL DEFAULT '0'," .
"`listeners` int(11) unsigned NOT NULL DEFAULT '0'," . "`listeners` int(11) unsigned NOT NULL DEFAULT '0'," .
"`key` varchar(32) CHARACTER SET utf8 NULL," . "`key` varchar(32) CHARACTER SET utf8 NULL," .

View file

@ -62,7 +62,7 @@ class WebPlayer
} }
protected static function get_types($item) protected static function get_types($item, $force_type='')
{ {
$types = array('real' => 'mp3', 'player' => ''); $types = array('real' => 'mp3', 'player' => '');
@ -70,10 +70,15 @@ class WebPlayer
if (count($browsers) > 0 ) { if (count($browsers) > 0 ) {
$browser = $browsers[0]; $browser = $browsers[0];
} }
if ($browser == "msie" || $browser == "trident" || $browser == "webkit" || $browser == "safari") {
$types['real'] = "mp3"; if (!empty($force_type)) {
$types['real'] = $force_type;
} else { } else {
$types['real'] = "ogg"; if ($browser == "msie" || $browser == "trident" || $browser == "webkit" || $browser == "safari") {
$types['real'] = "mp3";
} else {
$types['real'] = "ogg";
}
} }
$song = null; $song = null;
@ -90,7 +95,7 @@ class WebPlayer
$transcode = false; $transcode = false;
$transcode_cfg = AmpConfig::get('transcode'); $transcode_cfg = AmpConfig::get('transcode');
// Check transcode is required // Check transcode is required
if ($transcode_cfg == 'always' || ($types['real'] != $ftype && !AmpConfig::get('webplayer_flash'))) { if ($transcode_cfg == 'always' || !empty($force_type) || ($types['real'] != $ftype && !AmpConfig::get('webplayer_flash'))) {
$valid_types = Song::get_stream_types_for_type($ftype); $valid_types = Song::get_stream_types_for_type($ftype);
if ($transcode_cfg == 'always' || ($transcode_cfg != 'never' && in_array('transcode', $valid_types))) { if ($transcode_cfg == 'always' || ($transcode_cfg != 'never' && in_array('transcode', $valid_types))) {
// Transcode only if excepted type available // Transcode only if excepted type available
@ -139,7 +144,11 @@ class WebPlayer
{ {
$jptypes = array(); $jptypes = array();
foreach ($playlist->urls as $item) { foreach ($playlist->urls as $item) {
$types = self::get_types($item); $force_type = '';
if ($item->type == 'broadcast') {
$force_type = 'mp3';
}
$types = self::get_types($item, $force_type);
if (!in_array($types['player'], $jptypes)) { if (!in_array($types['player'], $jptypes)) {
$jptypes[] = $types['player']; $jptypes[] = $types['player'];
} }
@ -148,50 +157,60 @@ class WebPlayer
return $jptypes; return $jptypes;
} }
public static function add_media_js($playlist, $callback='addMedia') public static function add_media_js($playlist, $callback_container='')
{ {
$addjs = ""; $addjs = "";
foreach ($playlist->urls as $item) { foreach ($playlist->urls as $item) {
$js = array(); if ($item->type == 'broadcast') {
foreach (array('title', 'author') as $member) { $addjs .= $callback_container . "startBroadcastListening('" . $item->url . "');";
if ($member == "author") break;
$kmember = "artist"; } else {
else $addjs .= $callback_container . "addMedia(" . self::get_media_js_param($item) . ");";
$kmember = $member;
$js[$kmember] = $item->$member;
} }
$url = $item->url;
$types = self::get_types($item);
$song = null;
$urlinfo = Stream_URL::parse($url);
if ($urlinfo['id'] && $urlinfo['type'] == 'song') {
$song = new Song($urlinfo['id']);
} else if ($urlinfo['id'] && $urlinfo['type'] == 'song_preview') {
$song = new Song_Preview($urlinfo['id']);
}
if ($song != null) {
$js['artist_id'] = $song->artist;
$js['album_id'] = $song->album;
$js['song_id'] = $song->id;
if ($song->type != $types['real']) {
$url .= '&transcode_to=' . $types['real'];
}
//$url .= "&content_length=required";
}
$js['filetype'] = $types['player'];
$js['url'] = $url;
if ($urlinfo['type'] == 'song') {
$js['poster'] = $item->image_url . (!$iframed ? '&thumb=4' : '');
}
$addjs .= $callback . "(" . json_encode($js) . ");";
} }
return $addjs; return $addjs;
} }
public static function get_media_js_param($item, $force_type='')
{
$js = array();
foreach (array('title', 'author') as $member) {
if ($member == "author")
$kmember = "artist";
else
$kmember = $member;
$js[$kmember] = $item->$member;
}
$url = $item->url;
$types = self::get_types($item, $force_type);
$song = null;
$urlinfo = Stream_URL::parse($url);
if ($urlinfo['id'] && $urlinfo['type'] == 'song') {
$song = new Song($urlinfo['id']);
} else if ($urlinfo['id'] && $urlinfo['type'] == 'song_preview') {
$song = new Song_Preview($urlinfo['id']);
}
if ($song != null) {
$js['artist_id'] = $song->artist;
$js['album_id'] = $song->album;
$js['song_id'] = $song->id;
if ($song->type != $types['real']) {
$url .= '&transcode_to=' . $types['real'];
}
//$url .= "&content_length=required";
}
$js['filetype'] = $types['player'];
$js['url'] = $url;
if ($urlinfo['type'] == 'song') {
$js['poster'] = $item->image_url . (!$iframed ? '&thumb=4' : '');
}
return json_encode($js);
}
} }

View file

@ -64,14 +64,17 @@ if (!empty($link)) {
/** This is the version.... fluf nothing more... **/ /** This is the version.... fluf nothing more... **/
$results['version'] = '3.7-develop'; $results['version'] = '3.7-develop';
$results['int_config_version'] = '13'; $results['int_config_version'] = '14';
if (!empty($results['force_ssl'])) { if (!empty($results['force_ssl'])) {
$http_type = 'https://'; $http_type = 'https://';
} }
$results['raw_web_path'] = $results['web_path']; $results['raw_web_path'] = $results['web_path'];
$results['web_path'] = $http_type . $_SERVER['HTTP_HOST'] . $results['web_path']; if (empty($results['http_host'])) {
$results['http_host'] = $_SERVER['HTTP_HOST'];
}
$results['web_path'] = $http_type . $results['http_host'] . $results['web_path'];
$results['http_port'] = (!empty($results['http_port'])) ? $results['http_port'] : $http_port; $results['http_port'] = (!empty($results['http_port'])) ? $results['http_port'] : $http_port;
$results['site_charset'] = $results['site_charset'] ?: 'UTF-8'; $results['site_charset'] = $results['site_charset'] ?: 'UTF-8';
$results['raw_web_path'] = $results['raw_web_path'] ?: '/'; $results['raw_web_path'] = $results['raw_web_path'] ?: '/';

View file

@ -179,6 +179,11 @@ switch ($_REQUEST['action']) {
$channel = new Channel($_POST['id']); $channel = new Channel($_POST['id']);
$channel->update($_POST); $channel->update($_POST);
break; break;
case 'broadcast_row':
$key = 'broadcast_row_' . $_POST['id'];
$broadcast = new Broadcast($_POST['id']);
$broadcast->update($_POST);
break;
default: default:
$key = 'rfc3514'; $key = 'rfc3514';
echo xoutput_from_array(array($key=>'0x1')); echo xoutput_from_array(array($key=>'0x1'));

View file

@ -100,6 +100,9 @@ switch ($_REQUEST['action']) {
case 'channel': case 'channel':
$_SESSION['iframe']['target'] = AmpConfig::get('web_path') . '/stream.php?action=channel&id='.$_REQUEST['channel_id']; $_SESSION['iframe']['target'] = AmpConfig::get('web_path') . '/stream.php?action=channel&id='.$_REQUEST['channel_id'];
break; break;
case 'broadcast':
$_SESSION['iframe']['target'] = AmpConfig::get('web_path') . '/stream.php?action=broadcast&id='.$_REQUEST['broadcast_id'];
break;
} }
if (!empty($_REQUEST['append'])) { if (!empty($_REQUEST['append'])) {
$_SESSION['iframe']['target'] .= '&append=true'; $_SESSION['iframe']['target'] .= '&append=true';

View file

@ -182,6 +182,12 @@ switch ($_REQUEST['action']) {
'object_id' => scrub_in($_REQUEST['id']) 'object_id' => scrub_in($_REQUEST['id'])
); );
break; break;
case 'broadcast':
$media_ids[] = array(
'object_type' => 'broadcast',
'object_id' => scrub_in($_REQUEST['id'])
);
break;
default: default:
break; break;
} // end action switch } // end action switch

View file

@ -50,7 +50,7 @@ if ($_REQUEST['append']) {
<?php } ?> <?php } ?>
if (appendmedia) { if (appendmedia) {
<?php echo WebPlayer::add_media_js($this, "ff.contentWindow.addMedia"); ?> <?php echo WebPlayer::add_media_js($this, "ff.contentWindow."); ?>
} else { } else {
ff.setAttribute('src', '<?php echo AmpConfig::get('web_path'); ?>/web_player_embedded.php?playlist_id=<?php echo $this->id; ?>'); ff.setAttribute('src', '<?php echo AmpConfig::get('web_path'); ?>/web_player_embedded.php?playlist_id=<?php echo $this->id; ?>');
window.location = '<?php echo return_referer() ?>'; window.location = '<?php echo return_referer() ?>';

View file

@ -29,7 +29,7 @@
</div> </div>
</td> </td>
<td class="cel_name"><?php echo $broadcast->name; ?></td> <td class="cel_name"><?php echo $broadcast->name; ?></td>
<td class="cel_genre"></td> <td class="cel_genre"><?php echo $broadcast->f_tags; ?></td>
<td class="cel_started"><?php echo ($broadcast->started ? T_('Yes') : T_('No')); ?></td> <td class="cel_started"><?php echo ($broadcast->started ? T_('Yes') : T_('No')); ?></td>
<td class="cel_listeners"><?php echo $broadcast->listeners; ?></td> <td class="cel_listeners"><?php echo $broadcast->listeners; ?></td>
<td class="cel_action"><?php $broadcast->show_action_buttons($tags_list); ?></td> <td class="cel_action"><?php $broadcast->show_action_buttons($tags_list); ?></td>

View file

@ -39,6 +39,10 @@
<td class="cel_bitrate"><?php echo $channel->bitrate; ?></td> <td class="cel_bitrate"><?php echo $channel->bitrate; ?></td>
<td class="cel_startdate"><?php echo date("c", $channel->start_date); ?></td> <td class="cel_startdate"><?php echo date("c", $channel->start_date); ?></td>
<td class="cel_listeners"><?php echo $channel->listeners; ?></td> <td class="cel_listeners"><?php echo $channel->listeners; ?></td>
<td class="cel_streamurl"><?php echo $channel->get_stream_url(); ?><br /><?php echo $channel->get_stream_proxy_url(); ?></td> <td class="cel_streamurl">
<?php echo $channel->get_stream_url(); ?><br />
<?php if ($channel->is_private) { echo UI::get_icon('lock', T_('Authentication Required')); } ?>
<?php echo $channel->get_stream_proxy_url(); ?>
</td>
<td class="cel_state"><div id="channel_state_<?php echo $channel->id; ?>"><?php echo $channel->get_channel_state(); ?></div></td> <td class="cel_state"><div id="channel_state_<?php echo $channel->id; ?>"><?php echo $channel->get_channel_state(); ?></div></td>
<td class="cel_action"><?php $channel->show_action_buttons($tags_list); ?></td> <td class="cel_action"><?php $channel->show_action_buttons($tags_list); ?></td>

View file

@ -43,6 +43,7 @@ function NavigateTo(url)
var jpuqid = (new Date()).getMilliseconds(); var jpuqid = (new Date()).getMilliseconds();
var jplaylist = null; var jplaylist = null;
var timeoffset = 0; var timeoffset = 0;
var currentjpindex = 0;
$(document).ready(function(){ $(document).ready(function(){
@ -122,7 +123,6 @@ if ($isVideo) {
<?php } ?> <?php } ?>
}); });
$("#jquery_jplayer_1").bind($.jPlayer.event.play, function (event) { $("#jquery_jplayer_1").bind($.jPlayer.event.play, function (event) {
var current = jplaylist.current, var current = jplaylist.current,
playlist = jplaylist.playlist; playlist = jplaylist.playlist;
@ -134,6 +134,10 @@ if ($isVideo) {
$.each(playlist, function (index, obj) { $.each(playlist, function (index, obj) {
if (index == current) { if (index == current) {
currentjpindex = index;
if (brkey != '') {
sendBroadcastMessage('SONG', songids[index]);
}
<?php <?php
if (!$isVideo && !$isRadio && !$is_share) { if (!$isVideo && !$isRadio && !$is_share) {
if ($iframed) { if ($iframed) {
@ -209,7 +213,9 @@ if ($isVideo) {
} }
?> ?>
$("#jquery_jplayer_1").bind($.jPlayer.event.timeupdate, function (event) { $("#jquery_jplayer_1").bind($.jPlayer.event.timeupdate, function (event) {
sendBroadcastMessage('SONG_POSITION', event.jPlayer.status.currentTime); if (brkey != '') {
sendBroadcastMessage('SONG_POSITION', event.jPlayer.status.currentTime);
}
<?php <?php
if (AmpConfig::get('waveform') && !$is_share) { if (AmpConfig::get('waveform') && !$is_share) {
?> ?>
@ -236,10 +242,12 @@ function WaveformClick(songid, time)
NavigateTo('<?php echo AmpConfig::get('web_path') ?>/shout.php?action=show_add_shout&type=song&id=' + songid + '&offset=' + time); NavigateTo('<?php echo AmpConfig::get('web_path') ?>/shout.php?action=show_add_shout&type=song&id=' + songid + '&offset=' + time);
} else { } else {
// Single click // Single click
wavclicktimer = setTimeout(function() { if (brconn == null) {
wavclicktimer = null; wavclicktimer = setTimeout(function() {
$("#jquery_jplayer_1").data("jPlayer").play(time); wavclicktimer = null;
}, 250); $("#jquery_jplayer_1").data("jPlayer").play(time);
}, 250);
}
} }
} }
@ -272,7 +280,33 @@ function startBroadcast(key)
brkey = key; brkey = key;
listenBroadcast(); listenBroadcast();
sendBroadcastMessage('REGISTER_BROADCAST', brkey); brconn.onopen = function(e) {
sendBroadcastMessage('AUTH_SID', '<?php echo session_id(); ?>');
sendBroadcastMessage('REGISTER_BROADCAST', brkey);
sendBroadcastMessage('SONG', songids[currentjpindex]);
};
}
function startBroadcastListening(broadcast_id)
{
listenBroadcast();
// Hide few UI information on listening mode
$('.jp-previous').css('visibility', 'hidden');
$('.jp-play').css('visibility', 'hidden');
$('.jp-pause').css('visibility', 'hidden');
$('.jp-next').css('visibility', 'hidden');
$('.jp-stop').css('visibility', 'hidden');
$('.jp-toggles').css('visibility', 'hidden');
$('.jp-playlist').css('visibility', 'hidden');
$('#broadcast').css('visibility', 'hidden');
$('.jp-seek-bar').css('pointer-events', 'none');
brconn.onopen = function(e) {
sendBroadcastMessage('AUTH_SID', '<?php echo session_id(); ?>');
sendBroadcastMessage('REGISTER_LISTENER', broadcast_id);
};
} }
function listenBroadcast() function listenBroadcast()
@ -290,10 +324,11 @@ function receiveBroadcastMessage(e)
var jp = $("#jquery_jplayer_1").data("jPlayer"); var jp = $("#jquery_jplayer_1").data("jPlayer");
var msgs = e.data.split(';'); var msgs = e.data.split(';');
for (var i = 0; i < msgs.length; ++i) { for (var i = 0; i < msgs.length; ++i) {
var msg = msgs[i].split('='); var msg = msgs[i].split(':');
if (msg.count == 2) { if (msg.length == 2) {
switch (msg[0]) { switch (msg[0]) {
case 'PLAY': case 'PLAY':
alert('play: ' + msg[1]);
if (msg[1] == '1') { if (msg[1] == '1') {
if (jp.status.paused) { if (jp.status.paused) {
jp.play(); jp.play();
@ -306,15 +341,16 @@ function receiveBroadcastMessage(e)
break; break;
case 'SONG': case 'SONG':
addMedia($.parseJSON(atob(msg[1])));
jplaylist.next();
break; break;
case 'SONG_POSITION': case 'SONG_POSITION':
jp.play(msg[1]); jp.play(parseFloat(msg[1]));
break; break;
case 'NB_LISTENERS': case 'NB_LISTENERS':
$('#broadcast_listeners').text($msg[1]); $('#broadcast_listeners').html(msg[1]);
break; break;
case 'INFO': case 'INFO':
@ -324,6 +360,10 @@ function receiveBroadcastMessage(e)
case 'ENDED': case 'ENDED':
jp.stop(); jp.stop();
break; break;
default:
alert('Unknown message code.');
break;
} }
} }
} }
@ -332,8 +372,8 @@ function receiveBroadcastMessage(e)
function sendBroadcastMessage(cmd, value) function sendBroadcastMessage(cmd, value)
{ {
if (brconn != null) { if (brconn != null) {
var msg = cmd + '=' + value + ';'; var msg = cmd + ':' + value + ';';
brconn.send(cmd); brconn.send(msg);
} }
} }

View file

@ -173,7 +173,7 @@ if (!defined('INSTALL')) {
$http_type = 'https://'; $http_type = 'https://';
} }
$results['web_path'] = $http_type . $_SERVER['HTTP_HOST'] . AmpConfig::get('web_path'); $results['web_path'] = $http_type . AmpConfig::get('http_host') . AmpConfig::get('web_path');
if (check_config_values($results)) { if (check_config_values($results)) {
echo "&nbsp;&nbsp;&nbsp;<img src=\"" . $results['web_path'] ."/images/icon_enable.png\" />&nbsp;&nbsp;&nbsp;"; echo "&nbsp;&nbsp;&nbsp;<img src=\"" . $results['web_path'] ."/images/icon_enable.png\" />&nbsp;&nbsp;&nbsp;";
} else { } else {