summaryrefslogtreecommitdiff
path: root/muggle-plugin/vdr_stream.c
diff options
context:
space:
mode:
authorLarsAC <LarsAC@e10066b5-e1e2-0310-b819-94efdf66514b>2005-03-22 06:47:53 +0000
committerLarsAC <LarsAC@e10066b5-e1e2-0310-b819-94efdf66514b>2005-03-22 06:47:53 +0000
commite2de0c5ed7bbbe4b236246e8bfd71cc87c8d974f (patch)
tree616f2f0a482597e3968e281ccf8adcfd04f45bbc /muggle-plugin/vdr_stream.c
parent101360901576c7e91196de60e2e6ebd6a4b145dd (diff)
downloadvdr-plugin-muggle-0.1.6-BETA.tar.gz
vdr-plugin-muggle-0.1.6-BETA.tar.bz2
Added 0.1.6 beta tag0.1.6-BETA
git-svn-id: https://vdr-muggle.svn.sourceforge.net/svnroot/vdr-muggle/tags/0.1.6-BETA@586 e10066b5-e1e2-0310-b819-94efdf66514b
Diffstat (limited to 'muggle-plugin/vdr_stream.c')
-rw-r--r--muggle-plugin/vdr_stream.c351
1 files changed, 351 insertions, 0 deletions
diff --git a/muggle-plugin/vdr_stream.c b/muggle-plugin/vdr_stream.c
new file mode 100644
index 0000000..872ac4b
--- /dev/null
+++ b/muggle-plugin/vdr_stream.c
@@ -0,0 +1,351 @@
+/*!
+ * \file vdr_stream.c
+ * \brief Implementation of media stream classes
+ *
+ * \version $Revision: 1.2 $
+ * \date $Date$
+ * \author Ralf Klueber, Lars von Wedel, Andreas Kellner
+ * \author Responsible author: $Author$
+ *
+ * $Id$
+ *
+ * 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)
+
+// --- mgStream -----------------------------------------------------------------
+
+mgStream::mgStream (std::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;
+}