summaryrefslogtreecommitdiff
path: root/vdr_stream.c
diff options
context:
space:
mode:
Diffstat (limited to 'vdr_stream.c')
-rw-r--r--vdr_stream.c332
1 files changed, 332 insertions, 0 deletions
diff --git a/vdr_stream.c b/vdr_stream.c
new file mode 100644
index 0000000..d82877e
--- /dev/null
+++ b/vdr_stream.c
@@ -0,0 +1,332 @@
+/*!
+ * \file vdr_stream.c
+ * \brief Implementation of media stream classes
+ *
+ * \version $Revision: 1.2 $
+ * \date $Date: 2004/05/28 15:29:19 $
+ * \author Ralf Klueber, Lars von Wedel, Andreas Kellner
+ * \author Responsible author: $Author: lvw $
+ *
+ * $Id: vdr_stream.c,v 1.2 2004/05/28 15:29:19 lvw Exp $
+ *
+ * Adapted from
+ * MP3/MPlayer plugin to VDR (C++)
+ * (C) 2001-2003 Stefan Huelswitt <huels@iname.com>
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/statfs.h>
+#include <iostream>
+
+#include <interface.h>
+
+#include "mg_tools.h"
+
+// #include "setup-mp3.h"
+#include "vdr_stream.h"
+#include "vdr_network.h"
+#include "vdr_config.h"
+// #include "i18n.h"
+// #include "version.h"
+
+#define tr(x) x
+
+#ifdef USE_MMAP
+#include <sys/mman.h>
+#endif
+
+#define DEFAULT_PORT 80 // default port for streaming (HTTP)
+
+using namespace std;
+
+// --- mgStream -----------------------------------------------------------------
+
+mgStream::mgStream( string filename )
+ : m_filename( filename )
+{
+ m_fd = -1;
+ m_ismmap = false;
+ m_buffer = 0;
+}
+
+mgStream::~mgStream()
+{
+ close();
+}
+
+bool mgStream::open(bool log)
+{
+ if( m_fd >= 0 )
+ {
+ return seek();
+ }
+
+ // just check, whether file exists?
+ if( fileinfo( log ) )
+ {
+ printf( "mgStream::open: fileinfo == true\n");
+
+ if( ( m_fd = ::open( m_filename.c_str(), O_RDONLY ) ) >=0 )
+ {
+ printf( "mgStream::open: file opened\n" );
+
+ m_buffpos = m_readpos = 0;
+ m_fill = 0;
+
+ printf( "mgStream::open: buffpos, readpos, fill set\n" );
+
+ /*
+#ifdef USE_MMAP
+ if( m_filesize <= MAX_MMAP_SIZE )
+ {
+ m_buffer = (unsigned char*)mmap( 0, m_filesize, PROT_READ,
+ MAP_SHARED, m_fd, 0 );
+ if( m_buffer != MAP_FAILED )
+ {
+ m_ismmap = true;
+ return true;
+ }
+ else
+ {
+ dsyslog("mmap() failed for %s: %s", m_filename.c_str(), strerror(errno) );
+ }
+ }
+#endif
+ */
+ printf( "mgStream::open: allocating buffer: %d\n", MP3FILE_BUFSIZE );
+ m_buffer = new unsigned char[MP3FILE_BUFSIZE];
+ printf( "mgStream::open: buffer allocated\n" );
+
+ if( m_buffer )
+ {
+ printf( "mgStream::open: buffer allocated, returning true\n" );
+
+ return true;
+ }
+ else
+ {
+ esyslog("ERROR: not enough memory for buffer: %s", m_filename.c_str() );
+ }
+ }
+ else
+ {
+ if( log )
+ {
+ esyslog("ERROR: failed to open file %s: %s", m_filename.c_str(), strerror(errno) );
+ }
+ }
+ }
+
+ close();
+ printf( "mgStream::open: returning false\n" );
+ return false;
+}
+
+void mgStream::close(void)
+{
+#ifdef USE_MMAP
+ if( m_ismmap )
+ {
+ munmap( m_buffer, m_filesize );
+ m_buffer = 0;
+ m_ismmap = false;
+ }
+ else
+ {
+#endif
+ delete m_buffer;
+ m_buffer = 0;
+#ifdef USE_MMAP
+ }
+#endif
+ if( m_fd >= 0 )
+ {
+ ::close( m_fd );
+ m_fd = -1;
+ }
+}
+
+bool mgStream::seek(unsigned long long pos)
+{
+ printf( "mgStream::seek\n" );
+ if( m_fd >= 0 && pos >= 0 && pos <= m_filesize )
+ {
+ printf( "mgStream::seek valid file and position detected\n" );
+
+ m_buffpos = 0;
+ m_fill = 0;
+
+ if( m_ismmap )
+ {
+ m_readpos = pos;
+
+ printf( "mgStream::seek: returning true\n" );
+ return true;
+ }
+ else
+ {
+ if( ( m_readpos = lseek64( m_fd, pos, SEEK_SET ) ) >=0 )
+ {
+ if( m_readpos != pos )
+ {
+ dsyslog( "seek mismatch in %s, wanted %lld, got %lld", m_filename.c_str(), pos, m_readpos );
+ }
+ printf( "mgStream::seek: returning true\n" );
+ return true;
+ }
+ else
+ {
+ esyslog( "ERROR: seeking failed in %s: %d,%s", m_filename.c_str(), errno, strerror(errno) );
+ }
+ }
+ }
+ else
+ {
+ printf( "mp3: bad seek call fd=%d pos=%lld name=%s\n", m_fd, pos, m_filename.c_str() );
+ }
+
+ printf( "mgStream::seek: returning false\n" );
+ return false;
+}
+
+bool mgStream::stream(unsigned char * &data,
+ unsigned long &len,
+ const unsigned char *rest)
+{
+ if( m_fd >= 0 )
+ {
+ if( m_readpos < m_filesize )
+ {
+ if( m_ismmap )
+ {
+ if( rest && m_fill )
+ {
+ m_readpos = (rest - m_buffer); // take care of remaining data
+ }
+ m_fill = m_filesize - m_readpos;
+ data = m_buffer + m_readpos;
+ len = m_fill;
+ m_buffpos = m_readpos;
+ m_readpos += m_fill;
+
+ return true;
+ }
+ else
+ {
+ if( rest && m_fill )
+ { // copy remaining data to start of buffer
+ m_fill -= ( rest - m_buffer); // remaing bytes
+ memmove( m_buffer, rest, m_fill );
+ }
+ else
+ {
+ m_fill = 0;
+ }
+
+ int r;
+ do
+ {
+ r = read( m_fd, m_buffer + m_fill,
+ MP3FILE_BUFSIZE - m_fill );
+ } while( r == -1 && errno == EINTR );
+
+ if( r >= 0 )
+ {
+ m_buffpos = m_readpos - m_fill;
+ m_readpos += r;
+ m_fill += r;
+ data = m_buffer;
+ len = m_fill;
+
+ return true;
+ }
+ else
+ {
+ esyslog("ERROR: read failed in %s: %d,%s", m_filename.c_str(), errno, strerror(errno) );
+ }
+ }
+ }
+ else
+ {
+ len = 0;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool mgStream::removable()
+{
+ // we do not handle removable media at this time
+ return false;
+}
+
+bool mgStream::fileinfo( bool log )
+{
+ struct stat64 ds;
+
+ if( !stat64( m_filename.c_str(), &ds ) )
+ {
+ printf( "mgStream::fileinfo: stat64 == 0\n" );
+
+ if( S_ISREG( ds.st_mode ) )
+ {
+ m_fsID = "";
+ m_fsType = 0;
+
+ struct statfs64 sfs;
+
+ if( !statfs64( m_filename.c_str(), &sfs) )
+ {
+ if( removable() )
+ {
+ char *tmpbuf;
+ asprintf( &tmpbuf, "%llx:%llx", sfs.f_blocks, sfs.f_files );
+ m_fsID = tmpbuf;
+ free( tmpbuf );
+ }
+ m_fsType = sfs.f_type;
+ }
+ else
+ {
+ if( errno != ENOSYS && log )
+ {
+ esyslog("ERROR: can't statfs %s: %s", m_filename.c_str(), strerror(errno) );
+ }
+ }
+
+ m_filesize = ds.st_size;
+ m_ctime = ds.st_ctime;
+
+#ifdef CDFS_MAGIC
+ if( m_fsType == CDFS_MAGIC )
+ {
+ m_ctime=0; // CDFS returns mount time as ctime
+ }
+#endif
+ // infodone tells that info has been read, like a cache flag
+ // InfoDone();
+ return true;
+ }
+ else
+ {
+ if(log)
+ {
+ esyslog("ERROR: %s is not a regular file", m_filename.c_str() );
+ }
+ }
+ }
+ else
+ {
+ if(log)
+ {
+ esyslog("ERROR: can't stat %s: %s", m_filename.c_str(), strerror(errno) );
+ }
+
+ printf( "mgStream::fileinfo: stat64 != 0 for %s\n", m_filename.c_str() );
+ }
+
+ return false;
+}