liberty
[ class tree: liberty ] [ index: liberty ] [ all elements ]

Source for file mime.audio.php

Documentation is available at mime.audio.php

  1. <?php
  2. /**
  3.  * @version        $Header$
  4.  *
  5.  * @author        xing  <xing@synapse.plus.com>
  6.  * @version        $Revision$
  7.  *  created        Thursday May 08, 2008
  8.  * @package        liberty
  9.  * @subpackage    liberty_mime_handler
  10.  ***/
  11.  
  12. /**
  13.  * setup
  14.  */
  15. global $gLibertySystem;
  16.  
  17. /**
  18.  *  This is the name of the plugin - max char length is 16
  19.  * As a naming convention, the liberty mime handler definition should start with:
  20.  * PLUGIN_MIME_GUID_
  21.  */
  22. define'PLUGIN_MIME_GUID_AUDIO''mimeaudio' );
  23.  
  24. $pluginParams array (
  25.     // Set of functions and what they are called in this paricular plugin
  26.     // Use the GUID as your namespace
  27.     'preload_function'    => 'mime_audio_preload',
  28.     'verify_function'     => 'mime_default_verify',
  29.     'store_function'      => 'mime_audio_store',
  30.     'update_function'     => 'mime_audio_update',
  31.     'load_function'       => 'mime_audio_load',
  32.     'download_function'   => 'mime_default_download',
  33.     'expunge_function'    => 'mime_default_expunge',
  34.     // Brief description of what the plugin does
  35.     'title'               => 'Listen to uploaded Audio files',
  36.     'description'         => 'This plugin will extract as much information about an uploaded audio file as possible and allow you to listen to it on the website using a streaming player.',
  37.     // Templates to display the files
  38.     'view_tpl'            => 'bitpackage:liberty/mime/audio/view.tpl',
  39.     'inline_tpl'          => 'bitpackage:liberty/mime/audio/inline.tpl',
  40.     'storage_tpl'         => 'bitpackage:liberty/mime/audio/storage.tpl',
  41.     'attachment_tpl'      => 'bitpackage:liberty/mime/audio/attachment.tpl',
  42.     'edit_tpl'            => 'bitpackage:liberty/mime/audio/edit.tpl',
  43.     // url to page with options for this plugin
  44.     'plugin_settings_url' => LIBERTY_PKG_URL.'admin/plugins/mime_audio.php',
  45.     // This should be the same for all mime plugins
  46.     'plugin_type'         => MIME_PLUGIN,
  47.     // Set this to TRUE if you want the plugin active right after installation
  48.     'auto_activate'       => FALSE,
  49.     // Help page on bitweaver.org
  50.     //'help_page'           => 'LibertyMime+Audio+Plugin',
  51.     // this should pick up all audio
  52.     'mimetypes'           => array(
  53.         '#audio/.*#i',
  54.     ),
  55. );
  56. $gLibertySystem->registerPluginPLUGIN_MIME_GUID_AUDIO$pluginParams );
  57.  
  58. /**
  59.  * mime_audio_preload This function is loaded on every page load before anything happens and is used to load required scripts.
  60.  * 
  61.  * @access public
  62.  * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  63.  */
  64. function mime_audio_preload({
  65.     global $gBitThemes;
  66.     $gBitThemes->loadJavascriptUTIL_PKG_PATH."javascript/flv_player/swfobject.js"FALSE25 );
  67. }
  68.  
  69. /**
  70.  * Store the data in the database
  71.  * 
  72.  * @param array $pStoreRow File data needed to store details in the database - sanitised and generated in the verify function
  73.  * @access public
  74.  * @return TRUE on success, FALSE on failure - $pStoreRow['errors'] will contain reason
  75.  */
  76. function mime_audio_store&$pStoreRow {
  77.     // this will set the correct pluign guid, even if we let default handle the store process
  78.     $pStoreRow['attachment_plugin_guid'PLUGIN_MIME_GUID_AUDIO;
  79.     $pStoreRow['log'array();
  80.  
  81.     // if storing works, we process the audio
  82.     if$ret mime_default_store$pStoreRow )) {
  83.         if!mime_audio_converter$pStoreRow )) {
  84.             // if it all goes tits up, we'll know why
  85.             $pStoreRow['errors'$pStoreRow['log'];
  86.             $ret FALSE;
  87.         }
  88.     }
  89.     return $ret;
  90. }
  91.  
  92. /**
  93.  * mime_audio_update
  94.  * 
  95.  * @param array $pStoreRow 
  96.  * @access public
  97.  * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  98.  */
  99. function mime_audio_update&$pStoreRow$pParams NULL {
  100.     $ret FALSE;
  101.     ifBitBase::verifyId$pStoreRow['attachment_id')) {
  102.         $pStoreRow['log'array();
  103.  
  104.         // set the correct pluign guid, even if we let default handle the store process
  105.         $pStoreRow['attachment_plugin_guid'PLUGIN_MIME_GUID_AUDIO;
  106.         // remove the entire directory
  107.         $pStoreRow['unlink_dir'TRUE;
  108.  
  109.         // if storing works, we process the audio
  110.         if!empty$pStoreRow['upload'&& $ret mime_default_update$pStoreRow )) {
  111.             if!mime_audio_converter$pStoreRow )) {
  112.                 // if it all goes tits up, we'll know why
  113.                 $pStoreRow['errors'$pStoreRow['log'];
  114.                 $ret FALSE;
  115.             }
  116.         }
  117.  
  118.         // if there was no upload we'll process the file parameters
  119.         ifempty$pStoreRow['upload'&& !empty$pParams['meta')) {
  120.             // update our local version of the file
  121.             $file STORAGE_PKG_PATH.$pStoreRow['dest_branch'];
  122.             ifis_filedirname$file ).'/bitverted.mp3' )) {
  123.                 $verted dirname$file ).'/bitverted.mp3';
  124.             elseifis_filedirname$file ).'/bitverted.m4a' )) {
  125.                 $verted dirname$file ).'/bitverted.m4a';
  126.             }
  127.  
  128.             // update audio tags of converted and original file (ignore errors since these might be m4a)
  129.             mime_audio_update_tags$verted$pParams['meta');
  130.             mime_audio_update_tags$file$pParams['meta');
  131.  
  132.             // finally we update the meta table data
  133.             if!LibertyMime::storeMetaData$pStoreRow['attachment_id']'ID3'$pParams['meta')) {
  134.                 $log['store_meta'"There was a problem storing the meta data in the database";
  135.             }
  136.  
  137.             ifempty$log )) {
  138.                 $ret TRUE;
  139.             else {
  140.                 $pStoreRow['errors'$log;
  141.             }
  142.         }
  143.     }
  144.     return $ret;
  145. }
  146.  
  147. /**
  148.  * Load file data from the database
  149.  * 
  150.  * @param array $pFileHash Contains all file information
  151.  * @param array $pPrefs Attachment preferences taken liberty_attachment_prefs
  152.  * @param array $pParams Parameters for loading the plugin - e.g.: might contain values from the view page
  153.  * @access public
  154.  * @return TRUE on success, FALSE on failure - ['errors'] will contain reason for failure
  155.  */
  156. function mime_audio_load&$pFileHash&$pPrefs$pParams NULL {
  157.     global $gLibertySystem$gBitThemes;
  158.  
  159.     // don't load a mime image if we don't have an image for this file
  160.     if$ret mime_default_load$pFileHash$pPrefs$pParams )) {
  161.         // fetch meta data from the db
  162.         $ret['meta'LibertyMime::getMetaData$pFileHash['attachment_id']"ID3" );
  163.  
  164.         if!empty$ret['storage_path')) {
  165.             ifis_filedirnameSTORAGE_PKG_PATH.$ret['storage_path').'/bitverted.mp3' )) {
  166.                 $ret['media_url'storage_path_to_urldirname$ret['storage_path')).'/bitverted.mp3';
  167.                 // we need some javascript for the player:
  168.             elseifis_filedirnameSTORAGE_PKG_PATH.$ret['storage_path').'/bitverted.m4a' )) {
  169.                 $ret['media_url'storage_path_to_urldirname$ret['storage_path')).'/bitverted.m4a';
  170.             }
  171.         }
  172.     }
  173.     return $ret;
  174. }
  175.  
  176. /**
  177.  * mime_audio_converter
  178.  * 
  179.  * @param array $pParamHash 
  180.  * @access public
  181.  * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  182.  */
  183. function mime_audio_converter&$pParamHash {
  184.     global $gBitSystem;
  185.  
  186.     // audio conversion can take a while
  187.     ini_set"max_execution_time""1800" );
  188.  
  189.     $ret FALSE;
  190.     $log array();
  191.  
  192.     $source STORAGE_PKG_PATH.$pParamHash['upload']['dest_branch'].$pParamHash['upload']['name'];
  193.     $destPath dirname$source );
  194.  
  195.     if@BitBase::verifyId$pParamHash['attachment_id')) {
  196.         $pattern "#.*\.(mp3|m4a)$#i";
  197.         if!$gBitSystem->isFeatureActive'mime_audio_force_encode' && preg_match$pattern$pParamHash['upload']['name')) {
  198.             // make a copy of the original maintaining the original extension
  199.             $dest_file $destPath.'/bitverted.'.preg_replace$pattern"$1"strtolower$pParamHash['upload']['name'));
  200.             if!is_file$dest_file && !link$source$dest_file )) {
  201.                 copy$source$dest_file );
  202.             }
  203.             $ret TRUE;
  204.         else {
  205.             // TODO: have a better mechanism of converting audio to mp3. ffmpeg works well as long as the source is 'perfect'
  206.             //       there are many audiofiles that can't be read by ffmpeg but by other tools like flac, faac, oggenc
  207.             //       mplayer is very good, but has a lot of dependencies and not many servers have it installed
  208.             //       also, using mplayer is a 2 step process: decoding and encoding
  209.  
  210.             // if we convert audio, we always make an mp3
  211.             $dest_file $destPath.'/bitverted.mp3';
  212.             if!$ret mime_audio_converter_ffmpeg$pParamHash$source$dest_file ))) {
  213.                 // fall back to using slower mplayer / lame combo
  214.                 $ret mime_audio_converter_mplayer_lame$pParamHash$source$dest_file );
  215.             }
  216.         }
  217.  
  218.         // if the conversion was successful, we'll copy the tags to the new mp3 file and import data to meta tables
  219.         if$ret == TRUE {
  220.             $log['success''Successfully converted to mp3 audio';
  221.  
  222.             // now that we have a new mp3 file, we might as well copy the tags accross in case someone downloads it
  223.             require_onceUTIL_PKG_PATH.'getid3/getid3/getid3.php' );
  224.             $getID3 new getID3;
  225.             // we silence this since this will spew lots of ugly errors when using UTF-8 and some odd character in the file ID
  226.             $meta @$getID3->analyze$source );
  227.             getid3_lib::CopyTagsToComments$meta );
  228.  
  229.             // write tags to new mp3 file
  230.             if$errors mime_audio_update_tags$dest_file$meta['comments')) {
  231.                 $log['tagging'$errors;
  232.             }
  233.  
  234.             // getID3 returns everything in subarrays - we want to store everything in [0]
  235.             foreach$meta['comments'as $key => $comment {
  236.                 $store[$key$comment[0];
  237.             }
  238.             $store['playtimeseconds'$meta['playtime_seconds'];
  239.             $store['playtimestring']  $meta['playtime_string'];
  240.  
  241.             // make sure we remove previous entries first
  242.             LibertyMime::expungeMetaData$pParamHash['attachment_id');
  243.             if!LibertyMime::storeMetaData$pParamHash['attachment_id']'ID3'$store )) {
  244.                 $log['store_meta'"There was a problem storing the meta data in the database";
  245.             }
  246.  
  247.             // if we have an image in the id3v2 tag, we might as well do something with it
  248.             // we'll simply use the first image we can find in the file
  249.             if!empty$meta['id3v2']['APIC'][0]['data')) {
  250.                 $image $meta['id3v2']['APIC'][0];
  251.             elseif!empty$meta['id3v2']['PIC'][0]['data')) {
  252.                 $image $meta['id3v2']['PIC'][0];
  253.             }
  254.  
  255.             if !empty$image )) {
  256.                 // write the image to temp file for us to process
  257.                 $tmpfile str_replace"//""/"tempnamTEMP_PKG_PATHLIBERTY_PKG_NAME ));
  258.  
  259.                 if$fp fopen$tmpfile'w' )) {
  260.                     fwrite$fp$image['data');
  261.                     fclose$fp );
  262.  
  263.                     $fileHash['type']            $image['mime'];
  264.                     $fileHash['source_file']     $tmpfile;
  265.                     $fileHash['dest_branch']     $pParamHash['upload']['dest_branch'];
  266.                     liberty_generate_thumbnails$fileHash );
  267.  
  268.                     // remove temp file
  269.                     if!empty$tmpfile && is_file$tmpfile )) {
  270.                         unlink$tmpfile );
  271.                     }
  272.                 }
  273.             }
  274.  
  275.             // TODO: when tags package is enabled add an option to add tags
  276.             //       recommended tags might be artist and album
  277.  
  278.             // TODO: fetch album cover from amazon.com or musicbrainz.org
  279.             //       fetch lyrics from lyricwiki.org
  280.  
  281.             //$item->mLogs['audio_converter'] = "Audio file was successfully converted to MP3.";
  282.         }
  283.     }
  284.  
  285.     // update log
  286.     $pParamHash['log'array_merge$pParamHash['log']$log );
  287.  
  288.     return $ret;
  289. }
  290.  
  291. /**
  292.  * mime_audio_converter_mplayer_lame will decode the audio to wav using mplayer and then encode to mp3 using lame
  293.  * 
  294.  * @param array $pParamHash file information
  295.  * @param array $pSource source file
  296.  * @param array $pDest destination file
  297.  * @access public
  298.  * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  299.  */
  300. function mime_audio_converter_mplayer_lame&$pParamHash$pSource$pDest {
  301.     global $gBitSystem;
  302.     $ret FALSE;
  303.     $log array();
  304.  
  305.     if!empty$pParamHash && !empty$pSource && is_file$pSource && !empty$pDest )) {
  306.         $mplayer trim$gBitSystem->getConfig'mplayer_path'shell_exec'which mplayer' )));
  307.         $lame    trim$gBitSystem->getConfig'lame_path'shell_exec'which lame' )));
  308.  
  309.         // confirm that both applications are available
  310.         if$mm shell_exec"$mplayer 2>&1&& $ll shell_exec"$lame 2>&1)) {
  311.             // we will decode the audio file using mplayer and encode using lame
  312.             $mplayer_params " -quiet -vo null -vc dummy -af volume=0,resample=44100:0:1 -ao pcm:waveheader:file='$pSource.wav' '$pSource";
  313.             $lame_params    $gBitSystem->getConfig"mime_audio_lame_options"" -b ".$gBitSystem->getConfig'mime_audio_bitrate'64000 1000 ))." '$pSource.wav' '$pDest";
  314.             $command        "$mplayer $mplayer_params && $lame $lame_params";
  315.             $debug          shell_exec"$command 2>&1);
  316.  
  317.             // remove the temporary wav file again
  318.             @unlink"$pSource.wav);
  319.  
  320.             // make sure the conversion was successfull
  321.             ifis_file$pDest && filesize$pDest {
  322.                 $ret TRUE;
  323.             else {
  324.                 // remove unsuccessfully converted file
  325.                 @unlink$pDest );
  326.                 $log['message''ERROR: The audio you uploaded could not be converted by mplayer and lame. DEBUG OUTPUT: '.nl2br$debug );
  327.  
  328.                 // write error message to error file
  329.                 $h fopendirname$pDest )."/error"'w' );
  330.                 fwrite$h"$command\n\n$mm\n\n$ll\n\n$debug);
  331.                 fclose$h );
  332.             }
  333.         }
  334.     }
  335.  
  336.     // update log
  337.     $pParamHash['log'array_merge$pParamHash['log']$log );
  338.  
  339.     return $ret;
  340. }
  341.  
  342. /**
  343.  * mime_audio_converter_ffmpeg
  344.  * 
  345.  * @param array $pParamHash file information
  346.  * @param array $pSource source file
  347.  * @param array $pDest destination file
  348.  * @access public
  349.  * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  350.  */
  351. function mime_audio_converter_ffmpeg&$pParamHash$pSource$pDest {
  352.     global $gBitSystem;
  353.     $ret FALSE;
  354.     $log array();
  355.  
  356.     if!empty$pParamHash && !empty$pSource && is_file$pSource && !empty$pDest )) {
  357.         // these are set in the liberty plugin admin screen
  358.         $ffmpeg trim$gBitSystem->getConfig'ffmpeg_path'shell_exec'which ffmpeg' )));
  359.  
  360.         if$ff shell_exec"$ffmpeg 2>&1)) {
  361.             // set up parameters to convert audio
  362.             $params =
  363.                 " -i '$pSource'".
  364.                 " -acodec ".$gBitSystem->getConfig'ffmpeg_mp3_lib''libmp3lame' ).
  365.                 " -ab ".trim$gBitSystem->getConfig'mime_audio_bitrate'64000 ).'b' ).
  366.                 " -ar ".trim$gBitSystem->getConfig'mime_audio_samplerate'22050 )).
  367.                 " -y '$pDest'";
  368.             $debug shell_exec"$ffmpeg $params 2>&1);
  369.  
  370.             // make sure the conversion was successfull
  371.             ifis_file$pDest && filesize$pDest {
  372.                 $ret TRUE;
  373.             else {
  374.                 // remove unsuccessfully converted file
  375.                 @unlink$pDest );
  376.                 $log['message''ERROR: The audio you uploaded could not be converted by ffmpeg. DEBUG OUTPUT: '.nl2br$debug );
  377.  
  378.                 // write error message to error file
  379.                 $h fopendirname$pDest )."/error"'w' );
  380.                 fwrite$h"$ffmpeg $params\n\n$ff\n\n$debug);
  381.                 fclose$h );
  382.             }
  383.         }
  384.     }
  385.  
  386.     // update log
  387.     $pParamHash['log'array_merge$pParamHash['log']$log );
  388.  
  389.     return $ret;
  390. }
  391.  
  392. /**
  393.  * mime_audio_update_tags will update the tags of a given audio file
  394.  * 
  395.  * @param array $pFile absolute path to file
  396.  * @param array $pMetaData Hash of data that should be passed to the file.
  397.  * @access public
  398.  * @return NULL on success, String of errors on failure
  399.  */
  400. function mime_audio_update_tags$pFile$pMetaData {
  401.     $ret NULL;
  402.     if!empty$pFile && is_file$pFile && is_array$pMetaData )) {
  403.         // we need to initiate getID3 for the writer to work
  404.         require_onceUTIL_PKG_PATH.'getid3/getid3/getid3.php' );
  405.         $getID3 new getID3;
  406.  
  407.         require_onceUTIL_PKG_PATH.'getid3/getid3/write.php' );
  408.         // Initialize getID3 tag-writing module
  409.         $tagwriter new getid3_writetags();
  410.         $tagwriter->filename       $pFile;
  411.         $tagwriter->tagformats     array'id3v1''id3v2.3' );
  412.  
  413.         // set various options
  414.         $tagwriter->overwrite_tags TRUE;
  415.         $tagwriter->tag_encoding   "UTF-8";
  416.  
  417.         // prepare meta data for storing
  418.         foreach$pMetaData as $key => $data {
  419.             if!is_array$data )) {
  420.                 $data array$data );
  421.             }
  422.             $write[$key$data;
  423.         }
  424.  
  425.         // store the tags
  426.         if!empty$write )) {
  427.             $tagwriter->tag_data $write;
  428.             if!$tagwriter->WriteTags() ) {
  429.                 $ret 'Failed to write tags!<br />'.implode'<br /><br />'$tagwriter->errors );
  430.             }
  431.         }
  432.     }
  433.     return $ret;
  434. }
  435. ?>

Documentation generated on Wed, 29 Jul 2015 13:57:05 +0000 by phpDocumentor 1.5.0-lsces