Beispiel #1
0
 /**
  * @return Unpacker|NULL
  */
 protected function loadCompiled($filename)
 {
     $basename = basename($filename, '.xoup');
     $class = 'XOUP' . $basename . 'Unpacker';
     if (!class_exists($class, false)) {
         $dirname = dirname($filename);
         $compiled_name = $dirname . '/' . $basename . '.php';
         if (file_exists($dirname . '/' . $basename . '.php')) {
             $source_ts = filemtime($filename);
             $compiled_ts = filemtime($compiled_name);
             if ($compiled_ts < $source_ts) {
                 L::level(L::DEBUG) && L::log(L::DEBUG, __CLASS__, 'source modified since last compilation', array());
                 return null;
             }
             require_once $compiled_name;
             if (!class_exists($class)) {
                 throw new RuntimeException("{$class} not present in {$compiled_name}");
             }
             L::level(L::DEBUG) && L::log(L::DEBUG, __CLASS__, 'loaded compiled XOUP class %s from file %s', array($class, $compiled_name));
         } else {
             // no compiled file exists
             L::level(L::DEBUG) && L::log(L::DEBUG, __CLASS__, 'compiled XOUP file %s does not (yet) exist', array($compiled_name));
             return null;
         }
     }
     return new $class();
 }
 public function addPluginsTo(SSLPluggable $sslpluggable)
 {
     L::level(L::DEBUG) && L::log(L::DEBUG, __CLASS__, "yielding %d plugins", array(count($this->plugins)));
     foreach ($this->plugins as $plugin) {
         $sslpluggable->addPlugin($plugin);
     }
 }
 protected function trackStopped(SSLTrack $track)
 {
     $stm = $this->factory->newScrobblerTrackModel($track);
     if ($stm->isScrobblable()) {
         L::level(L::INFO) && L::log(L::INFO, __CLASS__, 'I reckon it\'s time to submit a scrobble for %s!', array($track->getFullTitle()));
         $this->notifyScrobbleObservers($track);
     }
 }
 protected function handle($signal)
 {
     switch ($signal) {
         case SIGINT:
             L::level(L::INFO) && L::log(L::INFO, __CLASS__, 'Caught SIGINT', array());
             $this->should_exit = true;
             break;
     }
 }
 public function dump()
 {
     L::level(L::INFO) && L::log(L::INFO, __CLASS__, 'reading structure of %s...', array($this->filename));
     $tree = $this->read($this->filename);
     L::level(L::INFO) && L::log(L::INFO, __CLASS__, 'asking structure DOM to parse %s...', array($this->filename));
     // Without this line you'll just get hexdumps, which is not very exciting.
     $tree->getData();
     L::level(L::INFO) && L::log(L::INFO, __CLASS__, 'printing structure of %s...', array($this->filename));
     // After the parsing has occurred, we get much more exciting debug output.
     $tree->display();
     echo "Memory usage: " . number_format(memory_get_peak_usage()) . " bytes\n";
 }
 public function getChunks()
 {
     $chunks = array();
     do {
         $chunk = $this->readChunk();
         if ($chunk !== false) {
             $chunks[] = $chunk;
         }
     } while ($chunk !== false);
     L::level(L::DEBUG) && L::log(L::DEBUG, __CLASS__, "Read %d chunks", array(count($chunks)));
     return $chunks;
 }
 protected function checkForNewFilename()
 {
     if (isset($this->fns)) {
         $old_filename = $this->filename;
         $this->filename = $this->fns->getNewFilename();
         $got_new_file = $this->filename != $old_filename;
         if ($got_new_file) {
             L::level(L::INFO) && L::log(L::INFO, __CLASS__, "Changed to new file %s", array($this->filename));
         }
         return $got_new_file;
     }
     return false;
 }
 /**
  * Enable a plugin.
  * 
  * HistoryReader calls this indirectly when it asks CLIPlugins to add their
  * SSLPlugins to the plugin chain.
  * 
  * @param SSLPlugin $plugin
  */
 public function addPlugin(SSLPlugin $plugin)
 {
     // onSetup for late added plugins
     if ($this->setup_done) {
         $plugin->onSetup();
     }
     // onStart for late added plugins
     if ($this->clock_is_ticking) {
         $plugin->onStart();
     }
     $this->plugin_wrapper->addPlugin($this->max_plugin_id, $plugin);
     L::level(L::DEBUG) && L::log(L::DEBUG, __CLASS__, "added %s plugin with id %d", array(get_class($plugin), $this->max_plugin_id));
     $this->max_plugin_id++;
 }
 /**
  * @return array of SSLOtrkChunk
  */
 public function getData()
 {
     $data = array();
     $chunk_count = 0;
     foreach ($this as $chunk) {
         if ($chunk instanceof SSLOtrkChunk) {
             $data[] = $chunk->getDataInto(new SSLLibraryTrack());
         } elseif ($chunk instanceof SSLVrsnChunk) {
             $data[] = $chunk->getDataInto(new SSLVersion());
         }
         $chunk_count++;
         L::level(L::DEBUG) && !($chunk_count % 1000) && L::log(L::DEBUG, __CLASS__, "Parsed %d chunks...", array($chunk_count));
     }
     return $data;
 }
 public function shorten($url)
 {
     L::level(L::INFO) && L::log(L::INFO, __CLASS__, "Shortening %s", array($url));
     $result = vgdShorten($url, null, true);
     // log stats
     if ($result['shortURL']) {
         L::level(L::INFO) && L::log(L::INFO, __CLASS__, "Shortened to %s", array($result['shortURL']));
         return $result['shortURL'];
     }
     L::level(L::WARNING) && L::log(L::WARNING, __CLASS__, "Shorten failed: %s", array($result['errorMessage']));
     // On failure we return empty rather than the original URL
     // on the assumption that it was too long in the first place
     //return $url;
     return '';
 }
 public function notifyNowPlaying(SSLTrack $track = null)
 {
     if (!$track) {
         return;
     }
     $sock = fsockopen($this->host, $this->port, $errno, $errstr, $timeout = 1);
     if ($sock === false) {
         L::level(L::ERROR) && L::log(L::ERROR, __CLASS__, "couldn't connect to IRCCat: (%d) %s", array($errno, $errstr));
         return;
     }
     $message = sprintf($this->config['message'], $track->getFullTitle());
     L::level(L::INFO) && L::log(L::INFO, __CLASS__, "sending '%s' -> %s:%d#%s", array($message, $this->host, $this->port, $this->channel));
     fwrite($sock, sprintf("%s %s", $this->channel, $message));
     fclose($sock);
 }
 public function notifyScrobble(SSLTrack $track)
 {
     $length = $track->getLengthInSeconds(SSLTrack::TRY_HARD);
     if ($length == 0) {
         // Perhaps this entry was added manually.
         L::level(L::WARNING) && L::log(L::WARNING, __CLASS__, 'Could not guess length. Last.fm will silently ignore the scrobble.', array());
     }
     try {
         $this->scrobbler->add($track->getArtist(), $track->getTitle(), $track->getAlbum(), $length, $track->getStartTime());
         L::level(L::DEBUG) && L::log(L::DEBUG, __CLASS__, 'Sending %d scrobble(s) to Last.fm', array($this->scrobbler->getQueueSize()));
         $this->scrobbler->submit();
         // TODO: caching if scrobbling's down whilst playing.
     } catch (Exception $e) {
         L::level(L::WARNING) && L::log(L::WARNING, __CLASS__, 'Could not send %d scrobble(s) to Last.fm: %s', array($this->scrobbler->getQueueSize(), $e->getMessage()));
     }
 }
 public function compile($filename)
 {
     L::level(L::INFO) && L::log(L::INFO, __CLASS__, 'compiling %s', array($filename));
     $class = $this->getClassName($filename);
     $output = "<?php\n\n";
     $output .= "/* Autogenerated by XoupCompiler */\n\n";
     $output .= "class {$class} extends Unpacker\n{\n\n";
     $output .= "    private \$out_buffer = '';\n";
     $output .= "    private \$context = array();\n";
     if (!empty($this->data)) {
         $output .= "    private \$data = array(\n";
         foreach ($this->data as $k => $v) {
             $k = addslashes($k);
             $v = addslashes($v);
             $output .= "        \"{$k}\" => \"{$v}\",\n";
         }
         $output .= "    );\n";
     }
     $output .= "\n";
     $output .= "    public function unpack(\$bin)\n";
     $output .= "    {\n";
     $output .= "        \$binlen = strlen(\$bin);\n";
     $output .= "        \$acc = 0;\n";
     $output .= "        \$ptr = 0;\n";
     $output .= "        \$this->_main(\$bin, \$binlen, \$acc, \$ptr);\n";
     $output .= "        return \$this->context;\n";
     $output .= "    }\n\n";
     $output .= "    public function flushBuffer()\n";
     $output .= "    {\n";
     $output .= "        L::level(L::INFO) &&\n";
     $output .= "            L::log(L::INFO, __CLASS__, \$this->out_buffer,\n";
     $output .= "                array());\n";
     $output .= "    }\n\n";
     foreach (array_keys($this->subs) as $sub) {
         $output .= $this->writeFunctionHeader($sub);
         $output .= $this->writeFunctionBody($sub);
         $output .= $this->writeFunctionFooter();
     }
     $output .= $this->writeLUTFunctionHeader();
     $output .= $this->writeLUTFunctionBody(array_keys($this->subs));
     $output .= $this->writeFunctionFooter();
     $output .= "}\n";
     file_put_contents($this->getCompiledName($filename), $output);
 }
 public function elapse($seconds)
 {
     $this->playtime += $seconds;
     $was_passed_now_playing_point = $this->passed_now_playing_point;
     $was_passed_scrobble_point = $this->passed_scrobble_point;
     $was_ended = $this->passed_end;
     $this->passed_now_playing_point = $this->playtime >= self::NOW_PLAYING_MIN;
     $this->passed_scrobble_point = $this->playtime >= $this->scrobble_point;
     $this->passed_end = $this->playtime >= $this->end_point;
     if ($this->passed_now_playing_point && !$was_passed_now_playing_point) {
         L::level(L::INFO) && L::log(L::INFO, __CLASS__, '%s passed now playing point', array($this->track->getFullTitle()));
     }
     if ($this->passed_scrobble_point && !$was_passed_scrobble_point) {
         L::level(L::INFO) && L::log(L::INFO, __CLASS__, '%s passed scrobble point', array($this->track->getFullTitle()));
     }
     if ($this->passed_end && !$was_ended) {
         L::level(L::INFO) && L::log(L::INFO, __CLASS__, '%s passed end point', array($this->track->getFullTitle()));
     }
 }
Beispiel #15
0
 public function parse($program)
 {
     $data = array();
     // strip comments
     $stripped_program = preg_replace("/#[^\n]*\n/", ' ', $program);
     // tokenize
     $ops = preg_split("/\\s+/", $stripped_program);
     // trim
     $ops = array_map('trim', $ops);
     // remove empty tokens
     foreach ($ops as $k => $v) {
         if (empty($v)) {
             unset($ops[$k]);
         }
     }
     $subs = array();
     $opdest = null;
     foreach ($ops as $k => $v) {
         if (preg_match('/^([a-zA-Z0-9]+):$/', $v, $matches)) {
             // it's a label
             $subs[$matches[1]] = array();
             $opdest = $matches[1];
         } elseif (preg_match('/^\\.[a-zA-Z0-9]+$/', $v, $matches)) {
             // we found our first piece of DATA. finish program parsing
             // and move to DATA parsing
             $data = $this->parseData($program);
             break;
         } else {
             // it's an op
             if (is_null($opdest)) {
                 throw new RuntimeException("Parse error: op found out of sub scope");
             }
             $subs[$opdest][] = $v;
         }
     }
     if (!in_array('main', array_keys($subs))) {
         throw new RuntimeException("Parse error: no 'main' sub found.");
     }
     L::level(L::DEBUG) && L::log(L::DEBUG, __CLASS__, 'parsed %d subs and %d literals', array(count($subs), count($this->data)));
     return $subs;
 }
 public function spinOff(ParallelTask $t, $task = 'task')
 {
     if (function_exists('pcntl_fork') && !defined('SINGLE_THREADED')) {
         L::level(L::DEBUG) && L::log(L::DEBUG, __CLASS__, "Forking %s...", array($task));
         $pid = pcntl_fork();
         if ($pid) {
             // parent
             if ($pid == -1) {
                 L::level(L::WARNING) && L::log(L::WARNING, __CLASS__, "Fork failed! Running %s single-threaded...", array($task));
                 $t->run();
                 return false;
             }
             return $pid;
         } else {
             // child
             $t->run();
             exit;
         }
     } else {
         L::level(L::DEBUG) && L::log(L::DEBUG, __CLASS__, "PCNTL not supported. Running %s single-threaded. If %s is slow, it will block the app until it is finished.", array($task, $task));
         $t->run();
     }
     return false;
 }
 protected function getBeatportURL(SSLTrack $track)
 {
     $url = '';
     $bp = $this->newBeatportAPIClient();
     $artistName = $track->getArtist();
     $trackName = $track->getTitle();
     $bp_track = $bp->getTrackByArtist($artistName, $trackName);
     if ($bp_track) {
         $bp_artist_names = $bp_track->getArtistNames();
         $bp_track_title = $bp_track->getName();
         $bp_url = $bp_track->getURL();
         $bp_track_string = implode(', ', $bp_artist_names) . ' - ' . $bp_track_title;
         $ssl_track_string = $track->getFullTitle();
         L::level(L::INFO) && L::log(L::INFO, __CLASS__, "Found %s at %s", array($bp_track_string, $bp_url));
         if ($this->checkMatch($ssl_track_string, $bp_track_string)) {
             $url = $bp_track->getURL();
         } else {
             L::level(L::INFO) && L::log(L::INFO, __CLASS__, "Rejected %s as a match for %s", array($bp_track_string, $ssl_track_string));
         }
     } else {
         L::level(L::INFO) && L::log(L::INFO, __CLASS__, "No track found.", array());
     }
     return $url;
 }
 protected function sendNowPlaying()
 {
     $track = $this->track_to_notify;
     $message = $this->msg_format;
     foreach ($this->message_filters as $mf) {
         /* @var $mf ITrackMessageFilter */
         $message = $mf->apply($track, $message);
     }
     // Twitter max message length, minus the pre-processed message,
     // and give back 2 chars for '%s'
     $max_title_length = 160 - (mb_strlen($message) - 2);
     $title = $track->getFullTitle();
     $title_length = mb_strlen($title);
     if ($title_length > $max_title_length) {
         $title = mb_substr($title, 0, $this->max_title_length - 1) . '…';
     }
     $status = sprintf($message, $title);
     try {
         L::level(L::DEBUG) && L::log(L::DEBUG, __CLASS__, 'Sending Now Playing to Twitter', array());
         $this->twitter->send($status);
     } catch (Exception $e) {
         L::level(L::WARNING) && L::log(L::WARNING, __CLASS__, 'Could not send Now Playing to Twitter: %s', array($e->getMessage()));
     }
 }
Beispiel #19
0
 /**
  * Converts an SSL signed binary string into a PHP integer
  */
 protected function unpacksint($datum, $intmax = PHP_INT_MAX)
 {
     $width = strlen($datum);
     switch ($intmax) {
         case 0x7fffffff:
             // 32-bit mode
             switch ($width) {
                 case 8:
                     // Seems that ScratchLive 2.0 uses 64-bit timestamps. oh shi--
                     $vals = unpack('Nupper/Nlower', $datum);
                     if ($vals['upper'] != 4294967295.0 && $vals['upper'] != 0 || $vals['upper'] == 4294967295.0 && $vals['lower'] & 2147483648.0 == 0 || $vals['upper'] == 0 && $vals['lower'] & 2147483648.0 == 2147483648.0) {
                         L::level(L::WARNING) && L::log(L::WARNING, __CLASS__, "Encountered signed 64-bit integer > PHP_INT_MAX on a 32-bit PHP. Throwing away upper bytes. Original value was 0x%08X%08X", array(dechex($vals['upper']), dechex($vals['lower'])));
                     }
                     // 32-bit range -ve vals will already be in the right sign. All bets are already off for other vals.
                     if ($vals['upper'] > 0) {
                         $vals['val'] = PHP_INT_MAX;
                     } elseif ($vals['upper'] < -1) {
                         $vals['val'] = -PHP_INT_MAX - 1;
                     } else {
                         $vals['val'] = $vals['lower'];
                         if ($vals['upper'] < 0) {
                             // -ve sign bit
                             $vals['val'] |= 2147483648.0;
                         }
                     }
                     break;
                 case 4:
                     // this will be signed on a 32-bit machine
                     $vals = unpack('Nval', $datum);
                     // unsigned long (always 32 bit, big endian byte order)
                     break;
                 case 2:
                     $vals = unpack('nval', $datum);
                     // unsigned short (always 16 bit, big endian byte order)
                     if ($vals['val'] & 0x8000) {
                         $vals['val'] |= 4294901760.0;
                         // extend sign
                     }
                     break;
                 case 1:
                     $vals = unpack('cval', $datum);
                     // char
                     if ($vals['val'] & 0x80) {
                         $vals['val'] |= 4294967040.0;
                         // extend sign
                     }
                     break;
                 default:
                     throw new InvalidArgumentException('Cannot unpack an odd-sized int of width ' . $width);
             }
             return $vals['val'];
         case 9.223372036854776E+18:
             // 64-bit mode
             switch ($width) {
                 case 8:
                     // Seems that ScratchLive 2.0 uses 64-bit timestamps. oh shi--
                     $vals = unpack('Nupper/Nlower', $datum);
                     // this will be signed on a 64-bit machine.
                     $vals['val'] = $vals['upper'] << 32 | $vals['lower'];
                     break;
                 case 4:
                     $vals = unpack('Nval', $datum);
                     // unsigned long (always 32 bit, big endian byte order)
                     if ($vals['val'] & 2147483648.0) {
                         $vals['val'] |= 1.8446744069414584E+19;
                         // extend sign
                     }
                     break;
                 case 2:
                     $vals = unpack('nval', $datum);
                     // unsigned short (always 16 bit, big endian byte order)
                     if ($vals['val'] & 0x8000) {
                         $vals['val'] |= 1.8446744073709486E+19;
                         // extend sign
                     }
                     break;
                 case 1:
                     $vals = unpack('cval', $datum);
                     // char
                     if ($vals['val'] & 0x80) {
                         $vals['val'] |= 1.8446744073709552E+19;
                         // extend sign
                     }
                     break;
                 default:
                     throw new InvalidArgumentException('Cannot unpack an odd-sized int of width ' . $width);
             }
             return $vals['val'];
         default:
             throw new RuntimeException('Unsupported architecture (neither 32-bit or 64-bit)');
     }
 }
 public function parseFromFile($fp)
 {
     $header_bin = fread($fp, 8);
     $length_read = strlen($header_bin);
     if ($length_read == 0) {
         L::level(L::DEBUG) && L::log(L::DEBUG, __CLASS__, "Reached EOF; no more to read", array());
         return false;
         // if we read an exact chunk, it's not an 'eof'.
     }
     if ($length_read < 8) {
         throw new OutOfBoundsException("No more data (read {$length_read} bytes)");
     }
     if ($header_bin === false) {
         throw new RuntimeException("Read error; failed to read 8 bytes of chunk header");
     }
     list($chunk_type, $chunk_size) = $this->parseHeader($header_bin);
     if ($chunk_size > 1048576) {
         // a chunk larger than 1Mb!?
         $chunk_size = number_format($chunk_size / 1024 / 1024, 2);
         throw new RuntimeException("Found chunk claiming to be enormous ({$chunk_size} MiB); are you reading the right file?");
     }
     $body_bin = fread($fp, $chunk_size);
     $chunk = $this->chunk_factory->newChunk($chunk_type, $body_bin);
     L::level(L::DEBUG) && L::log(L::DEBUG, __CLASS__, "Read %s chunk from file", array($chunk_type));
     return $chunk;
 }
Beispiel #21
0
 public function notifyExit()
 {
     L::level(L::DEBUG) && L::log(L::DEBUG, __CLASS__, "Exit caught.", array());
     $this->exit_notified = true;
 }
 protected function getMixesForTrack($key)
 {
     $search = $this->doMixcloudCall('mixes', 'http://api.mixcloud.com%spopular/?limit=%d', array($key, 20));
     if (isset($search['error'])) {
         throw new Exception('Error from Mixcloud: ' . $search['error']['message']);
     }
     $cloudcasts = array();
     foreach ($search['data'] as $result) {
         $cloudcasts[] = $result;
     }
     L::level(L::INFO) && L::log(L::INFO, __CLASS__, 'Found %d mixes for track %s', array(count($cloudcasts), $key));
     return $cloudcasts;
 }
 public function transitionTo(SSLTrack $track)
 {
     $from = $this->getStatus();
     $to = $track->getStatus();
     L::level(L::DEBUG) && L::log(L::DEBUG, __CLASS__, "deck %d transitioned from %s to %s with track %s", array($this->deck_number, $from, $to, $track->getTitle()));
     switch ($from) {
         case 'EMPTY':
             $this->transitionFromEmptyTo($track);
             break;
         case 'SKIPPED':
             $this->transitionFromSkippedTo($track);
             break;
         case 'PLAYED':
             $this->transitionFromPlayedTo($track);
             break;
         case 'NEW':
             $this->transitionFromNewTo($track);
             break;
         case 'PLAYING':
             $this->transitionFromPlayingTo($track);
             break;
         default:
             throw new InvalidArgumentException('Unknown FROM state "' . $from . '"');
     }
 }
 /**
  * Update model information based on changes to the SSL History.
  * 
  * @param SSLHistoryDiffDom $diff
  */
 public function notifyDiff(SSLHistoryDiffDom $diff)
 {
     foreach ($diff->getTracks() as $track) {
         /* @var $track SSLTrack */
         // create track deck on demand
         $this->getDeck($track->getDeck());
     }
     $events = array();
     foreach ($this->decks as $deck_number => $deck) {
         /* @var $deck SSLRealtimeModelDeck */
         $deck->notify($diff);
         $stopped_track = $deck->trackStopped();
         if ($stopped_track) {
             $events[] = $this->factory->newTrackStoppedEvent($stopped_track);
         }
         $started_track = $deck->trackStarted();
         if ($started_track) {
             $events[] = $this->factory->newTrackStartedEvent($started_track);
         }
         $updated_track = $deck->trackUpdated();
         if ($updated_track) {
             $events[] = $this->factory->newTrackUpdatedEvent($updated_track);
         }
     }
     if (count($events)) {
         $events = $this->factory->newTrackChangeEventList($events);
         L::level(L::DEBUG) && L::log(L::DEBUG, __CLASS__, "notifying %s", array($events));
         $this->notifyTrackChangeObservers($events);
     }
 }
 protected function handleRequest($conn)
 {
     socket_set_block($conn);
     $request = '';
     $bytes = socket_recv($conn, $request, 16384, 0);
     if ($bytes === false) {
         L::level(L::DEBUG) && L::log(L::DEBUG, __CLASS__, "Problem reading from socket: %s", array(socket_last_error($conn)));
         return;
     }
     $request = explode("\n", $request);
     $get_line = explode(' ', $request[0]);
     if (preg_match('#^/nowplaying\\.json(?:\\?.*|$)#', $get_line[1])) {
         $data = array();
         if (isset($this->most_recent_track)) {
             $track = $this->most_recent_track;
             $data = array('artist' => $track->getArtist(), 'title' => $track->getTitle(), 'album' => $track->getAlbum(), 'length' => $track->getLengthInSeconds());
         }
         $body = json_encode($data);
         $len = strlen($body);
         $lines = array('HTTP/1.0 200 OK', 'Date: ' . date('r'), 'Content-Type: application/json', 'Content-Length: ' . $len, 'Server: ScratchLive! Scrobbler', 'Connection: close', '', $body);
         socket_write($conn, implode("\n", $lines));
         socket_close($conn);
         L::level(L::DEBUG) && L::log(L::DEBUG, __CLASS__, "Finished handling request.", array());
     } else {
         $body = '<html><head><title>404 Not Found</title></head><body>No Dice.</body></html>';
         $len = strlen($body);
         $lines = array('HTTP/1.0 404 Not Found', 'Date: ' . date('r'), 'Content-Type: text/html', 'Content-Length: ' . $len, 'Server: ScratchLive! Scrobbler', 'Connection: close', '', $body);
         socket_write($conn, implode("\n", $lines));
         socket_close($conn);
         L::level(L::DEBUG) && L::log(L::DEBUG, __CLASS__, "Handled unknown request.", array());
     }
 }
 protected function addAllObserversFromPlugins()
 {
     foreach ($this->plugins as $id => $plugin) {
         $observers = $plugin->getObservers();
         $oc = 0;
         // observer count
         foreach ($observers as $o) {
             // we wrap every observer in a 'WithId' version
             // of the same observer which we can later use
             // to selectively pull matching observers back
             // out of the list.
             if ($o instanceof TickObserver) {
                 $this->addTickObserver(new TickObserverWithId($o, $id));
                 $oc++;
             }
             if ($o instanceof SSLDiffObserver) {
                 $this->addDiffObserver(new SSLDiffObserverWithId($o, $id));
                 $oc++;
             }
             if ($o instanceof TrackChangeObserver) {
                 $this->addTrackChangeObserver(new TrackChangeObserverWithId($o, $id));
                 $oc++;
             }
             if ($o instanceof NowPlayingObserver) {
                 $this->addNowPlayingObserver(new NowPlayingObserverWithId($o, $id));
                 $oc++;
             }
             if ($o instanceof ScrobbleObserver) {
                 $this->addScrobbleObserver(new ScrobbleObserverWithId($o, $id));
                 $oc++;
             }
         }
         L::level(L::INFO) && L::log(L::INFO, __CLASS__, "%d: %s installed", array($id, get_class($plugin)));
         L::level(L::DEBUG) && L::log(L::DEBUG, __CLASS__, "%s brought %d observers to the table", array(get_class($plugin), $oc));
     }
 }
Beispiel #27
0
 /**
  * Sometimes ScratchLive doesn't supply the length, even when it knows the file.
  * Not sure why; perhaps files that have never been analysed.
  * 
  * So, let's attempt to guess it by analysing the full file.
  */
 protected function guessLengthFromFile()
 {
     $fullpath = $this->getFullpath();
     if (strlen($fullpath) == 0) {
         L::level(L::WARNING) && L::log(L::WARNING, __CLASS__, 'Guessing MP3 length from file failed: full path was empty. Perhaps this entry was manually added?', array());
         return "0:00";
     }
     if (!$this->file_exists($fullpath)) {
         L::level(L::WARNING) && L::log(L::WARNING, __CLASS__, 'Guessing MP3 length from file failed: file not found (%s)', array($fullpath));
         return "0:00";
     }
     $external_factory = Inject::the(new ExternalRepo());
     /* @var $external_factory ExternalFactory */
     $getid3 = $external_factory->newGetID3();
     /* @var $getid3 getid3 */
     $getid3->option_tag_lyrics3 = false;
     $getid3->option_tag_apetag = false;
     $getid3->option_extra_info = true;
     $getid3->encoding = 'UTF-8';
     try {
         $info = $getid3->Analyze($fullpath);
         $playtime = $info['playtime_seconds'];
         if ($playtime) {
             L::level(L::WARNING) && L::log(L::WARNING, __CLASS__, 'Guessed MP3 length %d seconds from file.', array($playtime));
             $minutes = floor($playtime / 60);
             $seconds = $playtime % 60;
             return sprintf("%d:%02d", $minutes, $seconds);
         }
         L::level(L::WARNING) && L::log(L::WARNING, __CLASS__, 'Guessing MP3 length from file failed for an unknown reason. Hmmph.', array());
     } catch (getid3_exception $e) {
         // MP3 couldn't be analyzed.
         L::level(L::WARNING) && L::log(L::WARNING, __CLASS__, 'Guessing MP3 length from file failed: %s', array($e->getMessage()));
     }
     return "0:00";
 }
 protected function flushBuffer()
 {
     L::level(L::INFO) && L::log(L::INFO, __CLASS__, $this->out_buffer, array());
     $this->out_buffer = '';
 }
Beispiel #29
0
 protected function executeWithRetries(array $placeholders, $retry_count = 0)
 {
     if ($retry_count > self::RETRY_LIMIT) {
         L::level(L::ERROR) && L::log(L::ERROR, __CLASS__, 'Failed to execute database statement; tried %d times', array(self::RETRY_LIMIT + 1));
         return;
         // fail
     }
     if ($retry_count > 0) {
         L::level(L::INFO) && L::log(L::INFO, __CLASS__, 'Retrying database statement. Attempt number %d', array($retry_count + 1));
     }
     try {
         if (!isset($this->dbh)) {
             $this->connect();
         }
         $this->sth->execute($placeholders);
     } catch (Exception $e) {
         $this->close();
         L::level(L::WARNING) && L::log(L::WARNING, __CLASS__, 'Statement failed: %s', array($e->getMessage()));
         // retry
         $this->executeWithRetries($placeholders, $retry_count + 1);
     }
 }
 protected function groupByTimestamp(array $tracks)
 {
     $last_updated_at = 0;
     $group = array();
     L::level(L::DEBUG) && L::log(L::DEBUG, __CLASS__, 'Found %d tracks in file', array(count($tracks)));
     //usort($tracks, array($this, 'timestampSort'));
     foreach ($tracks as $track) {
         /* @var $track SSLTrack */
         if ($track->getUpdatedAt() != $last_updated_at) {
             if (!empty($group)) {
                 L::level(L::DEBUG) && L::log(L::DEBUG, __CLASS__, 'Entries found at %s', array(date('Y-m-d H:i:s', $last_updated_at)));
                 $this->payloads[] = new SSLHistoryDiffDom($group);
             }
             $last_updated_at = $track->getUpdatedAt();
             $group = array();
         }
         $group[] = $track;
     }
     if (!empty($group)) {
         L::level(L::DEBUG) && L::log(L::DEBUG, __CLASS__, 'Entries found at %s', array(date('Y-m-d H:i:s', $last_updated_at)));
         $this->payloads[$last_updated_at] = new SSLHistoryDiffDom($group);
     }
     L::level(L::DEBUG) && L::log(L::DEBUG, __CLASS__, 'Divided tracks in %d groups', array(count($this->payloads)));
 }