bool Caching_Stream::open(const Input_Stream_Position& position) { bool status; if (CFURLResourceIsReachable(m_metaDataUrl, NULL) && CFURLResourceIsReachable(m_fileUrl, NULL)) { m_cacheable = false; m_writable = false; m_useCache = true; m_cacheMetaDataWritten = false; readMetaData(); CS_TRACE("Playing file from cache\n"); CS_TRACE_CFURL(m_fileUrl); status = m_fileStream->open(position); } else { m_cacheable = false; m_writable = false; m_useCache = false; m_cacheMetaDataWritten = false; CS_TRACE("File not cached\n"); status = m_target->open(position); } return status; }
void Caching_Stream::streamEndEncountered() { if (m_fileOutput) { delete m_fileOutput, m_fileOutput = 0; } if (m_cacheable) { if (m_writable) { CS_TRACE("Successfully cached the stream\n"); CS_TRACE_CFURL(m_fileUrl); // We only write the meta data if the stream was successfully streamed. // In that way we can use the meta data as an indicator that there is a file to stream. if (!m_cacheMetaDataWritten) { CFWriteStreamRef writeStream = CFWriteStreamCreateWithFile(kCFAllocatorDefault, m_metaDataUrl); if (writeStream) { if (CFWriteStreamOpen(writeStream)) { CFStringRef contentType = m_target->contentType(); UInt8 buf[1024]; CFIndex usedBytes = 0; if (contentType) { // It is possible that some streams don't provide a content type CFStringGetBytes(contentType, CFRangeMake(0, CFStringGetLength(contentType)), kCFStringEncodingUTF8, '?', false, buf, 1024, &usedBytes); } if (usedBytes > 0) { CS_TRACE("Writing the meta data\n"); CS_TRACE_CFSTRING(contentType); CFWriteStreamWrite(writeStream, buf, usedBytes); } CFWriteStreamClose(writeStream); } CFRelease(writeStream); } m_cacheable = false; m_writable = false; m_useCache = true; m_cacheMetaDataWritten = true; } } } if (m_delegate) { m_delegate->streamEndEncountered(); } }
void Caching_Stream::streamIsReadyRead() { if (m_cacheable) { // If the stream is cacheable (not seeked from some position) // Check if the stream has a length. If there is no length, // it is a continuous stream and thus cannot be cached. m_cacheable = (m_target->contentLength() > 0); } #if CS_DEBUG if (m_cacheable) CS_TRACE("Stream can be cached!\n"); else CS_TRACE("Stream cannot be cached\n"); #endif if (m_delegate) { m_delegate->streamIsReadyRead(); } }
void Caching_Stream::streamHasBytesAvailable(UInt8 *data, UInt32 numBytes) { if (m_cacheable) { if (numBytes > 0) { if (!m_fileOutput) { if (m_fileUrl) { CS_TRACE("Caching started for stream\n"); m_fileOutput = new File_Output(m_fileUrl); m_writable = true; } } if (m_writable && m_fileOutput) { m_writable &= (m_fileOutput->write(data, numBytes) > 0); } } } if (m_delegate) { m_delegate->streamHasBytesAvailable(data, numBytes); } }
void Caching_Stream::readMetaData() { if (!m_metaDataUrl) { return; } CFReadStreamRef readStream = CFReadStreamCreateWithFile(kCFAllocatorDefault, m_metaDataUrl); if (readStream) { if (CFReadStreamOpen(readStream)) { UInt8 buf[1024]; CFIndex bytesRead = CFReadStreamRead(readStream, buf, 1024); if (bytesRead > 0) { CFStringRef contentType = CFStringCreateWithBytes(kCFAllocatorDefault, buf, bytesRead, kCFStringEncodingUTF8, false); if (contentType) { if (m_fileStream) { CS_TRACE("Setting the content type of the file stream based on the meta data\n"); CS_TRACE_CFSTRING(contentType); m_fileStream->setContentType(contentType); } CFRelease(contentType); } } CFReadStreamClose(readStream); } CFRelease(readStream); } }