/** * Actually sends the data in the specified file. * * * @author Ben Dodson, PHP.net * @version 11/11/04 * @since 11/11/04 */ function streamFile($path, $name, $limit = false, $resample = "", $download = false, $contentTypeFor = false) { global $always_resample, $allow_resample, $always_resample_rate, $jzUSER; // Let's ignore if they abort, that way we'll know when the track stops... ignore_user_abort(TRUE); $jzSERVICES = new jzServices(); $jzSERVICES->loadStandardServices(); $status = false; if ($limit === false) { $speed_limit = 1 * 1024; } else { $speed_limit = $limit; } // limit is passed as a param because we may want to limit it for downloads // but not for streaming / image viewing. // Also, we may want to write a different function for resampling, // but I don't know yet. // IF NO SPEED LIMIT: // the 'speed_limit' from above is the amount // of buffer used while sending the file. // but with no speed limit, there is no 'sleep' issued. // this makes seeking in a file much faster. // Let's get the extension of the real file $extArr = explode(".", $path); $ext = $extArr[count($extArr) - 1]; if (!is_file($path) || connection_status() != 0) { return false; } $meta = $jzSERVICES->getTagData($path); $do_resample = false; if (!isNothing($resample)) { $do_resample = true; } if ($allow_resample == "true" && stristr($always_resample, $ext)) { $do_resample = true; } if ($meta['type'] == "mp3") { if (!isNothing($resample) && $resample >= $meta['bitrate']) { $do_resample = false; } } if ($download) { $do_resample = false; } // Are they resampling or transcoding? if ($do_resample) { // Ok, if resampling isn't set let's go with the default if ($resample == "") { $resample = $always_resample_rate; } // Now let's load up the resampling service $jzSERVICES = new jzServices(); $jzSERVICES->loadService("resample", "resample"); $jzSERVICES->resampleFile($path, $name, $resample); // Now let's unset what they are playing $be = new jzBackend(); $be->unsetPlaying($_GET['jz_user'], $_GET['sid']); return; } // Now we need to know if this is an ID3 image or not // First let's get their limit $limit = "7"; $size = filesize($path); $range = getContentRange($size); if ($range !== false) { $range_from = $range[0]; $range_to = $range[1]; } else { $range_from = 0; $range_to = $size - 1; } $ps3 = false; $allheaders = getallheaders(); if (isset($allheaders['User-Agent']) && $allheaders['User-Agent'] == "PLAYSTATION 3") { $ps3 = true; } if ($ps3) { // ps3 is picky and bizarre. if ($range_from > $size) { // This happens if the ps3 thinks the file // is larger than it is, and sending a // This is supposed to be a read of the id3v1 tag at // the end of a file (128 bytes), or the lyrics tag // (138 bytes) $requested = $range_to - $range_from + 1; $range_from = $size - $requested; $range_to = $size - 1; header("HTTP/1.1 206 Partial content"); } else { if ($range_from == 0 && $size == $range_to + 1) { header("HTTP/1.1 200 OK"); } else { header("HTTP/1.1 206 Partial content"); header("CONTENT-RANGE: bytes {$range_from}-{$range_to}/{$size}"); } } header("transferMode.dlna.org: Streaming"); header("contentFeatures.dlna.org: DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=017000 00000000000000000000000000"); header("Accept-Ranges: bytes"); header("Connection: keep-alive"); header("Content-Length: " . ($size - $range_from)); } else { if ($range === false) { // Content length has already been sent header("Content-Length: " . (string) $size); } else { header("HTTP/1.1 206 Partial Content"); header("Accept-Range: bytes"); header("Content-Length: " . ($size - $range_from)); header("Content-Range: bytes {$range_from}" . "-" . $range_to . "/{$size}"); } } if ($contentTypeFor !== false) { sendContentType($contentTypeFor); } if (!$ps3) { header("Content-Disposition: inline; filename=\"" . $name . "\""); header("Expires: " . gmdate("D, d M Y H:i:s", mktime(date("H") + 2, date("i"), date("s"), date("m"), date("d"), date("Y"))) . " GMT"); header("Last-Modified: " . gmdate("D, d M Y H:i:s", filemtime($path)) . " GMT"); header("Cache-Control: no-cache, must-revalidate"); header("Pragma: no-cache"); } if ($file = fopen($path, 'rb')) { @set_time_limit(0); fseek($file, $range_from); while (!feof($file) and connection_status() == 0 and ($cur_pos = ftell($file)) < $range_to + 1) { print fread($file, min(1024 * $speed_limit, $range_to + 1 - $cur_pos)); flush(); if ($limit !== false) { sleep(1); } } $status = connection_status() == 0; fclose($file); @set_time_limit(30); } // Now let's unset what they are playing $be = new jzBackend(); $be->unsetPlaying($_GET['jz_user'], $_GET['sid']); return $status; }