[ANNOUNCE] vdr-xine-0.7.6-network plugin

Message ID 87hdcnwe6a.87fys7we6a@87ek7rwe6a.message.id
State New
Headers

Commit Message

syrius.ml@no-log.org Sept. 14, 2005, 9:30 p.m. UTC
  "Peter Weber" <peter_weber69@gmx.at> writes:

[...]
>> Would it be possible for you to post a patch for xine instead of the full
>> source?

> [...]
> there are hunks, but have a look at the xine-lib.h.rej file and
> make the changes in xine-lib.c with an editor
> [...]

humm do you really do that by hand every time ?

anyway, here are the 2 patches I use to add the network feature to
vdr-xine and to xine-lib.

Those are based on the *0.7.5-network.tar.gz, so the url to use with
xine is:
xine vdr-socket:/IP.OF.VDR.BOX#demux:mpeg_pes
(as explained on Peter's website)

vdr-xine+network.diff applies on top of vdr-xine
(vdr-xine-0.7.6.tar.gz for ex)

xine-lib+network.diff applies on top of a vdr-xine patched xine-lib.
(in other words, you have to patch xine-lib with the patch provided in
vdr-xine-0.7.6 then this one)

diff -Nru xine-lib/src/vdr/input_vdr.c xine-lib+net/src/vdr/input_vdr.c
--- xine-lib/src/vdr/input_vdr.c	2005-09-14 23:04:14.000000000 +0200
+++ xine-lib+net/src/vdr/input_vdr.c	2005-08-16 12:03:03.000000000 +0200
@@ -34,6 +34,10 @@
 #include <errno.h>
 #include <pthread.h>
 
+#include <sys/socket.h>
+#include <resolv.h>
+#include <netdb.h>
+
 #define LOG_MODULE "input_vdr"
 #define LOG_VERBOSE
 /*
@@ -51,8 +55,6 @@
 #define VDR_MAX_NUM_WINDOWS 16
 #define VDR_ABS_FIFO_DIR "/tmp/vdr-xine"
 
-
-
 #define BUF_SIZE 1024
 
 #define LOG_OSD(x)
@@ -1455,108 +1457,203 @@
   return INPUT_OPTIONAL_UNSUPPORTED;
 }
 
-static int vdr_plugin_open(input_plugin_t *this_gen)
+static int vdr_plugin_open_socket(vdr_input_plugin_t *this, struct hostent *host, unsigned short port)
+{
+	int fd;
+	struct sockaddr_in sain;
+	struct in_addr iaddr;
+
+	if ((fd = socket(PF_INET,SOCK_STREAM,0)) == -1) {
+		xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+				_("vdr: failed to create socket for port %d (%s)\n"),
+					port,strerror(errno));
+		return -1;
+	}
+
+	iaddr.s_addr = * ((unsigned int *) host->h_addr_list[0]);
+
+	sain.sin_port = htons(port);
+	sain.sin_family = AF_INET;
+	sain.sin_addr = iaddr;
+
+	if (connect(fd,(struct sockaddr*) &sain, sizeof(sain)) < 0) {
+		xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+				_("vdr: failed to connect to port %d (%s)\n"),port,
+				strerror(errno));
+		return -1;
+	}
+
+	xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+			"vdr: socket opening successful, fd = %d\n",fd);
+	return fd;
+}    
+
+static int vdr_plugin_open_sockets(vdr_input_plugin_t *this)
+{
+//  struct hostent *host = gethostbyname(VDR_SERVER_ADDRESS);
+  struct hostent *host = gethostbyname(&this->mrl[12]);
+ 
+  xprintf(this->stream->xine, XINE_VERBOSITY_LOG,"vdr: connecting to vdr.\n");
+  if (host == NULL) {
+    xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+            _("vdr: failed to resolve hostname '%s' (%s)\n"),
+			&this->mrl[12],
+			strerror(errno));
+	return 0;
+  }
+
+  if ((this->fh = vdr_plugin_open_socket(this,host,18701)) == -1)
+	  return 0;
+  
+  fcntl(this->fh, F_SETFL, ~O_NONBLOCK & fcntl(this->fh, F_GETFL, 0));
+  
+  if ((this->fh_control = vdr_plugin_open_socket(this,host,18702)) == -1)
+	  return 0;
+
+  if ((this->fh_result = vdr_plugin_open_socket(this,host,18703)) == -1)
+	  return 0;
+
+  if ((this->fh_event = vdr_plugin_open_socket(this,host,18704)) == -1)
+	  return 0;
+  xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+			"vdr: connecting to all sockets was successful.\n");
+  return 1;
+}
+
+static int vdr_plugin_open_vdr(input_plugin_t *this_gen)
 {
   vdr_input_plugin_t *this = (vdr_input_plugin_t *)this_gen;
 
-  lprintf("trying to open '%s'...\n", this->mrl);
+  char *filename;
 
-  if (this->fh == -1)
-  {
-    char *filename;
-    int err = 0;
+  filename = (char *)&this->mrl[ 4 ];
+  this->fh = open(filename, O_RDONLY | O_NONBLOCK);
 
-    filename = (char *)&this->mrl[ 4 ];
-    this->fh = open(filename, O_RDONLY | O_NONBLOCK);
+  lprintf("filename '%s'\n", filename);
 
-    lprintf("filename '%s'\n", filename);
+  if (this->fh == -1)
+  {
+    xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+            _(LOG_MODULE ": failed to open '%s' (%s)\n"),
+            filename,
+            strerror(errno));
+      
+    return 0;
+  }
 
-    if (this->fh == -1)
+  {
+    struct pollfd poll_fh = { this->fh, POLLIN, 0 };
+      
+    int r = poll(&poll_fh, 1, 300);      
+    if (1 != r)
     {
       xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
               _(LOG_MODULE ": failed to open '%s' (%s)\n"),
               filename,
-              strerror(errno));
-      
-      return 0;
-    }
-
-    {
-      struct pollfd poll_fh = { this->fh, POLLIN, 0 };
-      
-      int r = poll(&poll_fh, 1, 300);      
-      if (1 != r)
-      {
-        xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
-                _(LOG_MODULE ": failed to open '%s' (%s)\n"),
-                filename,
-                _("timeout expired during setup phase"));
+              _("timeout expired during setup phase"));
         
-        return 0;
-      }
+      return 0;
     }
+  }
     
-    fcntl(this->fh, F_SETFL, ~O_NONBLOCK & fcntl(this->fh, F_GETFL, 0));
+  fcntl(this->fh, F_SETFL, ~O_NONBLOCK & fcntl(this->fh, F_GETFL, 0));
     
-    {
-      char *filename_control = 0;
-      asprintf(&filename_control, "%s.control", filename);
-
-      this->fh_control = open(filename_control, O_RDONLY);
-
-      if (this->fh_control == -1) {
-        xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
-                _(LOG_MODULE ": failed to open '%s' (%s)\n"),
-                filename_control,
-                strerror(errno));
+  {
+    char *filename_control = 0;
+    asprintf(&filename_control, "%s.control", filename);
 
-        free(filename_control);
-        return 0;
-      }
+    this->fh_control = open(filename_control, O_RDONLY);
 
-      free(filename_control);      
+    if (this->fh_control == -1) {
+      xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+              _(LOG_MODULE ": failed to open '%s' (%s)\n"),
+              filename_control,
+              strerror(errno));
+       free(filename_control);
+      return 0;
     }
+     free(filename_control);      
+  }
 
-    {
-      char *filename_result = 0;
-      asprintf(&filename_result, "%s.result", filename);
+  {
+    char *filename_result = 0;
+    asprintf(&filename_result, "%s.result", filename);
 
-      this->fh_result = open(filename_result, O_WRONLY);
+    this->fh_result = open(filename_result, O_WRONLY);
 
-      if (this->fh_result == -1) {
-        perror("failed");
+    if (this->fh_result == -1) {
+      perror("failed");
         
-        xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
-                _(LOG_MODULE ": failed to open '%s' (%s)\n"),
-                filename_result,
-                strerror(errno));
+      xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+              _(LOG_MODULE ": failed to open '%s' (%s)\n"),
+              filename_result,
+              strerror(errno));
         
-        free(filename_result);
-        return 0;
-      }
-
       free(filename_result);
+      return 0;
     }
 
-    {
-      char *filename_event = 0;
-      asprintf(&filename_event, "%s.event", filename);
+    free(filename_result);
+  }
 
-      this->fh_event = open(filename_event, O_WRONLY);
+  {
+    char *filename_event = 0;
+    asprintf(&filename_event, "%s.event", filename);
 
-      if (this->fh_event == -1) {
-        perror("failed");
+    this->fh_event = open(filename_event, O_WRONLY);
 
-        xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
-                _(LOG_MODULE ": failed to open '%s' (%s)\n"),
-                filename_event,
-                strerror(errno));
-        
-        free(filename_event);
-        return 0;
-      }
+    if (this->fh_event == -1) {
+      perror("failed");
 
+      xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+              _(LOG_MODULE ": failed to open '%s' (%s)\n"),
+              filename_event,
+              strerror(errno));
+        
       free(filename_event);
+      return 0;
+    }
+
+    free(filename_event);
+  }
+
+  return 1;
+}
+
+static int vdr_plugin_open_vdr_socket(input_plugin_t *this_gen)
+{
+  vdr_input_plugin_t *this = (vdr_input_plugin_t *)this_gen;
+
+  lprintf("input_vdr: connecting to vdr-xine-server...\n");
+ 
+  if (!vdr_plugin_open_sockets(this))
+    return 0;
+   
+  return 1;
+}
+
+static int vdr_plugin_open(input_plugin_t *this_gen)
+{
+  vdr_input_plugin_t *this = (vdr_input_plugin_t *)this_gen;
+
+  lprintf("trying to open '%s'...\n", this->mrl);
+
+  if (this->fh == -1) 
+  {
+    int err = 0;
+
+    if (!strncasecmp(&this->mrl[0], "vdr:/", 5))
+    {
+       if (!vdr_plugin_open_vdr(this_gen))
+         return 0;
+    }
+    else
+    {
+      if (!strncasecmp(&this->mrl[0], "vdr-socket:/", 12))
+      {
+         if (!vdr_plugin_open_vdr_socket(this_gen))
+           return 0;
+      }
     }
 
     this->rpc_thread_shutdown = 0;
@@ -1571,7 +1668,6 @@
     }
   }
 
-
   /*
    * mrl accepted and opened successfully at this point
    *
@@ -1703,14 +1799,21 @@
   vdr_input_plugin_t *this;
   char               *mrl = strdup(data);
 
-  if (!strncasecmp(mrl, "vdr:/", 5))
+  if (!strncasecmp(mrl, "vdr-socket:/", 12))
   {
-    lprintf("filename '%s'\n", (char *)&mrl[ 4 ]);
+    lprintf("host '%s'\n", (char *)&mrl[ 12 ]);
   }
   else
   {
-    free(mrl);
-    return NULL;
+    if (!strncasecmp(mrl, "vdr:/", 5))
+    {
+      lprintf("filename '%s'\n", (char *)&mrl[ 4 ]);
+    }
+    else
+    {
+      free(mrl);
+      return NULL;
+    }
   }
 
   /*
I think i've read vdr-xine-0.8.0 will be the next version, maybe it
means we wont need those patches next time ...
(yes please add the network feature, hmm and if we could have several
xine playing different channels from the same vdr that would be even
greater ! (yeah yeah i know about streamdev)) *g*

--
  

Comments

Peter Weber Sept. 15, 2005, 12:40 p.m. UTC | #1
Hi,

>> [...]
>> there are hunks, but have a look at the xine-lib.h.rej file and
>> make the changes in xine-lib.c with an editor
>> [...]

>humm do you really do that by hand every time, ...
yes, i do. 
thank's for your files. if i have time, i will make a link on my homepage.

> I think i've read vdr-xine-0.8.0 will be the next version, maybe it
means we wont need those patches next time ...
>(yes please add the network feature, hmm and if we could have several
xine playing different channels from the same vdr that would be even
greater ! (yeah yeah i know about streamdev)) *g*

i hope so too,
@Reinhard, please, please, ...

bye
Horst
  

Patch

diff -Nru xine-0.7.5/xineLib.c xine-0.7.5+net/xineLib.c
--- xine-0.7.5/xineLib.c	2005-08-14 19:46:08.000000000 +0200
+++ xine-0.7.5+net/xineLib.c	2005-08-16 14:02:11.000000000 +0200
@@ -1855,6 +1855,10 @@ 
       , m_plugin(plugin)
       , m_settings(settings)
       , m_osdFlushRequired(false)
+      , fd_fifo0_serv(-1)
+      , fd_result_serv(-1)
+      , fd_control_serv(-1)
+      , fd_remote_serv(-1)
       , fd_fifo0(-1)
       , fd_result(-1)
       , fd_control(-1)
@@ -1941,6 +1945,34 @@ 
     m_eventSink = eventSink;
   }
 
+  int cXineLib::CreateServerSocket(unsigned short port)
+  {
+	int fd;
+	int onoff = 1;
+	struct sockaddr_in sain;
+
+	if ((fd = ::socket(PF_INET,SOCK_STREAM,0)) < 0) {
+		perror("socket failed.");
+		return -1;
+	}
+
+	sain.sin_addr.s_addr = 0;
+	sain.sin_port = htons(port);
+
+	::setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&onoff, sizeof(int) );
+
+	if (::bind(fd,(struct sockaddr*)&sain, sizeof(sain)) != 0) {
+		perror("bind failed.");
+		return -1;
+	}
+
+	if (::listen(fd,1) != 0) {
+		printf("listen failed.");
+		return -1;
+	}
+	return fd;
+  }
+  
   bool cXineLib::Open()
   {
     ::unlink(m_fifoNameExtControl.c_str());
@@ -2017,6 +2049,25 @@ 
     }
     
     ::umask(origUmask);
+/*
+{ .path = FIFO_STREAM,           .mode = 0644, .port = 18701 },
+{ .path = FIFO_STREAM_CONTROL,   .mode = 0644, .port = 18702 },
+{ .path = FIFO_STREAM_RESULT,    .mode = 0666, .port = 18703 },
+{ .path = FIFO_STREAM_EVENT,     .mode = 0666, .port = 18704 },
+	
+*/
+	/* sockets - create the server sockets */
+	if ((fd_fifo0_serv = CreateServerSocket(18701)) == -1) 
+		return false;
+		
+	if ((fd_control_serv = CreateServerSocket(18702)) == -1)
+		return false;
+		
+	if ((fd_result_serv = CreateServerSocket(18703)) == -1)
+		return false;
+
+	if ((fd_remote_serv = CreateServerSocket(18704)) == -1)
+		return false;
     
     if (!Start())
       return false;
@@ -2049,6 +2100,11 @@ 
     ::unlink(m_fifoNameRemote.c_str());
     ::unlink(m_fifoNameStream.c_str());
     ::rmdir(m_fifoDir.c_str());
+
+	::close(fd_remote_serv);
+	::close(fd_result_serv);
+	::close(fd_control_serv);
+	::close(fd_fifo0_serv);
   }
 
   void cXineLib::internalPaused(const bool paused)
@@ -2300,12 +2356,37 @@ 
 //    fprintf(stderr, "Action done\n");
   }
   
+  int cXineLib::SocketAcceptHelper(int fd)
+  {
+	  // use cPoller for checking server socket for incoming requests
+	  cPoller poller(fd,0); /* POLLIN */
+	  struct sockaddr sain;
+	  socklen_t len = sizeof(sain);
+	  int client;
+	  
+//	  ::fprintf(stderr,"vdr-xine: polling for connection on %d...\n",fd);
+	  if (!poller.Poll(100))
+		  return -1;
+
+//	  ::fprintf(stderr,"vdr-xine: incoming requests on %d\n",fd);
+	  if ((client = ::accept(fd,(struct sockaddr *) &sain,&len)) == -1) {
+		  ::fprintf(stderr,"vdr-xine: fifo0 failed to accept...\n");
+		  return -1;
+	  }
+//	  ::fprintf(stderr,"vdr-xine: successful request on %d (client: %d)\n",fd,client);
+	  return client;
+  }
+
   bool cXineLib::checkConnect()
   {
+
+	  /* files */
 //    bool reinit = false;
       
 //    if (-1 == fd_fifo0)
 //    {
+//
+/*
       fd_fifo0 = ::open(m_fifoNameStream.c_str(), O_WRONLY | O_NONBLOCK);
       if (-1 == fd_fifo0)
         return false;
@@ -2321,6 +2402,23 @@ 
 
       ::fcntl(fd_fifo0 , F_SETFL, ~O_NONBLOCK & ::fcntl(fd_fifo0 , F_GETFL, 0));
       ::fcntl(fd_remote, F_SETFL, ~O_NONBLOCK & ::fcntl(fd_remote, F_GETFL, 0));
+*/    
+	  /* sockets */
+
+	  if (fd_fifo0_serv == -1)
+		  return false;
+	 
+	  if ((fd_fifo0 = SocketAcceptHelper(fd_fifo0_serv)) == -1)
+		  return false;
+
+	  if ((fd_control = SocketAcceptHelper(fd_control_serv)) == -1)
+		  return false;
+		
+	  if ((fd_result = SocketAcceptHelper(fd_result_serv)) == -1)
+		  return false;
+	  
+	  if ((fd_remote = SocketAcceptHelper(fd_remote_serv)) == -1)
+		  return false;
       
       internalPaused(false);
       
diff -Nru xine-0.7.5/xineLib.h xine-0.7.5+net/xineLib.h
--- xine-0.7.5/xineLib.h	2005-08-14 12:55:10.000000000 +0200
+++ xine-0.7.5+net/xineLib.h	2005-08-16 12:18:50.000000000 +0200
@@ -137,7 +137,13 @@ 
     }
     
   private:    
+ /* sockets */
+    int CreateServerSocket(unsigned short port);
+    int SocketAcceptHelper(int fd);
+    int fd_fifo0_serv, fd_result_serv, fd_control_serv, fd_remote_serv;
     int fd_fifo0, fd_result, fd_control, fd_remote;
+
+
     cMutex m_ioMutex, m_dataMutex, m_disconnectMutex;
     cMutex &m_osdMutex;