public static function import($new_songs, $force = false) { $db_stats = array('skipped' => 0, 'updated' => 0, 'inserted' => 0, 'deleted' => 0); if (empty($new_songs)) { return false; } Debug::startTimer('Import data into database'); $em = self::getEntityManager(); $existing_hashes = self::getHashes(); $existing_ids = self::getIds(); $unused_hashes = $existing_hashes; $song_ids = Song::getIds(); $i = 0; foreach ($new_songs as $song_hash => $processed) { if (!in_array($song_hash, $song_ids)) { Song::getOrCreate($processed); } if (isset($existing_hashes[$song_hash])) { if ($force && $existing_hashes[$song_hash] == $processed['id']) { $db_stats['updated']++; $record = self::find($processed['id']); } else { $db_stats['skipped']++; $record = null; } } else { if (isset($existing_ids[$processed['id']])) { $db_stats['updated']++; $record = self::find($processed['id']); } else { $db_stats['inserted']++; $record = new self(); } } if ($record instanceof self) { $existing_ids[$processed['id']] = $processed['hash']; $existing_hashes[$processed['hash']] = $processed['id']; $record->fromArray($processed); $em->persist($record); } unset($unused_hashes[$song_hash]); $i++; if ($i % 200 == 0) { $em->flush(); $em->clear(); } } $em->flush(); $em->clear(); // Clear out any songs not found. $hashes_remaining = array_keys($unused_hashes); $db_stats['deleted'] = count($hashes_remaining); $em->createQuery('DELETE FROM ' . __CLASS__ . ' e WHERE e.hash IN (:hashes)')->setParameter('hashes', $hashes_remaining)->execute(); Debug::endTimer('Import data into database'); Debug::print_r($db_stats); return $db_stats; }
/** * Process a single audio stream's NowPlaying info. * * @param StationStream $stream * @param Station $station * @return array Structured NowPlaying Data */ public static function processAudioStream(StationStream $stream, Station $station, $force = false) { $current_np_data = (array) $stream->nowplaying_data; // Only process non-default streams on odd-numbered "segments" to improve performance. if (!$stream->is_default && !$force && NOWPLAYING_SEGMENT % 2 == 0 && !empty($current_np_data)) { return $current_np_data; } $np = StationStream::api($stream); $custom_class = Station::getStationClassName($station->name); $custom_adapter = '\\PVL\\RadioAdapter\\' . $custom_class; if (class_exists($custom_adapter)) { $np_adapter = new $custom_adapter($stream, $station); } elseif ($stream->type == "icecast") { $np_adapter = new \PVL\RadioAdapter\IceCast($stream, $station); } elseif ($stream->type == "icebreath") { $np_adapter = new \PVL\RadioAdapter\IceBreath($stream, $station); } elseif ($stream->type == "shoutcast2") { $np_adapter = new \PVL\RadioAdapter\ShoutCast2($stream, $station); } elseif ($stream->type == "shoutcast1") { $np_adapter = new \PVL\RadioAdapter\ShoutCast1($stream, $station); } else { return array(); } Debug::log('Adapter Class: ' . get_class($np_adapter)); $stream_np = $np_adapter->process(); $np = array_merge($np, $stream_np['meta']); $np['listeners'] = $stream_np['listeners']; // Pull from current NP data if song details haven't changed. $current_song_hash = Song::getSongHash($stream_np['current_song']); if (strcmp($current_song_hash, $current_np_data['current_song']['id']) == 0) { $np['current_song'] = $current_np_data['current_song']; $np['song_history'] = $current_np_data['song_history']; } else { if (empty($stream_np['current_song']['text'])) { $np['current_song'] = array(); $np['song_history'] = $station->getRecentHistory($stream); } else { // Register a new item in song history. $np['current_song'] = array(); $np['song_history'] = $station->getRecentHistory($stream); // Determine whether to log this song play for analytics. $log_radio_play = $stream->is_default && $station->category == 'audio'; $song_obj = Song::getOrCreate($stream_np['current_song'], $log_radio_play); $sh_obj = SongHistory::register($song_obj, $station, $stream, $np); // Compose "current_song" object for API. $current_song = Song::api($song_obj); $current_song['sh_id'] = $sh_obj->id; $current_song['score'] = SongVote::getScoreForStation($song_obj, $station); $vote_urls = array(); $vote_functions = array('like', 'dislike', 'clearvote'); foreach ($vote_functions as $vote_function) { $vote_urls[$vote_function] = \PVL\Url::api(array('module' => 'api', 'controller' => 'song', 'action' => $vote_function, 'sh_id' => $sh_obj->id)); } $current_song['vote_urls'] = $vote_urls; $external = $song_obj->getExternal(); if ($external) { $current_song['external'] = $song_obj->getExternal(); } $np['current_song'] = $current_song; } } $stream->nowplaying_data = $np; return $np; }
/** @PrePersist */ public function preSave() { $this->song = Song::getOrCreate(array('text' => $this->artist . ' - ' . $this->title, 'artist' => $this->artist, 'title' => $this->title)); }
public function songconfirmAction() { // Handle files submitted directly to page. $ignore_files = (int) $this->getParam('ignore_files'); $request = $this->di->get('request'); if ($request->hasFiles() && !$ignore_files) { $this->_processSongUpload(); } // Validate song identifier token. $token = $this->_getSongHashToken(); if (!$this->_validateSongHash($token)) { return $this->redirectFromHere(array('action' => 'song')); } // Check that any stations were selected if (!$this->hasParam('stations')) { throw new \DF\Exception\DisplayOnly('You did not specify any stations!'); } // Check for uploaded songs. $temp_dir_name = 'song_uploads'; $temp_dir = DF_INCLUDE_TEMP . DIRECTORY_SEPARATOR . $temp_dir_name; $all_files = glob($temp_dir . DIRECTORY_SEPARATOR . $token . '*.mp3'); if (empty($all_files)) { throw new \DF\Exception\DisplayOnly('No files were uploaded!'); } $songs = array(); $getId3 = new GetId3(); $getId3->encoding = 'UTF-8'; foreach ($all_files as $song_file_base) { $song_file_path = $temp_dir . DIRECTORY_SEPARATOR . basename($song_file_base); // Attempt to analyze the MP3. $audio = $getId3->analyze($song_file_path); if (isset($audio['error'])) { @unlink($song_file_path); throw new \DF\Exception\DisplayOnly(sprintf('Error at reading audio properties with GetId3: %s.', $audio['error'][0])); } if (isset($audio['tags']['id3v1']['title'])) { $song_data = array('title' => $audio['tags']['id3v1']['title'][0], 'artist' => $audio['tags']['id3v1']['artist'][0]); } elseif (isset($audio['tags']['id3v2']['title'])) { $song_data = array('title' => $audio['tags']['id3v2']['title'][0], 'artist' => $audio['tags']['id3v2']['artist'][0]); } else { @unlink($song_file_path); continue; } // Check if existing submission exists. $song = Song::getOrCreate($song_data); $existing_submission = SongSubmission::getRepository()->findOneBy(array('hash' => $song->id)); if ($existing_submission instanceof SongSubmission) { @unlink($song_file_path); continue; } // Create record in database. $metadata = array('File Format' => strtoupper($audio['fileformat']), 'Play Time' => $audio['playtime_string'], 'Bitrate' => round($audio['audio']['bitrate'] / 1024) . 'kbps', 'Bitrate Mode' => strtoupper($audio['audio']['bitrate_mode']), 'Channels' => $audio['audio']['channels'], 'Sample Rate' => $audio['audio']['sample_rate']); $record = new SongSubmission(); $record->song = $song; $auth = $this->di->get('auth'); $record->user = $auth->getLoggedInUser(); $record->title = $song_data['title']; $record->artist = $song_data['artist']; $record->song_metadata = $metadata; $record->stations = $this->getParam('stations'); $song_download_url = $record->uploadSong($song_file_path); $record->save(); // Append information to e-mail to stations. $song_row = array('Download URL' => '<a href="' . $song_download_url . '" target="_blank">' . $song_download_url . '</a>', 'Title' => $song_data['title'], 'Artist' => $song_data['artist']) + $metadata; $songs[] = $song_row; } if (!empty($songs)) { // Notify all existing managers. $network_administrators = Action::getUsersWithAction('administer all'); $email_to = Utilities::ipull($network_administrators, 'email'); // Pull list of station managers for the specified stations. $station_managers = array(); $short_names = Station::getShortNameLookup(); foreach ($this->getParam('stations') as $station_key) { if (isset($short_names[$station_key])) { $station_id = $short_names[$station_key]['id']; $station = Station::find($station_id); foreach ($station->managers as $manager) { $station_managers[] = $manager->email; } } } $email_to = array_merge($email_to, $station_managers); // Trigger e-mail notice. if (!empty($email_to)) { \DF\Messenger::send(array('to' => $email_to, 'subject' => 'New Song(s) Submitted to Station', 'template' => 'newsong', 'vars' => array('songs' => $songs))); } } // Have to manually call view because a view was already rendered (e-mail was sent). // TODO: Fix this. It's dumb. $this->view->songs = $songs; return $this->view->render('submit', 'songconfirm'); }