SSL puts a lot of useful information into the history file, including the full path to the MP3, bpm, key, etc., as well as history-oriented data such as start and end time, which deck the track was played on, played or skipped, manually added, etc. There is also an incrementing integer primary key (which I've called 'row'). History file Tracks also have a concept of their own 'status', in the sense of 'NEW', 'PLAYING', 'PLAYED' or 'SKIPPED'. (@see SSLRealtimeModel for more detail). These states are derived from a combination of the 'played' field, which is either 0 or 1 corresponding to whether or not the row is 'green' in the SSL interface, and whether or not an 'endtime' is present.
Author: ben
Inheritance: extends SSLStruct
    public function notifyNowPlaying(SSLTrack $track = null)
    {
        $nicecastOutput = <<<EOF
Title: {$track->getTitle()}
Artist: {$track->getArtist()}
Album: {$track->getAlbum()}
Time: {$track->getLength()}
EOF;
        file_put_contents($this->getFilename(), $nicecastOutput);
    }
Exemplo n.º 2
0
 public function getBuyLink(SSLTrack $track)
 {
     $en_api_key = trim(file_get_contents('SevenDigital.key'));
     $en_url = "http://developer.echonest.com/api/v4/song/search?api_key=%s&format=json&results=1&artist=%s&title=%s&bucket=id:7digital&bucket=id:7digital&limit=true&bucket=tracks";
     $real_en_url = sprintf($en_url, $en_api_key, rawurlencode($track->getArtist()), rawurlencode($track->getTitle()));
     //var_dump($real_en_url);
     $en_result = file_get_contents($real_en_url);
     $en_result = json_decode($en_result, true);
     //        var_dump(
     //            levenshtein(mb_strtolower($en_result['response']['songs'][0]['title']), mb_strtolower($track->getTitle())),
     //            $en_result['response'],
     //            $track->getTitle()
     //        );
     if (levenshtein(mb_strtolower($en_result['response']['songs'][0]['title']), mb_strtolower($track->getTitle())) < 5) {
         foreach ($en_result['response']['songs'][0]['tracks'] as $track) {
             if ($track['catalog'] == '7digital') {
                 $id_parts = explode(':', $track['foreign_id']);
                 $seven_digital_id = $id_parts[2];
                 break;
             }
         }
     }
     if (!isset($seven_digital_id)) {
         return false;
     }
     $sd_url = 'http://api.7digital.com/1.2/track/details?trackid=%d&oauth_consumer_key=%s&country=GB';
     $real_sd_url = sprintf($sd_url, $seven_digital_id, 'musichackday');
     $sd_result = @file_get_contents($real_sd_url);
     if (empty($sd_result)) {
         return '';
     }
     //var_dump($sd_result);
     $xml = new DOMDocument();
     $xml->loadXML($sd_result);
     $xpath = new DOMXpath($xml);
     $urls = $xpath->query('//track/url/text()');
     /* @var $urls DomNodeList */
     return @$urls->item(0)->textContent;
     //        $api = new SevenDigitalApi();
     //        $api->OutputType = 'json';
     //        $api->ConsumerId = 'musichackday';
     //        var_dump($track->getArtist() . ' ' . $track->getTitle());
     //        $results = $api->GetTracksByTitle($track->getArtist() . ' ' . $track->getTitle());
     //        $resultsObj = json_decode($results);
     //        var_dump($results);
     //        if(isset($resultsObj->response->searchResults->searchResult[0]))
     //        {
     //            return $resultsObj->response->searchResults->searchResult[0]->release->url;
     //        }
     //        return false;
 }
Exemplo n.º 3
0
 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);
 }
 /**
  * @return SSLHistoryDom
  */
 protected function readCSV($filename)
 {
     $fp = fopen($filename, 'r');
     if ($fp === false) {
         throw new RuntimeException("Could not open CSV file {$filename}");
     }
     $tracks = array();
     $field_order = array('row', 'deck', 'artist', 'title', 'starttime', 'endtime', 'played', 'added', 'updatedAt', 'playtime', 'length');
     while (false !== ($fs = fgetcsv($fp))) {
         if ($fs) {
             foreach ($field_order as $i => $f_name) {
                 isset($fs[$i]) && ($fields[$f_name] = $fs[$i]);
             }
             $track = new SSLTrack();
             $track->populateFrom($fields);
             $tracks[] = $track;
         }
     }
     if (empty($tracks)) {
         throw new InvalidArgumentException("File {$filename} contained no records");
     }
     fclose($fp);
     return $tracks;
 }
 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;
 }
 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()));
     }
 }
 /**
  * This version of setLengthIfUnknown() looks in the cache that the track was
  * constructed with for a track with the same row ID. If it finds one, it 
  * inquired if this (possibly expensive) question has already been answered.
  * If it has, we use the answer from the cache.
  * 
  * If no answer is found in the cache, we fall back to scanning the file with
  * getID3 in the usual way. If results are found we are sure to poke them 
  * back in to the cache.
  * 
  * This is necessary because ScratchLive! can create several objects for the
  * same row (as it will write multiple, updated, versions of the row to the
  * history file over time). Several of these may be missing expensive info,
  * so we want to cache it from object to object.
  * 
  */
 public function setLengthIfUnknown()
 {
     if (!isset($this->length)) {
         // have a go at pulling it from the cache, if it's in the cache!
         $cached_track = $this->track_cache->getByRow($this->getRow());
         if ($cached_track) {
             $cached_length = $cached_track->getLength();
             if (isset($cached_length)) {
                 $this->length = $cached_length;
             }
         }
         parent::setLengthIfUnknown();
         // save in the cache, for next time.
         if (isset($this->length)) {
             if (isset($cached_track)) {
                 $cached_track->length = $this->length;
             } else {
                 $this->track_cache->register($this);
             }
         }
     }
 }
Exemplo n.º 8
0
 public function register(SSLTrack $track)
 {
     $this->tracks[$track->getRow()] = $track;
 }
 public function newScrobblerTrackModel(SSLTrack $track)
 {
     $this->call_count++;
     $track_row = $track->getRow();
     $this->decks[$track_row] = parent::newScrobblerTrackModel($track);
     return $this->decks[$track_row];
 }
Exemplo n.º 10
0
 public function getRow()
 {
     return $this->track->getRow();
 }
 public function notifyScrobble(SSLTrack $track)
 {
     $this->growler->notify('alert', 'Scrobbling', $track->getFullTitle());
     L::level(L::INFO) && L::log(L::INFO, __CLASS__, '>> Scrobbling: >> %s', array($track->getFullTitle()));
 }
Exemplo n.º 12
0
 public function __toString()
 {
     return 'Track started: ' . $this->track->getArtist() . ' - ' . $this->track->getTitle();
 }
 private function timestampSort(SSLTrack $a, SSLTrack $b)
 {
     $a_ts = $a->getUpdatedAt();
     $b_ts = $b->getUpdatedAt();
     if ($a_ts > $b_ts) {
         return 1;
     }
     if ($a_ts == $b_ts) {
         return 0;
     }
     return -1;
 }
Exemplo n.º 14
0
 public function allTimePlays(SSLTrack $track)
 {
     $statement = $this->dbo->prepare("SELECT COUNT(*) FROM history WHERE title=:title AND artist=:artist AND played=1");
     $statement->bindValue('title', $track->getTitle());
     $statement->bindValue('artist', $track->getArtist());
     $results = $statement->execute()->fetchArray();
     if ($results === false) {
         return 0;
     }
     return $results[0];
 }
Exemplo n.º 15
0
 public function getInfo(SSLTrack $track)
 {
     $vars = array();
     $vars['apiKey'] = $this->config['api_key'];
     $vars['secret'] = $this->config['api_secret'];
     $auth = new lastfmApiAuth('setsession', $vars);
     $lfm = new lastfmApi();
     /* @var $trackP lastfmApiTrack */
     /* @var $artistP lastfmApiArtist */
     $trackP = $lfm->getPackage($auth, 'track');
     $artistP = $lfm->getPackage($auth, 'artist');
     //$track_info = $trackP->getInfo(array('artist' => $track->getArtist(), 'title' => $track->getTitle()));
     $artist_info = $artistP->getInfo(array('artist' => $track->getArtist()));
     $artist_images = $artistP->getImages(array('artist' => $track->getArtist()));
     $all = array('artist' => $artist_info, 'images' => $artist_images);
     return $all;
 }
 protected function transitionFromNewToSkipped(SSLTrack $track)
 {
     $this->max_row = max($track->getRow(), $this->max_row);
     $this->track = null;
     $this->status = $track->getStatus();
     // don't touch start time
     $this->end_time = time();
     // don't touch previous track
 }
Exemplo n.º 17
0
 protected function getBestTrack(SSLTrack $track)
 {
     $search = $this->doMixcloudCall('best track', 'http://api.mixcloud.com/search/?q=%s+%s&type=track', array(urlencode($track->getArtist()), urlencode($track->getTitle())));
     if (isset($search['error'])) {
         throw new Exception('Error from Mixcloud: ' . $search['error']['message']);
     }
     $potential_tracks = array();
     foreach ($search['data'] as $result) {
         $potential_track = array('artist' => $result['artist']['name'], 'title' => $result['name'], 'key' => $result['key']);
         $score = levenshtein($track->getArtist() . ' ' . $track->getTitle(), $result['artist']['name'] . ' ' . $result['name']);
         $potential_tracks[$score] = $result['key'];
     }
     if ($potential_tracks) {
         ksort($potential_tracks);
         $best_track = array_shift($potential_tracks);
         L::level(L::INFO) && L::log(L::INFO, __CLASS__, 'Best track match: %s', array($best_track));
         return $best_track;
     }
     throw new Exception('no track match for ' . $track->getFullTitle());
 }
Exemplo n.º 18
0
 /**
  * It's an SQL error to provide the wrong number variable bindings to a prepared
  * statement, so we must trim down the number we pass based on which actually
  * appeared in the SQL statement.
  */
 protected function getPlaceholdersFromTrack(SSLTrack $track, array $placeholder_map)
 {
     $placeholders = array();
     if ($placeholder_map[':track']) {
         $placeholders[':track'] = $track->getFullTitle();
     }
     if ($placeholder_map[':artist']) {
         $placeholders[':artist'] = $track->getArtist();
     }
     if ($placeholder_map[':title']) {
         $placeholders[':title'] = $track->getTitle();
     }
     if ($placeholder_map[':album']) {
         $placeholders[':album'] = $track->getAlbum();
     }
     if ($placeholder_map[':key']) {
         $placeholders[':key'] = $this->key;
     }
     return $placeholders;
 }
Exemplo n.º 19
0
 protected function startTrack(SSLTrack $started_track)
 {
     $started_row = $started_track->getRow();
     foreach ($this->now_playing_queue as $i => $scrobble_model) {
         /* @var $scrobble_model ScrobblerTrackModel */
         if ($scrobble_model->getRow() == $started_row) {
             // do not double-add to the queue.
             return;
         }
     }
     // Put new tracks last in the queue for the purposes of determining what's now playing.
     // This means that tracks should transition to "Now Playing" when the previous track is stopped or taken off the deck.
     $scrobble_model = $this->factory->newScrobblerTrackModel($started_track);
     $scrobble_model_row = $scrobble_model->getRow();
     if ($scrobble_model_row != $started_row) {
         throw new RuntimeException("Row mismatch! Asked for {$started_row}, got {$scrobble_model_row}");
     }
     $this->now_playing_queue[] = $scrobble_model;
     L::level(L::INFO) && L::log(L::INFO, __CLASS__, 'enqueued track %s', array($started_track->getFullTitle()));
     L::level(L::DEBUG) && L::log(L::DEBUG, __CLASS__, 'queue length is now %d', array(count($this->now_playing_queue)));
 }