protected function execute($arguments = array(), $options = array()) { // initialize default context sfContext::createInstance(sfProjectConfiguration::getApplicationConfiguration('smint', 'dev', true)); // initialize the database connection $databaseManager = new sfDatabaseManager($this->configuration); $connection = $databaseManager->getDatabase($options['connection'])->getConnection(); // add your code here $tmpFilePath = smintUploadFileHelper::getUploadPath(); $tmpfname = tempnam($tmpFilePath, "uploadscript.tmp"); copy($options['filename'], $tmpfname); $newFile = new sfValidatedFile($options['filename'], "audio/mpeg", $tmpfname, null, $tmpFilePath); $fileInfo = smintUploadFileHelper::saveFile($newFile); //print_r($fileInfo); echo "originalFilename=" . urlencode($fileInfo["originalFilename"]) . "&existingUploadedFile=" . urlencode($fileInfo["filename"]) . "\n"; unlink($tmpfname); }
/** Action that is called if file has been uploaded (metadata may have been entered) * */ public function executeRelated(sfWebRequest $request) { try { // Load helpers $this->getContext()->getConfiguration()->loadHelpers('Asset'); $this->getContext()->getConfiguration()->loadHelpers('Url'); // get config $configFeaturevectortypeid = sfConfig::get('app_defaults_featurevectortypeid', 0); // get request params $reqparamtracknr = $request->getParameter('tracknr'); $filename = $request->getParameter('uploadedFilename'); $originalFilename = $request->getParameter('originalFilename'); $metadataquery = $request->getParameter('metadataquery'); // 2 possibilities: either tracknr is given or uploadedFilename if (isset($reqparamtracknr) && $reqparamtracknr != '' && $reqparamtracknr != 'undefined') { //get file via external key $tracknr = $reqparamtracknr; $fileForSearchSimilar = FilePeer::getFileByExternalKey($tracknr); //only if the file was found in the smafestore db if ($fileForSearchSimilar) { $originalFilename = $fileForSearchSimilar->getUri(); $filesavepath = $fileForSearchSimilar->getUri(); } else { throw new Exception("Could not find file in database with external_key: {$tracknr}"); } $bUploadedFile = false; } else { $originalFilename = $request->getParameter('originalFilename'); $filesavepath = smintUploadFileHelper::getUploadPath() . $filename; $bUploadedFile = true; } // variables about segment selection //$reqparamStartSegment = '10000'; // Start of segment in ms MOCKUP 10 to 20 seconds //$reqparamEndSegment = '20000'; // end of segment in ms MOCKUP $reqparamStartSegment = $request->getParameter('segmentStart'); // Start of segment in ms $reqparamEndSegment = $request->getParameter('segmentEnd'); $reqparamDuration = $request->getParameter('duration'); // end of segment in ms $aSegmSearch = array('enabled' => false, 'startSegment' => 0, 'endSegment' => 0); //$bSegmSearch = FALSE; // boolean: is this segmented search? To be set later. //$startSegment; // int value, to be set later //$endSegment; // int value, to be set later $empty_livequery = false; $empty_metadatafilteredquery = false; $omit_empty_metadataquery = $request->getParameter('omit_empty_metadataquery', false); ///// check validity of parameters if (isset($reqparamStartSegment)) { $aSegmSearch['startSegment'] = intval($reqparamStartSegment); } if (isset($reqparamEndSegment)) { $aSegmSearch['endSegment'] = intval($reqparamEndSegment); } if (isset($reqparamDuration)) { $aSegmSearch['duration'] = intval($reqparamDuration); } if (isset($reqparamStartSegment) && isset($reqparamEndSegment)) { mysfLog::log($this, "DEBUG: " . intval($reqparamStartSegment) . ", {$reqparamEndSegment} " . $aSegmSearch['startSegment']); } // for selection, both start and end must be given and of type int and greater or equal 0 // Note that the start and end times are set "inline" if (isset($reqparamStartSegment) && $aSegmSearch['startSegment'] > 0 || isset($reqparamEndSegment) && $aSegmSearch['endSegment'] > 0) { mysfLog::log($this, "DEBUG: Using segmented search with start-end in ms:" . $aSegmSearch['startSegment'] . " - " . $aSegmSearch['endSegment']); $aSegmSearch['enabled'] = TRUE; } else { mysfLog::log($this, "DEBUG: NOT using segmented search"); $aSegmSearch['enabled'] = false; } $this->exec_result = smintSmafeHelper::queryFile($filesavepath, $aSegmSearch); $results = smintSmafeHelper::getResultsOnly($this->exec_result["output"]); // $results = smintSmafeHelper::getResultsWithUri($this -> exec_result["output"]); // If we are here in a "search similar" scenario (track is in db, so it will be returned as result again) // we have to filter out the seed song if (!$bUploadedFile) { // do filtering $track_id_seed = $fileForSearchSimilar->getTrackId(); $results_no_seed = array(); foreach ($results as $key => $result) { if ($result[0] != $track_id_seed) { $results_no_seed[$key] = $result; } } $results = $results_no_seed; } if (count($results) == 0) { $empty_livequery = true; } // filter with metadata // select external_key,genre from file left join filedesc on file.external_key = filedesc.tracknr where filedesc.genre ilike '%metadata%' and track_id IN ('31469', '31465') limit 10 if (is_string($metadataquery) && strlen($metadataquery) > 0) { $bMDsearch = true; $filtered_results = $this->metadataFilter($results, $metadataquery); // omit metadata query if empty if ($omit_empty_metadataquery) { if (count($filtered_results) > 0) { // set results to filtered results if the metadata filter returns results $results = $filtered_results; } else { $empty_metadatafilteredquery = true; } } else { $results = $filtered_results; } } else { $bMDsearch = false; } // reduce to maxresults $this->limit = $this->getContext()->getConfiguration()->getSmintMaxQueryResults(); $this->results = array_slice($results, 0, $this->limit); //$this -> results = array_slice($results, 0, 50); ////// If this is segmented search, we perform re-ordering if ($aSegmSearch['enabled']) { // First, we get the length of the segments in samples mysfLog::log($this, "res " . print_r($this->results, true)); $aResultsEnhanced = array(); foreach ($this->results as $key => $value) { // check for negative segmentnr (indicates non-segment server) if ($value[1] < 0) { //throw new Exception("Negative value for segment nr. Probably the smafe server is not configured for segmented search?"); // Set dummy segments (whole track) array_push($aResultsEnhanced, array('track_id' => intval($value[0]), 'segmnr' => 0, 'dist' => doubleval($value[2]), 'start' => 0, 'end' => 0)); } else { $fvsegm = FeaturevectorsegmentPeer::getInformationOnSegment($value[0], $value[1], $configFeaturevectortypeid); $iSamplef = $fvsegm->getFile()->getSamplef(); array_push($aResultsEnhanced, array('track_id' => $fvsegm->getTrackId(), 'segmnr' => $fvsegm->getSegmentnr(), 'dist' => doubleval($value[2]), 'start' => intval($fvsegm->getStartsample() * 1000 / $iSamplef), 'end' => intval(($fvsegm->getStartsample() + $fvsegm->getLength()) * 1000 / $iSamplef))); //$value[3] = $value[1] * 262144; // this is correct for 44100 Hz samples audio //$value[4] = 262144; // this is correct for 44100 Hz samples audio } } //mysfLog::log($this, "DEBUG: " . print_r($aResultsEnhanced, true)); $aSegmSearch['resultsegments'] = array(); // Structure of $aSegmSearch['resultsegments']: // first dim: // each element corresponds to element at same position in $this -> results (and later: ->files) // second dim: // list of result segments for given track // third dim: // assoc array with start and end time for this result segment // INPUT for the aggregation algo: // - $aResultsEnhanced // - $this->results // OUTPUT // - $this -> results array of array[0]...track id , [1] segm nr, [2] distance // - $aSegmSearch['resultsegments'] (see above) switch (sfConfig::get('app_defaults_segm_search_aggregation_algo', 0)) { case 0: foreach ($aResultsEnhanced as $key => $value) { // new segment // conversion done from sample number to ms array_push($aSegmSearch['resultsegments'], array(array('start' => $value['start'], 'end' => $value['end'], 'dist' => $value['dist']))); } break; case 1: // extract 1st column (track ids) // do the actual work // $column = 0; // $result_trackids = array_map('array_slice', $this->results, array_fill(0, count( $this->results), $column), array_fill(0, count( $this->results), 1)); $result_trackids = array(); foreach ($this->results as $key => $value) { array_push($result_trackids, $value[0]); } mysfLog::log($this, "DEBUG: " . print_r($result_trackids, true)); $unique = array(); foreach ($result_trackids as $key => $value) { if (!in_array($value, $unique)) { array_push($unique, $value); } } // $unique = array_unique($result_trackids); //mysfLog::log($this, "DEBUG: " . print_r($unique, true)); foreach ($unique as $ukey => $uvalue) { // segments for $value $tmparray = array(); foreach ($aResultsEnhanced as $key => $value) { if ($uvalue == $value['track_id']) { array_push($tmparray, array('start' => $value['start'], 'end' => $value['end'], 'dist' => $value['dist'])); } } // Sort result segments ascending in start time $fCmpSegments = create_function('$a, $b', ' if ($a[\'start\'] == $b[\'start\']) { return 0; } else if ($a[\'start\'] < $b[\'start\']) { return -1; } else { return 1; } '); usort($tmparray, $fCmpSegments); // push segments to master array array_push($aSegmSearch['resultsegments'], $tmparray); } //mysfLog::log($this, "DEBUG: " . print_r($aSegmSearch['resultsegments'], true)); $this->results = $unique; break; default: throw new Exception("Bad value for app_defaults_segm_search_aggregation_algo: " . sfConfig::get('app_defaults_segm_search_aggregation_algo', 0)); break; } } else { // segmented search enabled // nothing to do, normal search } // segmented search enabled // not used in _result.php // $this -> distances = smintSmafeHelper::getDistances($this -> results); $this->files = $this->queryMetadataDatabase($this->results); //mysfLog::log($this, "DEBUG: " . print_r($this -> files, true)); // depending on whether it is an upload or not if ($bUploadedFile) { //tracknr is before underscore in filename $fileNameParts = explode("_", $filename); $tracknr = $fileNameParts[0]; $uploadedFileURL = _compute_public_path($filename, 'uploads/mp3uploads', 'mp3', false); //url_for("getAudioFile/download") . "?uploaded=" . rawurlencode($filename); // the url for getting the file via PHP, but incomplete. Format parameter is missing and will be // appended in mp3 helper class $uploadedFilePHPUrl_incomplete = url_for("getAudioFile/download", true) . "?uploaded=" . rawurlencode(basename($filename)); if ($aSegmSearch['enabled']) { $seedLabel = intval(($aSegmSearch['endSegment'] - $aSegmSearch['startSegment']) / 1000) . " seconds from {$originalFilename}"; if ($bMDsearch) { $seedlabel_topleft = "Seed track, results filtered by " . $metadataquery; } else { $seedlabel_topleft = "Seed track"; } } else { $seedLabel = $originalFilename; if ($bMDsearch) { $seedlabel_topleft = "Seed track, results filtered by " . $metadataquery; } else { $seedlabel_topleft = "Seed track"; } } } else { $queryFileMetadata = FiledescPeer::retrieveByPk($tracknr); $fileInfoName = $queryFileMetadata->getTitle() . " - " . $queryFileMetadata->getPerformers(); $uploadedFilePHPUrl_incomplete = url_for("getAudioFile/download", true) . "?tracknr=" . rawurlencode($tracknr); $uploadedFileURL = smintUploadFileHelper::getDirectFileUrl($fileForSearchSimilar->getUri()); $seedLabel = $fileInfoName; if ($bMDsearch) { $seedlabel_topleft = "Acoustic similarity, filtered by " . $metadataquery; } else { $seedlabel_topleft = "Acoustic similarity"; } } return $this->renderPartial('search/result', array('render' => 'related', 'id_prefix' => "id_prefix", 'tracknr' => $tracknr, 'uploadedFilePHPUrl_incomplete' => $uploadedFilePHPUrl_incomplete, 'uploadedFileURL' => $uploadedFileURL, 'files' => $this->files, 'queryTrackIsUploaded' => true, 'seedLabel' => $seedLabel, 'limit' => $this->limit, 'metadataquery' => $metadataquery, 'empty_livequery' => $empty_livequery, 'empty_metadatafilteredquery' => $empty_metadatafilteredquery, 'aSegmSearch' => $aSegmSearch, 'seedlabel_topleft' => $seedlabel_topleft)); } catch (Exception $e) { // an error occoured while trying to query the file mysfLog::log($this, "STARTING the QUERY failed: " . $e->getMessage()); return $this->renderPartial('search/error', array('error_message' => $e->getMessage())); } }
/** provides the file as download/streaming * Request params: * - tracknr * - fileid * - uploaded * ( either tracknr or fileid or uploaded is required) * - format optional. One of: mp3, ogg. If format is given, the file is converted to the given format, using command line invocations that are configured in app.yml * * */ public function executeDownload(sfWebRequest $request) { // write session, so it won't lock other requests session_write_close(); $reqparamUploaded = $this->getRequestParameter('uploaded'); if ($reqparamUploaded) { $filename = smintUploadFileHelper::getUploadPath() . $reqparamUploaded; } else { $tracknr = $this->getRequestParameter('tracknr'); if ($tracknr) { $file = FilePeer::getFileByExternalKey($tracknr); $filekey = $tracknr; } else { # check if file.id is given $fileid = $this->getRequestParameter('fileid'); $file = FilePeer::retrieveByPK($fileid); $filekey = $fileid; } //check if a file was found matching tracknr, else exit with 404 if ($file) { $filename = $file->getUri(); } else { $this->forward404("file not found in database."); } } //check if a tracknr is given, otherwise exit with 404 if (!$filename) { $this->forward404("Invalid query! Provide tracknr, fileid or uploaded to get a file."); } if (file_exists($filename)) { //check if file is inside the folder configured in smint/config/app.yml // or inside the upload folder $mp3Path = dirname(sfConfig::get('app_files_mp3path') . "/file"); if (strpos($filename, $mp3Path) === false && strpos($filename, smintUploadFileHelper::getUploadPath()) === false) { $this->forward404("file: {$filename} is outside of the configured path (app.yml): {$mp3Path}. Accessing files outside the path is not allowed. Check app.yml and URI in file table."); } // ----------------------------------------------- // -------------- check for format -------------- // if no format is given, $reqparamFormat = $this->getRequestParameter('format'); if ($reqparamFormat) { if (substr($filename, -3) === $reqparamFormat) { mysfLog::log($this, "INFO: format parameter equals original audio file suffix. No conversion."); if ($reqparamFormat === "mp3") { $contenttype = "audio/mpeg"; } else { $contenttype = "audio/{$reqparamFormat}"; } } else { // conversion if ($reqparamFormat === "ogg") { $filename = smintFileserverHelper::doFileConversion($filename, $reqparamFormat); $contenttype = "audio/ogg"; } else { if ($reqparamFormat === "mp3") { $filename = smintFileserverHelper::doFileConversion($filename, $reqparamFormat); $contenttype = "audio/mpeg"; } else { if ($reqparamFormat === "waveform") { $filename = smintFileserverHelper::doFileConversion($filename, $reqparamFormat); $contenttype = "application/txt"; } else { if ($reqparamFormat === "png") { $waveformfilename = smintFileserverHelper::doFileConversion($filename, "waveform"); $wfdata = split(", ", file_get_contents($waveformfilename)); //mysfLog::log($this, print_r($wfdata, true)); // how much detail we want. Larger number means less detail // (basically, how many bytes/frames to skip processing) // the lower the number means longer processing time // EP: in SMINT we do not chagne this. To change the detail, edit your waveform_resolution // config param in app.yml! define("DETAIL", 1); // get user vars from form $width = $this->getRequestParameter('width') ? rawurldecode($this->getRequestParameter('width')) : 640; $height = $this->getRequestParameter('height') ? rawurldecode($this->getRequestParameter('height')) : 100; $foreground = $this->getRequestParameter('fg') ? rawurldecode($this->getRequestParameter('fg')) : "#4D4D4D"; $background = $this->getRequestParameter('bg') ? rawurldecode($this->getRequestParameter('bg')) : "#ffffff"; $maxval = 0; $factor = sfConfig::get('app_defaults_waveform_factor', 0.8); // create original image width based on amount of detail $img = imagecreatetruecolor(sizeof($wfdata) / DETAIL, $height); // apply factor to the data //$wfdata_factor = array_map("this->pow_func", $wfdata); for ($i = 0; $i < sizeof($wfdata); $i += DETAIL) { $wfdata[$i] = pow(abs($wfdata[$i]), $factor); } $datamaxval = max(array_map("abs", $wfdata)); $normconstant = doubleval($height) / doubleval($datamaxval); for ($i = 0; $i < sizeof($wfdata); $i += DETAIL) { $wfdata[$i] = $wfdata[$i] * $normconstant; } /* for ($i = 0; $i < sizeof($wfdata); $i += DETAIL) { if (abs($wfdata[$i]) > $maxval) { $maxval = $wfdata[$i]; } } if ($maxval < 40) { for ($i = 0; $i < sizeof($wfdata); $i += DETAIL) { $wfdata[$i] = pow(abs($wfdata[$i]), 1.4); } } * */ // fill background of image if ($background == "") { imagesavealpha($img, true); $transparentColor = imagecolorallocatealpha($img, 0, 0, 0, 127); imagefill($img, 0, 0, $transparentColor); } else { list($r, $g, $b) = smintTools::html2rgb($background); imagefilledrectangle($img, 0, 0, sizeof($wfdata) / DETAIL, $height, imagecolorallocate($img, $r, $g, $b)); } // generate foreground color list($r, $g, $b) = smintTools::html2rgb($foreground); // loop through frames/bytes of wav data as genearted above for ($d = 0; $d < sizeof($wfdata); $d += DETAIL) { // relative value based on height of image being generated // data values can range between -127 and 128 $v = $wfdata[$d]; //$v = pow($v, sfConfig::get('app_defaults_waveform_factor', 0.8)); // draw the line on the image using the $v value and centering it vertically on the canvas imageline($img, $d / DETAIL, ($height - $v) / 2, $d / DETAIL, ($height + $v) / 2, imagecolorallocate($img, $r, $g, $b)); } // want it resized? if ($width != imagesx($img)) { // resample the image to the proportions defined in the form $rimg = imagecreatetruecolor($width, $height); // save alpha from original image imagesavealpha($rimg, true); imagealphablending($rimg, false); // copy to resized imagecopyresampled($rimg, $img, 0, 0, 0, 0, $width, $height, sizeof($wfdata) / DETAIL, $height); $img = $rimg; } $contenttype = "image/png"; header("Content-type: {$contenttype}"); imagepng($img); imagedestroy($img); // dont render view return sfView::NONE; } else { $error_message = "ERROR: Format {$reqparamFormat} not valid"; mysfLog::log($this, $error_message); throw new Exception($error_message); } } } } } } else { mysfLog::log($this, "INFO: format parameter not given, sending the original file "); // assuming file ending as content type. Just an approximation $contenttype = "audio/" . substr($filename, -3); } // do a redirect to file to have apache handle it $this->redirect(smintUploadFileHelper::getDirectFileUrl_for_uploads($filename)); /* alternate version of redirect (not using symf framework) * does not work better :-( * $url = smintUploadFileHelper::getDirectFileUrl_for_uploads($filename); $statusCode = 302; // redirect $response = $this->context->getResponse(); $response->clearHttpHeaders(); $response->setStatusCode($statusCode); $response->setHttpHeader('Location', $url); $response->send(); throw new sfStopException(); // we do not reach this part b/o the redirect! * */ // ------------ delegate to helper for download // serves file, obeying the range header smintFileserverHelper::serve_file_resumable($this->getResponse(), $filename, $contenttype); // dont render view return sfView::NONE; //return sfView::HEADER_ONLY; } else { $missingfile = $filename ? $filename : "No filename found!"; $this->forward404("file for tracknr: not found: " . $missingfile); } }
public function configure() { $this->setWidgets(array('mp3' => new sfWidgetFormInputFile(array(), array('size' => 30)), 'metadataquery' => new sfWidgetFormInputText())); $this->setValidators(array('metadataquery' => new sfValidatorString(array('required' => false)), 'mp3' => new sfValidatorFile(array('required' => true, 'max_size' => '30000000', 'path' => smintUploadFileHelper::getUploadPath())))); $this->widgetSchema->setNameFormat('fileupload[%s]'); }
/** * Performs the file conversion, ie, calls external tool, checks if it worked correctly, and returns the filename of the output file * Note that the output files can be deleted safely. On the other hand this function also checks if the file has already been converted. * If so, it will not be converted a second time. * @param filename the filename including path (local) * @param formatcode Currently these codes are supported: * - ogg * - mp3 * - waveform * - waveformpng * * * To add another type: * - Add command_XXX in app.yml. The command must follow the same conventions as command_mp3 and _ogg ($INfile, ...) * - XXX is also used as the file suffix for the output file */ public static function doFileConversion($filename, $formatcode = "ogg") { $exec_output = array(); $exec_err = array(); $current_date = date("_Ymd_His_"); // get command as configured in app.yml $exec_cmd_raw = mysfConfig::get('app_conversion_setting_command_' . $formatcode, ""); // replace placeholder with real file name, infile $exec_cmd = str_replace('$INfile', escapeshellcmd($filename), $exec_cmd_raw); // replace outfile placeholder. outfile is : upload dir, basename of infile, and ogg suffix if ($formatcode === 'waveform') { // extra file ending for waveform, since waveform is not recognized by apache $outfile = smintUploadFileHelper::getUploadPath() . basename($filename) . "." . $formatcode . ".txt"; } else { $outfile = smintUploadFileHelper::getUploadPath() . basename($filename) . "." . $formatcode; } $exec_cmd = str_replace('$OUTfile', escapeshellcmd($outfile), $exec_cmd); // check for pixels per second variable. If found, replace it with config param if (substr_count($exec_cmd, '$PIXELSPERSECOND') > 0) { $pixelspersecond = sfConfig::get('app_defaults_waveform_resolution'); $exec_cmd = str_replace('$PIXELSPERSECOND', escapeshellcmd($pixelspersecond), $exec_cmd); } $exec_cmd_escaped = $exec_cmd; // before conversion check if file exists already if (file_exists($outfile)) { mysfLog::log(self::$context, "INFO: file {$outfile} exists, using it."); } else { mysfLog::log(self::$context, "INFO: starting conversion. Command = {$exec_cmd_escaped}"); // executing, redirecting stderr to stdout exec($exec_cmd_escaped . " 2>&1", $exec_err, $exec_result); if ($exec_result != 0 || !file_exists($outfile)) { $result_array = array("command" => $exec_cmd_escaped, "result" => $exec_result, "error" => $exec_err); $error_message = "ERROR during conversion. " . print_r($result_array, true); mysfLog::log(self::$context, $error_message); throw new Exception($error_message); } mysfLog::log(self::$context, "INFO: conversion done"); } return $outfile; }