Exemplo n.º 1
0
        $troptions['frame'] = floatval($_REQUEST['frame']);
        if (isset($_REQUEST['duration'])) {
            $troptions['duration'] = floatval($_REQUEST['duration']);
        }
    } else {
        if (isset($_REQUEST['segment'])) {
            // 10 seconds segment. Should it be an option?
            $ssize = 10;
            $send_all_in_once = true;
            // Should we use temporary folder instead?
            debug_event('play', 'Sending all data in once.', 5);
            $troptions['frame'] = intval($_REQUEST['segment']) * $ssize;
            $troptions['duration'] = $troptions['frame'] + $ssize <= $media->time ? $ssize : $media->time - $troptions['frame'];
        }
    }
    $transcoder = Stream::start_transcode($media, $transcode_to, $player, $troptions);
    $fp = $transcoder['handle'];
    $media_name = $media->f_artist_full . " - " . $media->title . "." . $transcoder['format'];
} else {
    if ($cpaction) {
        $transcoder = $media->run_custom_play_action($cpaction, $transcode_to);
        $fp = $transcoder['handle'];
        $transcode = true;
    } else {
        $fp = fopen(Core::conv_lc_file($media->file), 'rb');
    }
}
if ($transcode) {
    // Content-length guessing if required by the player.
    // Otherwise it shouldn't be used as we are not really sure about final length when transcoding
    if ($_REQUEST['content_length'] == 'required') {
Exemplo n.º 2
0
 public function get_chunk()
 {
     $chunk = null;
     if (!$this->is_init) {
         $this->init_channel_songs();
     }
     if ($this->is_init) {
         // Move to next song
         while ($this->media == null && ($this->random || $this->song_pos < count($this->songs))) {
             if ($this->random) {
                 $randsongs = $this->playlist->get_random_items(1);
                 $this->media = new Song($randsongs[0]['object_id']);
             } else {
                 $this->media = new Song($this->songs[$this->song_pos]);
             }
             $this->media->format();
             if ($this->media->catalog) {
                 $catalog = Catalog::create_from_id($this->media->catalog);
                 if (make_bool($this->media->enabled)) {
                     if (AmpConfig::get('lock_songs')) {
                         if (!Stream::check_lock_media($this->media->id, 'song')) {
                             debug_event('channel', 'Media ' . $this->media->id . ' locked, skipped.', '3');
                             $this->media = null;
                         }
                     }
                 }
                 if ($this->media != null) {
                     $this->media = $catalog->prepare_media($this->media);
                     if (!$this->media->file || !Core::is_readable(Core::conv_lc_file($this->media->file))) {
                         debug_event('channel', 'Cannot read media ' . $this->media->id . ' file, skipped.', '3');
                         $this->media = null;
                     } else {
                         $valid_types = $this->media->get_stream_types();
                         if (!in_array('transcode', $valid_types)) {
                             debug_event('channel', 'Missing settings to transcode ' . $this->media->file . ', skipped.', '3');
                             $this->media = null;
                         } else {
                             debug_event('channel', 'Now listening to ' . $this->media->file . '.', '5');
                         }
                     }
                 }
             } else {
                 debug_event('channel', 'Media ' . $this->media->id . ' doesn\'t have catalog, skipped.', '3');
                 $this->media = null;
             }
             $this->song_pos++;
             // Restart from beginning for next song if the channel is 'loop' enabled
             // and load fresh data from database
             if ($this->media != null && $this->song_pos == count($this->songs) && $this->loop) {
                 $this->init_channel_songs();
             }
         }
         if ($this->media != null) {
             // Stream not yet initialized for this media, start it
             if (!$this->transcoder) {
                 $options = array('bitrate' => $this->bitrate);
                 $this->transcoder = Stream::start_transcode($this->media, $this->stream_type, null, $options);
                 $this->media_bytes_streamed = 0;
             }
             if (is_resource($this->transcoder['handle'])) {
                 if (ftell($this->transcoder['handle']) == 0) {
                     $this->header_chunk = '';
                 }
                 $chunk = fread($this->transcoder['handle'], $this->chunk_size);
                 $this->media_bytes_streamed += strlen($chunk);
                 if (ftell($this->transcoder['handle']) < 10000 && strtolower($this->stream_type) == "ogg" || $this->header_chunk_remainder) {
                     //debug_event('channel', 'File handle pointer: ' . ftell($this->transcoder['handle']) ,'5');
                     $clchunk = $chunk;
                     if ($this->header_chunk_remainder) {
                         $this->header_chunk .= substr($clchunk, 0, $this->header_chunk_remainder);
                         if (strlen($clchunk) >= $this->header_chunk_remainder) {
                             $clchunk = substr($clchunk, $this->header_chunk_remainder);
                             $this->header_chunk_remainder = 0;
                         } else {
                             $this->header_chunk_remainder = $this->header_chunk_remainder - strlen($clchunk);
                             $clchunk = '';
                         }
                     }
                     // see bin/channel_run.inc for explanation what's happening here
                     while ($this->strtohex(substr($clchunk, 0, 4)) == "4F676753") {
                         $hex = $this->strtohex(substr($clchunk, 0, 27));
                         $ogg_nr_of_segments = hexdec(substr($hex, 26 * 2, 2));
                         if (substr($clchunk, 27 + $ogg_nr_of_segments + 1, 6) == "vorbis" || substr($clchunk, 27 + $ogg_nr_of_segments, 4) == "Opus") {
                             $hex .= $this->strtohex(substr($clchunk, 27, $ogg_nr_of_segments));
                             $ogg_sum_segm_laces = 0;
                             for ($segm = 0; $segm < $ogg_nr_of_segments; $segm++) {
                                 $ogg_sum_segm_laces += hexdec(substr($hex, 27 * 2 + $segm * 2, 2));
                             }
                             $this->header_chunk .= substr($clchunk, 0, 27 + $ogg_nr_of_segments + $ogg_sum_segm_laces);
                             if (strlen($clchunk) < 27 + $ogg_nr_of_segments + $ogg_sum_segm_laces) {
                                 $this->header_chunk_remainder = (int) (27 + $ogg_nr_of_segments + $ogg_sum_segm_laces - strlen($clchunk));
                             }
                             $clchunk = substr($clchunk, 27 + $ogg_nr_of_segments + $ogg_sum_segm_laces);
                         } else {
                             //no more interesting headers
                             $clchunk = '';
                         }
                     }
                 }
                 //debug_event('channel', 'File handle pointer: ' . ftell($this->transcoder['handle']) ,'5');
                 //debug_event('channel', 'CHUNK : ' . $chunk, '5');
                 //debug_event('channel', 'Chunk size: ' . strlen($chunk) ,'5');
                 // End of file, prepare to move on for next call
                 if (feof($this->transcoder['handle'])) {
                     $this->media->set_played(-1, 'Ampache', array());
                     if (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN') {
                         fread($this->transcoder['stderr'], 4096);
                         fclose($this->transcoder['stderr']);
                     }
                     fclose($this->transcoder['handle']);
                     Stream::kill_process($this->transcoder);
                     $this->media = null;
                     $this->transcoder = null;
                 }
             } else {
                 $this->media = null;
                 $this->transcoder = null;
             }
             if (!strlen($chunk)) {
                 $chunk = $this->get_chunk();
             }
         }
     }
     return $chunk;
 }
Exemplo n.º 3
0
 public function get_chunk()
 {
     $chunk = null;
     if (!$this->is_init) {
         $this->init_channel_songs();
     }
     if ($this->is_init) {
         // Move to next song
         while ($this->media == null && ($this->random || $this->song_pos < count($this->songs))) {
             if ($this->random) {
                 $randsongs = $this->playlist->get_random_items(1);
                 $this->media = new Song($randsongs[0]['object_id']);
             } else {
                 $this->media = new Song($this->songs[$this->song_pos]);
             }
             $this->media->format();
             if ($this->media->catalog) {
                 $catalog = Catalog::create_from_id($this->media->catalog);
                 if (make_bool($this->media->enabled)) {
                     if (AmpConfig::get('lock_songs')) {
                         if (!Stream::check_lock_media($this->media->id, 'song')) {
                             debug_event('channel', 'Media ' . $this->media->id . ' locked, skipped.', '3');
                             $this->media = null;
                         }
                     }
                 }
                 if ($this->media != null) {
                     $this->media = $catalog->prepare_media($this->media);
                     if (!$this->media->file || !Core::is_readable(Core::conv_lc_file($this->media->file))) {
                         debug_event('channel', 'Cannot read media ' . $this->media->id . ' file, skipped.', '3');
                         $this->media = null;
                     } else {
                         $valid_types = $this->media->get_stream_types();
                         if (!in_array('transcode', $valid_types)) {
                             debug_event('channel', 'Missing settings to transcode ' . $this->media->file . ', skipped.', '3');
                             $this->media = null;
                         } else {
                             debug_event('channel', 'Now listening to ' . $this->media->file . '.', '5');
                         }
                     }
                 }
             } else {
                 debug_event('channel', 'Media ' . $this->media->id . ' doesn\'t have catalog, skipped.', '3');
                 $this->media = null;
             }
             $this->song_pos++;
             // Restart from beginning for next song if the channel is 'loop' enabled
             // and load fresh data from database
             if ($this->media != null && $this->song_pos == count($this->songs) && $this->loop) {
                 $this->init_channel_songs();
             }
         }
         if ($this->media != null) {
             // Stream not yet initialized for this media, start it
             if (!$this->transcoder) {
                 $this->transcoder = Stream::start_transcode($this->media, $this->stream_type, $this->bitrate);
                 $this->media_bytes_streamed = 0;
             }
             if (is_resource($this->transcoder['handle'])) {
                 $chunk = fread($this->transcoder['handle'], 4096);
                 $this->media_bytes_streamed += strlen($chunk);
                 // End of file, prepare to move on for next call
                 if (feof($this->transcoder['handle'])) {
                     $this->media->set_played();
                     if (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN') {
                         fread($this->transcoder['stderr'], 4096);
                         fclose($this->transcoder['stderr']);
                     }
                     fclose($this->transcoder['handle']);
                     proc_close($this->transcoder['process']);
                     $this->media = null;
                     $this->transcoder = null;
                 }
             } else {
                 $this->media = null;
                 $this->transcoder = null;
             }
             if (!strlen($chunk)) {
                 $chunk = $this->get_chunk();
             }
         }
     }
     return $chunk;
 }
Exemplo n.º 4
0
 /**
  * Get a song waveform.
  * @param int $song_id
  * @return binary|string|null
  */
 public static function get($song_id)
 {
     $song = new Song($song_id);
     $waveform = null;
     if ($song->id) {
         $song->format();
         $waveform = $song->waveform;
         if (!$waveform) {
             $catalog = Catalog::create_from_id($song->catalog);
             if ($catalog->get_type() == 'local') {
                 $transcode_to = 'wav';
                 $transcode_cfg = AmpConfig::get('transcode');
                 $valid_types = $song->get_stream_types();
                 if ($song->type != $transcode_to) {
                     $basedir = AmpConfig::get('tmp_dir_path');
                     if ($basedir) {
                         if ($transcode_cfg != 'never' && in_array('transcode', $valid_types)) {
                             $tmpfile = tempnam($basedir, $transcode_to);
                             $tfp = fopen($tmpfile, 'wb');
                             if (!is_resource($tfp)) {
                                 debug_event('waveform', "Failed to open " . $tmpfile, 3);
                                 return null;
                             }
                             $transcoder = Stream::start_transcode($song, $transcode_to);
                             $fp = $transcoder['handle'];
                             if (!is_resource($fp)) {
                                 debug_event('waveform', "Failed to open " . $song->file . " for waveform.", 3);
                                 return null;
                             }
                             do {
                                 $buf = fread($fp, 2048);
                                 fwrite($tfp, $buf);
                             } while (!feof($fp));
                             fclose($fp);
                             fclose($tfp);
                             Stream::kill_process($transcoder);
                             $waveform = self::create_waveform($tmpfile);
                             //$waveform = self::create_waveform("C:\\tmp\\test.wav");
                             @unlink($tmpfile);
                         } else {
                             debug_event('waveform', 'transcode setting to wav required for waveform.', '3');
                         }
                     } else {
                         debug_event('waveform', 'tmp_dir_path setting required for waveform.', '3');
                     }
                 } else {
                     $waveform = self::create_waveform($song->file);
                 }
             }
             if ($waveform) {
                 self::save_to_db($song_id, $waveform);
             }
         }
     }
     return $waveform;
 }
Exemplo n.º 5
0
                    } else {
                        debug_event('play', 'Decided not to transcode', 5);
                    }
                }
            }
        }
    } else {
        if ($transcode_cfg != 'never') {
            debug_event('play', 'Transcoding is not enabled for this media type. Valid types: {' . json_encode($valid_types) . '}', 5);
        } else {
            debug_event('play', 'Transcode disabled in user settings.', 5);
        }
    }
}
if ($transcode) {
    $transcoder = Stream::start_transcode($media, $transcode_to, $bitrate);
    $fp = $transcoder['handle'];
    $media_name = $media->f_artist_full . " - " . $media->title . "." . $transcoder['format'];
} else {
    if ($cpaction) {
        $transcoder = $media->run_custom_play_action($cpaction, $transcode_to);
        $fp = $transcoder['handle'];
        $transcode = true;
    } else {
        $fp = fopen(Core::conv_lc_file($media->file), 'rb');
    }
}
if ($transcode) {
    // Content-length guessing if required by the player.
    // Otherwise it shouldn't be used as we are not really sure about final length when transcoding
    // Should also support video, but video implementation as to be reviewed first!