summaryrefslogtreecommitdiff
path: root/xine_input_vdr.c
diff options
context:
space:
mode:
authorphintuka <phintuka>2006-08-23 06:50:20 +0000
committerphintuka <phintuka>2006-08-23 06:50:20 +0000
commit1e26f013029efd068b045b13d0a7f60853efd033 (patch)
tree2a9079ec638e3476066173f029f2ee090db275ad /xine_input_vdr.c
parent70dcc1222853937bfd7c971ac0a7bb1513769e83 (diff)
downloadxineliboutput-1e26f013029efd068b045b13d0a7f60853efd033.tar.gz
xineliboutput-1e26f013029efd068b045b13d0a7f60853efd033.tar.bz2
Image grabbing for remote frontends
Poll instead of busy wait when writing to control stream
Diffstat (limited to 'xine_input_vdr.c')
-rw-r--r--xine_input_vdr.c82
1 files changed, 72 insertions, 10 deletions
diff --git a/xine_input_vdr.c b/xine_input_vdr.c
index 605c3a69..bfd342f1 100644
--- a/xine_input_vdr.c
+++ b/xine_input_vdr.c
@@ -4,7 +4,7 @@
* See the main source file 'xineliboutput.c' for copyright information and
* how to reach the author.
*
- * $Id: xine_input_vdr.c,v 1.31 2006-08-22 08:32:38 phintuka Exp $
+ * $Id: xine_input_vdr.c,v 1.32 2006-08-23 06:50:20 phintuka Exp $
*
*/
@@ -854,27 +854,49 @@ static int io_select_rd (int fd)
return XIO_TIMEOUT; /* newer reached ... */
}
-static void write_control(vdr_input_plugin_t *this, const char *str)
+static void write_control_data(vdr_input_plugin_t *this, const char *str, size_t len)
{
- size_t len = (size_t)strlen(str);
size_t ret;
-
do {
if(this->fd_control < 0)
return;
errno = 0;
- if(len != (ret = write(this->fd_control, str, len))) {
- /*if(ret <= 0 && (errno == EINTR || errno == EAGAIN))*/
- if(ret <= 0 && errno == EAGAIN)
- continue;
- if(ret <= 0 && errno == EINTR)
+ if(len == (ret = write(this->fd_control, str, len)))
+ return;
+
+ if(ret <= 0) {
+ if(errno == EAGAIN) {
+ /* poll socket instead of busy wait */
+ fd_set fdset, eset;
+ struct timeval select_timeout;
+ FD_ZERO (&fdset);
+ FD_ZERO (&eset);
+ FD_SET (this->fd_control, &fdset);
+ FD_SET (this->fd_control, &eset);
+ select_timeout.tv_sec = 0;
+ select_timeout.tv_usec = 500*1000; /* 500 ms */
+ errno = 0;
+ if(1 == select (this->fd_control + 1, NULL, &fdset, &eset, &select_timeout))
+ continue;
+ LOGERR("write_control failed (poll timeout)");
+ } else if(errno == EINTR)
LOGERR("write_control failed (%d) EINTR", ret);
else
LOGERR("write_control failed (%d)", ret);
close(this->fd_control);
this->fd_control = -1;
+ } else {
+ len -= ret;
+ str += ret;
+ continue;
}
- } while(0);
+ } while(1);
+}
+
+static void write_control(vdr_input_plugin_t *this, const char *str)
+{
+ size_t len = (size_t)strlen(str);
+ write_control_data(this, str, len);
}
static void printf_control(vdr_input_plugin_t *this, const char *fmt, ...)
@@ -1643,6 +1665,7 @@ static int exec_osd_command(vdr_input_plugin_t *this, osd_command_t *cmd)
ov_event.event_type = OVERLAY_EVENT_SHOW;
ov_event.object.handle = handle;
ov_event.object.overlay = &ov_overlay;
+ ov_event.object.object_type = 1; /* menu */
memset( ov_event.object.overlay, 0, sizeof(*ov_event.object.overlay) );
#if XINE_VERSION_CODE < 10101
@@ -2290,6 +2313,41 @@ static int handle_control_playfile(vdr_input_plugin_t *this, const char *cmd)
return err ? CONTROL_PARAM_ERROR : CONTROL_OK;
}
+static int handle_control_grab(vdr_input_plugin_t *this, const char *cmd)
+{
+ int quality, width, height, jpeg;
+ jpeg = !strcmp(cmd+5,"JPEG");
+
+ if(3 == sscanf(cmd+5+4, "%d %d %d", &quality, &width, &height)) {
+ grab_data_t *data = NULL;
+ uint64_t t = monotonic_time_ms();
+ LOGDBG("GRAB: jpeg=%d quality=%d w=%d h=%d", jpeg, quality, width, height);
+ /*VDR_ENTRY_UNLOCK();*/ /* grab takes long time so we may lose data connection ... */
+
+ if(this->funcs.fe_control)
+ data = (grab_data_t*)(this->funcs.fe_control(this->funcs.fe_handle, cmd));
+ if(this->fd_control >= 0) {
+ printf_control(this, "RESULT %d %d\r\n", this->token, data?data->size:-1);
+ if(data && data->size>0 && data->data) {
+ char zero=0;
+ /* TODO: should lock control stream ; if anythings is written in middle -> Boom! */
+ printf_control(this, "GRAB %d %d\r\n", this->token, data->size);
+ write_control_data(this, &zero, 1);
+ write_control_data(this, data->data, data->size);
+ }
+ }
+
+ if(data)
+ free(data->data);
+ free(data);
+ /*VDR_ENTRY_LOCK(CONTROL_DISCONNECTED);*/
+ LOGDBG("grab took %d ms", (int)(monotonic_time_ms() - t));
+ return CONTROL_OK;
+ }
+
+ return CONTROL_PARAM_ERROR;
+}
+
static int handle_control_substream(vdr_input_plugin_t *this, const char *cmd)
{
unsigned int pid;
@@ -2929,6 +2987,10 @@ static int vdr_plugin_parse_control(input_plugin_t *this_gen, const char *cmd)
err = CONTROL_PARAM_ERROR;
}
+ } else if(!strncasecmp(cmd, "GRAB ", 5)) {
+ handle_control_grab(this, cmd);
+ /*LOGMSG("unimplemented control %s", cmd);*/
+
} else {
LOGMSG("unknown control %s", cmd);
err = CONTROL_UNKNOWN;