<?php
// $Id$

/**
 *  Implementation of hook_mapi_programs()
 */
function mapi_ffmpeg_mapi_programs($op, $program, $edit) {
  switch ($op) {
    case 'list':
      if (!$program) {
        return array('ffmpeg');
      }
      if ($program == 'ffmpeg') {
        // could use the list extensions section of ffmpeg for this.
        return array('flv', 'wmv', 'mov');
      }
      break;
    case 'path':
      if ($program) {
        return array(
          '/usr/local/bin/ffmpeg',
          'C:\\Program Files\\ffmpeg\\bin\\ffmpeg.exe',
        );
      }
      break;
  }
}

/**
 *  Implementation of hook_mapi_transforms()
 */
function mapi_ffmpeg_mapi_transforms($op, $transform, $data, $file) {
  switch ($op) {
    case 'list':
      switch ($transform) {
        case 'transcode':
        case 'snapshot':
          return media_program_extensions('ffmpeg');
        default:
            if (mapi_program_installed('ffmpeg')) {
              return array('transcode', 'snapshot');
            }
          break;
      }
      break;
    case 'info':
      $list = array(
        'transcode' => array(
          'description' => t('Converts video into video of another type, or audio.')
        ),
        'snapshot' => array(
          'description' => t('Allows a snapshot to be taken of the video at a predefined time period.')
        ),
      );
      if (array_key_exists($transform, $list)) {
        return $list[$transform];
      }
      return $list;
      break;

    // test for extension change
    case 'test':
      return _mapi_ffmpeg_filename($file, $data['output']);

    // what are the defaults for the various transforms
    case 'defaults':
      if ($transform == 'transcode') {
        $items = array(
          'output' => array_shift(mapi_program_extensions('ffmpeg')),
          'audio' => array(
            'frequency' => 0,
            'bitrate' => 0,
            'channels' => 0,
          ),
          'video' => array(
            'bitrate' => 0,
            'channels' => 0,
          )
        );
      }
      elseif ($transform == 'snapshot') {
        $items = array(
          'output' => 'jpg',
          'timing' => 3
        );
      }
      return $items;

    // the form
    case 'form':
      $exts = mapi_program_extensions('ffmpeg');
      $extensions = array();
      foreach ($exts as $ext) {
        $extensions[$ext] = $ext;
      }

      if ($transform == 'transcode') {
        $form['output'] = array(
          '#type' => 'select',
          '#title' => t('Output extension'),
          '#description' => t('Select the output extension for transcoding'),
          '#options' => $extensions,
          '#default_value' => !empty($data['output']) ? $data['output'] : $data[0],
        );

        $form['audio'] = array(
          '#type' => 'fieldset',
          '#tree' => true,
          '#title' => t('Audio'),
          '#description' => t('Audio settings'),
        );

        $form['audio']['frequency'] = array(
          '#type' => 'select',
          '#title' => t('Frequency'),
          '#description' => t('Selects the frequency for the audio output'),
          '#options' => array(t('No Change'), '11025' => '11.025 kHz', '22050' => '22.050 kHz', '44100' => '44.100 kHz'),
          '#default_value' => !empty($data['audio']['frequency']) ? $data['audio']['frequency'] : 0
        );

        $form['audio']['bitrate'] = array(
          '#type' => 'select',
          '#title' => t('Bit Rate'),
          '#description' => t('Selects the bit rate for the audio output'),
          '#options' => array(t('No Change'), '11k' => '11khz (FBR)', '22k' => '22khz (FBR)', '44k' => '44khz (FBR)'),
          '#default_value' => !empty($data['audio']['bitrate']) ? $data['audio']['bitrate'] : 0
        );

        $form['audio']['channels'] = array(
          '#type' => 'select',
          '#title' => t('Channels'),
          '#description' => t('Select the output channels for the audio.'),
          '#options' => array(t('No Change'), t('stereo'), t('mono')),
          '#default_value' => !empty($data['audio']['channels']) ? $data['audio']['channels'] : 0
        );

        $form['video'] = array(
          '#type' => 'fieldset',
          '#tree' => true,
          '#title' => t('Video'),
          '#description' => t('Video settings'),
        );

        $form['video']['bitrate'] = array(
          '#type' => 'select',
          '#title' => t('Audio Bit Rate'),
          '#description' => t('Selects the bit rate for the audio output'),
          '#options' => array(t('No Change'), '11k' => '11khz (FBR)', '22k' => '22khz (FBR)', '44k' => '44khz (FBR)'),
          '#default_value' => !empty($data['video']['bitrate']) ? $data['video']['bitrate'] : 0
        );

        $form['video']['channels'] = array(
          '#type' => 'select',
          '#title' => t('Channels'),
          '#description' => t('Select the output channels for the audio.'),
          '#options' => array(t('No Change'), t('stereo'), t('mono')),
          '#default_value' => !empty($data['video']['channels']) ? $data['video']['channels'] : 0
        );
      }
      elseif ($transform == 'snapshot') {
        $form['output'] = array(
          '#type' => 'select',
          '#title' => t('Output image extension'),
          '#description' => t('Select the output extension for transcoding'),
          '#options' => array('jpg' => 'jpg', 'png' => 'png', 'gif' => 'gif'),
          '#default_value' => !empty($data['output']) ? $data['output'] : 'jpg',
        );

        $form['timing'] = array(
          '#type' => 'textfield',
          '#title' => t('Snapshot time'),
          '#description' => t('Determines in seconds when the snapshot is taken.'),
          '#default_value' => !empty($data['timing']) ? $data['timing'] : 3,
        );
      }
      break;
    case 'validate':
      if ($transform == 'snapshot' && (!is_numeric($data['timing']) || $data['timing'] < 0)) {
        form_set_error('timing', t('Timing must be in positive seconds.'));
      }
      break;
    case 'transform':
      if (!media_program_installed('ffmpeg') || is_null($data)) {
        return;
      }

      // get necessary information from the data
      $dest = (isset($data['dest']) ? $data['dest'] : $file);
      $data = (isset($data['settings']) ? $data['settings'] : array());

      if ($transform == 'transcode') {
        // find the output filename (with possible change in extension)
        $ofile = _mapi_ffmpeg_filename($dest, $data['output']);

        // make sure not to overwrite whatever it is we're dealing with
        if ($ofile == $file) {
          $ofile = mapi_file_freename($ofile);
        }

        // make sure the file exists, otherwise realpath doesn't function.
        touch($ofile);

        // initial commandline
        $cmdline = array('-y', '-i', realpath($file));

        if ($transform == 'transcode') {
          // additional conversion materials
          if ($data['audio']['frequency']) {
            $cmdline = array_merge($cmdline, array('-ar', $data['audio']['frequency']));
          }
        }
        elseif ($transform == 'snapshot') {
          // determine output format
          switch ($data['output']) {
            case 'jpg':
              $cmdline = array_merge($cmdline, array('-f', 'mjpeg'));
              break;
            case 'gif':
              $cmdline = array_merge($cmdline, array('-f', 'gif', '-pix_fmt', 'rgb24'));
              break;
            case 'png':
              $cmdline = array_merge($cmdline, array('-vcodec', 'png', '-f', 'rawvideo'));
              break;
          }

          // what location of time to take the video frame at?
          $cmdline = array_merge($cmdline, array('-ss', $data['timing']));

          // we only want one frame
          $cmdline = array_merge($cmdline, array('-vframes', 1));

          // disables video recording
          $cmdline[] = '-an';
        }

        // output file
        $cmdline[] = realpath($ofile);

        $result = media_program_execute('ffmpeg', $cmdline);

        // return the correct output name
        return $ofile;
      }
      break;
  }
}

function _mapi_ffmpeg_filename($filename, $ext) {
  return dirname($filename) .'/'. mapi_file_name($filename) .'.'. $ext;
}