예제 #1
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;
 }
예제 #2
0
파일: index.php 프로젝트: ivan801/ampache
                    print $buf;
                    if (ob_get_length()) {
                        ob_flush();
                        flush();
                        ob_end_flush();
                    }
                    ob_start();
                }
            }
            $bytes_streamed += strlen($buf);
        }
    } while (!feof($fp) && connection_status() == 0 && ($transcode || $bytes_streamed < $stream_size));
}
if ($send_all_in_once && connection_status() == 0) {
    header("Content-Length: " . strlen($buf_all));
    print $buf_all;
    ob_flush();
}
$real_bytes_streamed = $bytes_streamed;
// Need to make sure enough bytes were sent.
if ($bytes_streamed < $stream_size && connection_status() == 0) {
    print str_repeat(' ', $stream_size - $bytes_streamed);
    $bytes_streamed = $stream_size;
}
if ($transcode && isset($transcoder)) {
    fclose($fp);
    Stream::kill_process($transcoder);
} else {
    fclose($fp);
}
debug_event('play', 'Stream ended at ' . $bytes_streamed . ' (' . $real_bytes_streamed . ') bytes out of ' . $stream_size, 5);
예제 #3
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;
 }