summaryrefslogtreecommitdiff
path: root/xine/post.c
diff options
context:
space:
mode:
Diffstat (limited to 'xine/post.c')
-rw-r--r--xine/post.c868
1 files changed, 868 insertions, 0 deletions
diff --git a/xine/post.c b/xine/post.c
new file mode 100644
index 00000000..615f8b37
--- /dev/null
+++ b/xine/post.c
@@ -0,0 +1,868 @@
+/*
+ * Copyright (C) 2003 by Dirk Meyer
+ *
+ * This file is part of xine, a unix video player.
+ *
+ * xine is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * xine is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * The code is taken from xine-ui/src/xitk/post.c at changed to work with fbxine
+ *
+ * Modified for VDR xineliboutput plugin by Petri Hintukainen, 2006
+ * - runtime re-configuration (load/unload, enable/disable)
+ * - support for multiple streams
+ * - support for mosaico post plugin (picture-in-picture)
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "post.h"
+
+#if 1
+# include <sys/types.h>
+# include <linux/unistd.h>
+# include <errno.h>
+
+# define LOG_MODULENAME "[xine-post] "
+# include "../logdefs.h"
+
+ /* from xine_frontend.c or vdr tools.c: */
+ extern int SysLogLevel; /* errors and info, no debug */
+ /* from xine_frontend.c: */
+ extern int LogToSysLog; /* log to syslog instead of console */
+
+# if !defined(XINELIBOUTPUT_DEBUG_STDOUT) && \
+ !defined(XINELIBOUTPUT_DEBUG_STDERR)
+
+# undef x_syslog
+
+ pid_t gettid(void); /*_syscall0(pid_t, gettid);*/
+
+ static void x_syslog(int level, const char *fmt, ...)
+ {
+ va_list argp;
+ char buf[512];
+ va_start(argp, fmt);
+ vsnprintf(buf, 512, fmt, argp);
+ if(!LogToSysLog) {
+ printf(LOG_MODULENAME "%s\n", buf);
+ } else {
+ syslog(level, "[%d] " LOG_MODULENAME "%s", gettid(), buf);
+ }
+ va_end(argp);
+ }
+# endif
+
+#else
+# define LOGERR(x...)
+# define LOGMSG(x...)
+# define LOGDBG(x...)
+# define TRACELINE (void)
+#endif
+
+#define fe_t post_plugins_t
+
+typedef struct {
+ xine_post_t *post;
+ xine_post_api_t *api;
+ xine_post_api_descr_t *descr;
+ xine_post_api_parameter_t *param;
+ char *param_data;
+
+ int x;
+ int y;
+
+ int readonly;
+
+ char **properties_names;
+} post_object_t;
+
+
+static int __pplugin_retrieve_parameters(post_object_t *pobj)
+{
+ xine_post_in_t *input_api;
+
+ if((input_api = (xine_post_in_t *) xine_post_input(pobj->post,
+ "parameters"))) {
+ xine_post_api_t *post_api;
+ xine_post_api_descr_t *api_descr;
+ xine_post_api_parameter_t *parm;
+ int pnum = 0;
+
+ post_api = (xine_post_api_t *) input_api->data;
+
+ api_descr = post_api->get_param_descr();
+
+ parm = api_descr->parameter;
+ pobj->param_data = malloc(api_descr->struct_size);
+
+ while(parm->type != POST_PARAM_TYPE_LAST) {
+
+ post_api->get_parameters(pobj->post, pobj->param_data);
+
+ if(!pnum)
+ pobj->properties_names = (char **) xine_xmalloc(sizeof(char *) * 2);
+ else
+ pobj->properties_names = (char **)
+ realloc(pobj->properties_names, sizeof(char *) * (pnum + 2));
+
+ pobj->properties_names[pnum] = strdup(parm->name);
+ pobj->properties_names[pnum + 1] = NULL;
+ pnum++;
+ parm++;
+ }
+
+ pobj->api = post_api;
+ pobj->descr = api_descr;
+ pobj->param = api_descr->parameter;
+
+ return 1;
+ }
+
+ return 0;
+}
+
+static void _pplugin_update_parameter(post_object_t *pobj)
+{
+ pobj->api->set_parameters(pobj->post, pobj->param_data);
+ pobj->api->get_parameters(pobj->post, pobj->param_data);
+}
+
+static void __pplugin_update_parameters(xine_post_t *post, char *args)
+{
+ post_object_t pobj;
+ char *p;
+
+ memset(&pobj, 0, sizeof(post_object_t));
+ pobj.post = post;
+
+ if(__pplugin_retrieve_parameters(&pobj)) {
+ int i;
+
+ if(pobj.properties_names && args && *args) {
+ char *param;
+
+ while((param = xine_strsep(&args, ",")) != NULL) {
+
+ p = param;
+
+ while((*p != '\0') && (*p != '='))
+ p++;
+
+ if(p && strlen(p)) {
+ int param_num = 0;
+
+ *p++ = '\0';
+
+ while(pobj.properties_names[param_num]
+ && strcasecmp(pobj.properties_names[param_num], param))
+ param_num++;
+
+ if(pobj.properties_names[param_num]) {
+
+ pobj.param = pobj.descr->parameter;
+ pobj.param += param_num;
+ pobj.readonly = pobj.param->readonly;
+
+ switch(pobj.param->type) {
+ case POST_PARAM_TYPE_INT:
+ if(!pobj.readonly) {
+ if(pobj.param->enum_values) {
+ char **values = pobj.param->enum_values;
+ int i = 0;
+
+ while(values[i]) {
+ if(!strcasecmp(values[i], p)) {
+ *(int *)(pobj.param_data + pobj.param->offset) = i;
+ break;
+ }
+ i++;
+ }
+
+ if( !values[i] )
+ *(int *)(pobj.param_data + pobj.param->offset) = (int) strtol(p, &p, 10);
+ } else {
+ *(int *)(pobj.param_data + pobj.param->offset) = (int) strtol(p, &p, 10);
+ }
+ _pplugin_update_parameter(&pobj);
+ }
+ break;
+
+ case POST_PARAM_TYPE_DOUBLE:
+ if(!pobj.readonly) {
+ *(double *)(pobj.param_data + pobj.param->offset) = strtod(p, &p);
+ _pplugin_update_parameter(&pobj);
+ }
+ break;
+
+ case POST_PARAM_TYPE_CHAR:
+ case POST_PARAM_TYPE_STRING:
+ if(!pobj.readonly) {
+ if(pobj.param->type == POST_PARAM_TYPE_CHAR) {
+ int maxlen = pobj.param->size / sizeof(char);
+
+ snprintf((char *)(pobj.param_data + pobj.param->offset), maxlen, "%s", p);
+ _pplugin_update_parameter(&pobj);
+ }
+ else
+ fprintf(stderr, "parameter type POST_PARAM_TYPE_STRING not supported yet.\n");
+ }
+ break;
+
+ case POST_PARAM_TYPE_STRINGLIST: /* unsupported */
+ if(!pobj.readonly)
+ fprintf(stderr, "parameter type POST_PARAM_TYPE_STRINGLIST not supported yet.\n");
+ break;
+
+ case POST_PARAM_TYPE_BOOL:
+ if(!pobj.readonly) {
+ *(int *)(pobj.param_data + pobj.param->offset) = ((int) strtol(p, &p, 10)) ? 1 : 0;
+ _pplugin_update_parameter(&pobj);
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ i = 0;
+
+ while(pobj.properties_names[i]) {
+ free(pobj.properties_names[i]);
+ i++;
+ }
+
+ free(pobj.properties_names);
+ }
+
+ free(pobj.param_data);
+ }
+}
+
+/* -post <name>:option1=value1,option2=value2... */
+static post_element_t **pplugin_parse_and_load(fe_t *fe,
+ int plugin_type,
+ const char *pchain,
+ int *post_elements_num)
+{
+ post_element_t **post_elements = NULL;
+ char *post_chain;
+
+ *post_elements_num = 0;
+
+ if(pchain && strlen(pchain)) {
+ char *p;
+
+ xine_strdupa(post_chain, pchain);
+
+ while((p = xine_strsep(&post_chain, ";"))) {
+
+ if(p && strlen(p)) {
+ char *plugin, *args = NULL;
+ xine_post_t *post;
+
+ while(*p == ' ')
+ p++;
+
+ plugin = strdup(p);
+
+ if((p = strchr(plugin, ':')))
+ *p++ = '\0';
+
+ if(p && (strlen(p) > 1))
+ args = p;
+#if 0
+ post = xine_post_init(fe->xine, plugin, 0,
+ &fe->audio_port, &fe->video_port);
+#else
+ if(plugin_type == XINE_POST_TYPE_VIDEO_COMPOSE) {
+ post = xine_post_init(fe->xine, plugin, 2,
+ &fe->audio_port, &fe->video_port);
+ } else
+ post = xine_post_init(fe->xine, plugin, 0,
+ &fe->audio_port, &fe->video_port);
+#endif
+
+ if (post && plugin_type) {
+ if (post->type != plugin_type) {
+ xine_post_dispose(fe->xine, post);
+ post = NULL;
+ }
+ }
+
+ if(post) {
+
+ if(!(*post_elements_num))
+ post_elements = (post_element_t **) xine_xmalloc(sizeof(post_element_t *) * 2);
+ else
+ post_elements = (post_element_t **)
+ realloc(post_elements, sizeof(post_element_t *) * ((*post_elements_num) + 2));
+
+ post_elements[(*post_elements_num)] = (post_element_t *)
+ xine_xmalloc(sizeof(post_element_t));
+ post_elements[(*post_elements_num)]->post = post;
+ post_elements[(*post_elements_num)]->name = strdup(plugin);
+#if 1
+ post_elements[(*post_elements_num)]->args = args ? strdup(args) : NULL;
+ post_elements[(*post_elements_num)]->enable = 0;
+#endif
+ (*post_elements_num)++;
+ post_elements[(*post_elements_num)] = NULL;
+
+ __pplugin_update_parameters(post, args);
+ }
+
+ free(plugin);
+ }
+ }
+ }
+
+ return post_elements;
+}
+
+void pplugin_parse_and_store_post(fe_t *fe, int plugin_type,
+ const char *post_chain)
+{
+ post_element_t ***_post_elements;
+ int *_post_elements_num;
+ post_element_t **posts = NULL;
+ int num;
+
+ switch(plugin_type) {
+ case XINE_POST_TYPE_VIDEO_FILTER:
+ _post_elements = &fe->post_video_elements;
+ _post_elements_num = &fe->post_video_elements_num;
+ break;
+ case XINE_POST_TYPE_VIDEO_COMPOSE:
+ _post_elements = &fe->post_pip_elements;
+ _post_elements_num = &fe->post_pip_elements_num;
+ break;
+ case XINE_POST_TYPE_AUDIO_VISUALIZATION:
+ _post_elements = &fe->post_vis_elements;
+ _post_elements_num = &fe->post_vis_elements_num;
+ break;
+ default:
+ _post_elements = &fe->post_audio_elements;
+ _post_elements_num = &fe->post_audio_elements_num;
+ break;
+ }
+
+ if((posts = pplugin_parse_and_load(fe, plugin_type, post_chain, &num))) {
+ if(*_post_elements_num) {
+ int i;
+ int ptot = *_post_elements_num + num;
+
+ *_post_elements = (post_element_t **) realloc(*_post_elements,
+ sizeof(post_element_t *) * (ptot + 1));
+ for(i = *_post_elements_num; i < ptot; i++)
+ (*_post_elements)[i] = posts[i - *_post_elements_num];
+
+ (*_post_elements)[i] = NULL;
+ (*_post_elements_num) += num;
+
+ }
+ else {
+ *_post_elements = posts;
+ *_post_elements_num = num;
+ }
+ }
+}
+
+
+void vpplugin_parse_and_store_post(fe_t *fe, const char *post_chain)
+{
+ pplugin_parse_and_store_post(fe, XINE_POST_TYPE_VIDEO_FILTER, post_chain);
+ pplugin_parse_and_store_post(fe, XINE_POST_TYPE_VIDEO_COMPOSE, post_chain);
+}
+
+
+void applugin_parse_and_store_post(fe_t *fe, const char *post_chain)
+{
+ pplugin_parse_and_store_post(fe, XINE_POST_TYPE_AUDIO_FILTER, post_chain);
+ pplugin_parse_and_store_post(fe, XINE_POST_TYPE_AUDIO_VISUALIZATION, post_chain);
+}
+
+
+static void _vpplugin_unwire(fe_t *fe)
+{
+ xine_post_out_t *vo_source;
+
+ vo_source = xine_get_video_source(fe->stream);
+
+ (void) xine_post_wire_video_port(vo_source, fe->video_port);
+}
+
+
+static void _applugin_unwire(fe_t *fe)
+{
+ xine_post_out_t *ao_source;
+
+ ao_source = xine_get_audio_source(fe->stream);
+
+ (void) xine_post_wire_audio_port(ao_source, fe->audio_port);
+}
+
+
+static void _vpplugin_rewire_from_post_elements(fe_t *fe, post_element_t **post_elements, int post_elements_num)
+{
+ if(post_elements_num) {
+ xine_post_out_t *vo_source;
+ int i = 0;
+
+ for(i = (post_elements_num - 1); i >= 0; i--) {
+ const char *const *outs = xine_post_list_outputs(post_elements[i]->post);
+ const xine_post_out_t *vo_out = xine_post_output(post_elements[i]->post, (char *) *outs);
+ if(i == (post_elements_num - 1)) {
+ xine_post_wire_video_port((xine_post_out_t *) vo_out, fe->video_port);
+ }
+ else {
+ const xine_post_in_t *vo_in;
+ int err;
+
+ /* look for standard input names */
+ vo_in = xine_post_input(post_elements[i + 1]->post, "video");
+ if( !vo_in )
+ vo_in = xine_post_input(post_elements[i + 1]->post, "video in");
+ err = xine_post_wire((xine_post_out_t *) vo_out,
+ (xine_post_in_t *) vo_in);
+ }
+ }
+
+ if(fe->post_pip_enable &&
+ !strcmp(post_elements[0]->name, "mosaico")) {
+ vo_source = xine_get_video_source(fe->pip_stream);
+ xine_post_wire_video_port(vo_source,
+ post_elements[0]->post->video_input[1]);
+ }
+
+ if(fe->slave_stream)
+ vo_source = xine_get_video_source(fe->slave_stream);
+ else
+ vo_source = xine_get_video_source(fe->stream);
+ xine_post_wire_video_port(vo_source,
+ post_elements[0]->post->video_input[0]);
+ }
+}
+
+
+static void _applugin_rewire_from_post_elements(fe_t *fe, post_element_t **post_elements, int post_elements_num)
+{
+ if(post_elements_num) {
+ xine_post_out_t *ao_source;
+ int i = 0;
+
+ for(i = (post_elements_num - 1); i >= 0; i--) {
+ const char *const *outs = xine_post_list_outputs(post_elements[i]->post);
+ const xine_post_out_t *ao_out = xine_post_output(post_elements[i]->post, (char *) *outs);
+
+ if(i == (post_elements_num - 1)) {
+ xine_post_wire_audio_port((xine_post_out_t *) ao_out, fe->audio_port);
+ }
+ else {
+ const xine_post_in_t *ao_in;
+ int err;
+
+ /* look for standard input names */
+ ao_in = xine_post_input(post_elements[i + 1]->post, "audio");
+ if( !ao_in )
+ ao_in = xine_post_input(post_elements[i + 1]->post, "audio in");
+
+ err = xine_post_wire((xine_post_out_t *) ao_out, (xine_post_in_t *) ao_in);
+ }
+ }
+
+ if(fe->slave_stream)
+ ao_source = xine_get_audio_source(fe->slave_stream);
+ else
+ ao_source = xine_get_audio_source(fe->stream);
+ xine_post_wire_audio_port(ao_source, post_elements[0]->post->audio_input[0]);
+ }
+}
+
+static post_element_t **_pplugin_join_deinterlace_and_post_elements(fe_t *fe, int *post_elements_num)
+{
+ post_element_t **post_elements;
+ int i = 0, j = 0, n = 0;
+
+ *post_elements_num = 0;
+ if( fe->post_video_enable )
+ *post_elements_num += fe->post_video_elements_num;
+
+ if( fe->post_pip_enable )
+ *post_elements_num += fe->post_pip_elements_num;
+
+ if( *post_elements_num == 0 )
+ return NULL;
+
+ post_elements = (post_element_t **)
+ xine_xmalloc(sizeof(post_element_t *) * (*post_elements_num));
+
+ if(fe->post_pip_enable)
+ for( i = 0; i < fe->post_pip_elements_num; i++ ) {
+ if(fe->post_pip_elements[i]->enable)
+ post_elements[i+j-n] = fe->post_pip_elements[i];
+ else
+ n++;
+ }
+
+ if(fe->post_video_enable)
+ for( j = 0; j < fe->post_video_elements_num; j++ ) {
+ if(fe->post_video_elements[j]->enable)
+ post_elements[i+j-n] = fe->post_video_elements[j];
+ else
+ n++;
+ }
+
+ *post_elements_num -= n;
+ if( *post_elements_num == 0 ) {
+ free(post_elements);
+ return NULL;
+ }
+
+ return post_elements;
+}
+
+static post_element_t **_pplugin_join_visualization_and_post_elements(fe_t *fe, int *post_elements_num)
+{
+ post_element_t **post_elements;
+ int i = 0, j = 0, n = 0;
+
+ *post_elements_num = 0;
+ if( fe->post_audio_enable )
+ *post_elements_num += fe->post_audio_elements_num;
+
+ if( fe->post_vis_enable )
+ *post_elements_num += fe->post_vis_elements_num;
+
+ if( *post_elements_num == 0 )
+ return NULL;
+
+ post_elements = (post_element_t **)
+ xine_xmalloc(sizeof(post_element_t *) * (*post_elements_num));
+
+ if(fe->post_audio_enable)
+ for( j = 0; j < fe->post_audio_elements_num; j++ ) {
+ if(fe->post_audio_elements[j]->enable)
+ post_elements[i+j-n] = fe->post_audio_elements[j];
+ else
+ n++;
+ }
+
+ if(fe->post_vis_enable)
+ for( i = 0; i < fe->post_vis_elements_num; i++ ) {
+ if(fe->post_vis_elements[i]->enable)
+ post_elements[i+j-n] = fe->post_vis_elements[i];
+ else
+ n++;
+ }
+
+ *post_elements_num -= n;
+ if( *post_elements_num == 0 ) {
+ free(post_elements);
+ return NULL;
+ }
+
+ return post_elements;
+}
+
+static void _vpplugin_rewire(fe_t *fe)
+{
+ static post_element_t **post_elements;
+ int post_elements_num;
+
+ post_elements = _pplugin_join_deinterlace_and_post_elements(fe, &post_elements_num);
+
+ if( post_elements ) {
+ _vpplugin_rewire_from_post_elements(fe, post_elements, post_elements_num);
+
+ free(post_elements);
+ }
+}
+
+static void _applugin_rewire(fe_t *fe)
+{
+ static post_element_t **post_elements;
+ int post_elements_num;
+
+ post_elements = _pplugin_join_visualization_and_post_elements(fe, &post_elements_num);
+
+ if( post_elements ) {
+ _applugin_rewire_from_post_elements(fe, post_elements, post_elements_num);
+
+ free(post_elements);
+ }
+}
+
+void vpplugin_rewire_posts(fe_t *fe)
+{
+ /*TRACELINE;*/
+ _vpplugin_unwire(fe);
+ _vpplugin_rewire(fe);
+}
+
+void applugin_rewire_posts(fe_t *fe)
+{
+ /*TRACELINE;*/
+ _applugin_unwire(fe);
+ _applugin_rewire(fe);
+}
+
+static int _pplugin_enable_post(post_plugins_t *fe, const char *name,
+ const char *args,
+ post_element_t **post_elements,
+ int post_elements_num,
+ int *found)
+{
+ int i, result = 0;
+
+ for(i=0; i<post_elements_num; i++)
+ if(post_elements[i])
+ if(!strcmp(post_elements[i]->name, name)) {
+ if(post_elements[i]->enable == 0) {
+ post_elements[i]->enable = 1;
+ result = 1;
+ }
+
+ *found = 1;
+
+ if(args && *args) {
+ char *tmp = strdup(args);
+ __pplugin_update_parameters(post_elements[i]->post, tmp);
+ free(tmp);
+ if(post_elements[i]->args)
+ free(post_elements[i]->args);
+ post_elements[i]->args = strdup(args);
+ }
+ }
+
+ return result;
+}
+
+static int _vpplugin_enable_post(post_plugins_t *fe, const char *name,
+ const char *args, int *found)
+{
+ return
+ _pplugin_enable_post(fe, name, args, fe->post_video_elements,
+ fe->post_video_elements_num, found) +
+ _pplugin_enable_post(fe, name, args, fe->post_pip_elements,
+ fe->post_pip_elements_num, found);
+}
+
+static int _applugin_enable_post(post_plugins_t *fe, const char *name,
+ const char *args, int *found)
+{
+ return
+ _pplugin_enable_post(fe, name, args, fe->post_audio_elements,
+ fe->post_audio_elements_num, found) +
+ _pplugin_enable_post(fe, name, args, fe->post_vis_elements,
+ fe->post_vis_elements_num, found);
+}
+
+static char * _pp_name(const char *initstr)
+{
+ char *name = strdup(initstr), *pt;
+
+ if(NULL != (pt = strchr(name, ':')))
+ *pt = 0;
+
+ return name;
+}
+
+static const char * _pp_args(const char *initstr)
+{
+ char *pt = strchr(initstr, ':');
+ if(pt && *(pt+1))
+ return pt+1;
+ return NULL;
+}
+
+int vpplugin_enable_post(post_plugins_t *fe, const char *initstr,
+ int *found)
+{
+ char *name = _pp_name(initstr);
+ const char *args = _pp_args(initstr);
+
+ int result = _vpplugin_enable_post(fe, name, args, found);
+
+ LOGDBG(" * enable post %s --> %s, %s", name,
+ *found ? "found" : "not found",
+ result ? "enabled" : "no action");
+
+ if(!*found) {
+ LOGDBG(" * loading post %s", initstr);
+ vpplugin_parse_and_store_post(fe, initstr);
+ result = _vpplugin_enable_post(fe, name, NULL, found);
+ LOGDBG(" * enable post %s --> %s, %s", name,
+ *found ? "found" : "not found",
+ result ? "enabled" : "no action");
+ }
+
+ if(result)
+ _vpplugin_unwire(fe);
+
+ free(name);
+ return result;
+}
+
+int applugin_enable_post(post_plugins_t *fe, const char *initstr,
+ int *found)
+{
+ const char *args = _pp_args(initstr);
+ char *name = _pp_name(initstr);
+
+ int result = _vpplugin_enable_post(fe, name, args, found);
+
+ LOGDBG(" * enable post %s --> %s, %s", name,
+ *found ? "found" : "not found",
+ result ? "enabled" : "no action");
+
+ if(!*found) {
+ LOGDBG(" * loading post %s", initstr);
+ applugin_parse_and_store_post(fe, initstr);
+ result = _applugin_enable_post(fe, name, NULL, found);
+ LOGDBG(" * enable post %s --> %s, %s", name,
+ *found ? "found" : "not found",
+ result ? "enabled" : "no action");
+ }
+
+ if(result)
+ _applugin_unwire(fe);
+
+ free(name);
+ return result;
+}
+
+static int _pplugin_disable_post(post_plugins_t *fe, const char *name,
+ post_element_t **post_elements,
+ int post_elements_num)
+{
+ int i, result = 0;
+ /*TRACELINE;*/
+ if(post_elements)
+ for(i = 0; i < post_elements_num; i++)
+ if(post_elements[i])
+ if(!name || !strcmp(post_elements[i]->name, name))
+ if(post_elements[i]->enable == 1) {
+ post_elements[i]->enable = 0;
+ result = 1;
+ }
+ return result;
+}
+
+int vpplugin_disable_post(post_plugins_t *fe, const char *name)
+{
+ /*TRACELINE;*/
+ if(_pplugin_disable_post(fe, name, fe->post_video_elements,
+ fe->post_video_elements_num) ||
+ _pplugin_disable_post(fe, name, fe->post_pip_elements,
+ fe->post_pip_elements_num)) {
+ _vpplugin_unwire(fe);
+ return 1;
+ }
+ return 0;
+}
+
+int applugin_disable_post(post_plugins_t *fe, const char *name)
+{
+ /*TRACELINE;*/
+ if(_pplugin_disable_post(fe, name, fe->post_audio_elements,
+ fe->post_audio_elements_num) ||
+ _pplugin_disable_post(fe, name, fe->post_vis_elements,
+ fe->post_vis_elements_num)) {
+ _applugin_unwire(fe);
+ return 1;
+ }
+ return 0;
+}
+
+static int _pplugin_unload_post(post_plugins_t *fe, const char *name,
+ post_element_t ***post_elements,
+ int *post_elements_num)
+{
+ /* does not unwrire plugins ! */
+ int i, j, result = 0;
+ /*TRACELINE;*/
+
+ if(!*post_elements || !*post_elements_num)
+ return 0;
+
+ for(i=0; i < *post_elements_num; i++)
+ if((*post_elements)[i])
+ if(!name || !strcmp((*post_elements)[i]->name, name)) {
+
+ if((*post_elements)[i]->enable == 0) {
+ xine_post_dispose(fe->xine, (*post_elements)[i]->post);
+
+ free((*post_elements)[i]->name);
+
+ if((*post_elements)[i]->args)
+ free((*post_elements)[i]->args);
+
+ free((*post_elements)[i]);
+
+ for(j=i; j < *post_elements_num - 1; j++)
+ (*post_elements)[j] = (*post_elements)[j+1];
+
+ (*post_elements_num) --;
+ (*post_elements)[(*post_elements_num)] = 0;
+
+ result = 1;
+ } else {
+ LOGDBG("Unload %s failed: plugin enabled and in use", name);
+ }
+ }
+
+ if(*post_elements_num <= 0) {
+ if(*post_elements)
+ free(*post_elements);
+ *post_elements = NULL;
+ }
+
+ return result;
+}
+
+int vpplugin_unload_post(post_plugins_t *fe, const char *name)
+{
+ int result = vpplugin_disable_post(fe, name);
+
+ /* unload already disabled plugins too (result=0) */
+ _pplugin_unload_post(fe, name, &fe->post_video_elements,
+ &fe->post_video_elements_num);
+ _pplugin_unload_post(fe, name, &fe->post_pip_elements,
+ &fe->post_pip_elements_num);
+
+ /* result indicates only unwiring condition, not unload result */
+ return result;
+}
+
+int applugin_unload_post(post_plugins_t *fe, const char *name)
+{
+ int result = applugin_disable_post(fe, name);
+
+ /* unload already disabled plugins too (result=0) */
+ _pplugin_unload_post(fe, name, &fe->post_audio_elements,
+ &fe->post_audio_elements_num);
+ _pplugin_unload_post(fe, name, &fe->post_vis_elements,
+ &fe->post_vis_elements_num);
+
+ /* result indicates only unwiring condition, not unload result */
+ return result;
+}
+
+
+/* end of post.c */
+