Commit 01bc9692 authored by Jean-Paul Saman's avatar Jean-Paul Saman

Rewrite old command definitions to no longer use those filthy macros. Added...

Rewrite old command definitions to no longer use those filthy macros. Added all text functionality so the test application runs successfully.
parent 5f65eb66
SOURCES_dynamicoverlay = dynamicoverlay.c dynamicoverlay_buffer.c dynamicoverlay_queue.c
noinst_HEADERS = dynamicoverlay.h dynamicoverlay_commands.h
SOURCES_dynamicoverlay = dynamicoverlay_buffer.c dynamicoverlay_queue.c dynamicoverlay_list.c dynamicoverlay_commands.c dynamicoverlay.c
noinst_HEADERS = dynamicoverlay.h
......@@ -28,14 +28,15 @@
# include "config.h"
#endif
#include <fcntl.h>
#include <vlc/vlc.h>
#include <vlc_sout.h>
#include <vlc_vout.h>
#include <vlc_filter.h>
#include <vlc_osd.h>
#include <ctype.h>
#include <fcntl.h>
#include "dynamicoverlay.h"
/*****************************************************************************
......@@ -79,282 +80,6 @@ static const char *ppsz_filter_options[] = {
"input", "output", NULL
};
/*****************************************************************************
* overlay_t: Overlay descriptor
*****************************************************************************/
struct overlay_t
{
int i_x, i_y;
int i_alpha;
vlc_bool_t b_active;
video_format_t format;
union {
picture_t *p_pic;
char *p_text;
} data;
};
typedef struct overlay_t overlay_t;
static overlay_t *OverlayCreate( void )
{
overlay_t *p_ovl = malloc( sizeof( overlay_t ) );
if( p_ovl == NULL )
return NULL;
memset( p_ovl, 0, sizeof( overlay_t ) );
p_ovl->i_x = p_ovl->i_y = 0;
p_ovl->i_alpha = 0xFF;
p_ovl->b_active = VLC_FALSE;
vout_InitFormat( &p_ovl->format, VLC_FOURCC( '\0','\0','\0','\0') , 0, 0,
VOUT_ASPECT_FACTOR );
p_ovl->data.p_text = NULL;
return p_ovl;
}
static int OverlayDestroy( overlay_t *p_ovl )
{
if( p_ovl->data.p_text != NULL )
free( p_ovl->data.p_text );
return VLC_SUCCESS;
}
/*****************************************************************************
* list_t: Command queue
*****************************************************************************/
struct list_t
{
overlay_t **pp_head, **pp_tail;
};
typedef struct list_t list_t;
static int ListInit( list_t *p_list )
{
p_list->pp_head = malloc( 16 * sizeof( overlay_t * ) );
if( p_list->pp_head == NULL )
return VLC_ENOMEM;
p_list->pp_tail = p_list->pp_head + 16;
memset( p_list->pp_head, 0, 16 * sizeof( overlay_t * ) );
return VLC_SUCCESS;
}
static int ListDestroy( list_t *p_list )
{
for( overlay_t **pp_cur = p_list->pp_head;
pp_cur < p_list->pp_tail;
++pp_cur )
{
if( *pp_cur != NULL )
{
OverlayDestroy( *pp_cur );
free( *pp_cur );
}
}
free( p_list->pp_head );
return VLC_SUCCESS;
}
static ssize_t ListAdd( list_t *p_list, overlay_t *p_new )
{
/* Find an available slot */
for( overlay_t **pp_cur = p_list->pp_head;
pp_cur < p_list->pp_tail;
++pp_cur )
{
if( *pp_cur == NULL )
{
*pp_cur = p_new;
return pp_cur - p_list->pp_head;
}
}
/* Have to expand */
size_t i_size = p_list->pp_tail - p_list->pp_head;
size_t i_newsize = i_size * 2;
p_list->pp_head = realloc( p_list->pp_head,
i_newsize * sizeof( overlay_t * ) );
if( p_list->pp_head == NULL )
return VLC_ENOMEM;
p_list->pp_tail = p_list->pp_head + i_newsize;
memset( p_list->pp_head + i_size, 0, i_size * sizeof( overlay_t * ) );
p_list->pp_head[i_size] = p_new;
return i_size;
}
static int ListRemove( list_t *p_list, size_t i_idx )
{
int ret;
if( ( i_idx >= (size_t)( p_list->pp_tail - p_list->pp_head ) ) ||
( p_list->pp_head[i_idx] == NULL ) )
{
return VLC_EGENERIC;
}
ret = OverlayDestroy( p_list->pp_head[i_idx] );
free( p_list->pp_head[i_idx] );
p_list->pp_head[i_idx] = NULL;
return ret;
}
static overlay_t *ListGet( list_t *p_list, size_t i_idx )
{
if( ( i_idx >= (size_t)( p_list->pp_tail - p_list->pp_head ) ) ||
( p_list->pp_head[i_idx] == NULL ) )
{
return NULL;
}
return p_list->pp_head[i_idx];
}
static overlay_t *ListWalk( list_t *p_list )
{
static overlay_t **pp_cur = NULL;
if( pp_cur == NULL )
pp_cur = p_list->pp_head;
else
pp_cur = pp_cur + 1;
for( ; pp_cur < p_list->pp_tail; ++pp_cur )
{
if( ( *pp_cur != NULL ) &&
( (*pp_cur)->b_active == VLC_TRUE )&&
( (*pp_cur)->format.i_chroma != VLC_FOURCC( '\0','\0','\0','\0') ) )
{
return *pp_cur;
}
}
pp_cur = NULL;
return NULL;
}
/*****************************************************************************
* filter_sys_t: adjust filter method descriptor
*****************************************************************************/
struct filter_sys_t
{
buffer_t input, output;
int i_inputfd, i_outputfd;
char *psz_inputfile, *psz_outputfile;
vlc_bool_t b_updated, b_atomic;
queue_t atomic, pending, processed;
list_t overlays;
};
/*****************************************************************************
* Command functions
*****************************************************************************/
#define SKIP \
{ \
const char *psz_temp = psz_command; \
while( isspace( *psz_temp ) ) { \
++psz_temp; \
} \
if( psz_temp == psz_command ) { \
return VLC_EGENERIC; \
} \
psz_command = psz_temp; \
}
#define INT( name ) \
SKIP \
{ \
char *psz_temp; \
p_myparams->name = strtol( psz_command, &psz_temp, 10 ); \
if( psz_temp == psz_command ) \
{ \
return VLC_EGENERIC; \
} \
psz_command = psz_temp; \
}
#define CHARS( name, count ) \
SKIP \
{ \
if( psz_end - psz_command < count ) \
{ \
return VLC_EGENERIC; \
} \
memcpy( p_myparams->name, psz_command, count ); \
psz_command += count; \
}
#define COMMAND( name, param, ret, atomic, code ) \
static int Command##name##Parse( const char *psz_command, \
const char *psz_end, \
commandparams_t *p_params ) \
{ \
struct commandparams##name##_t *p_myparams = &p_params->name; \
param \
return VLC_SUCCESS; \
}
#include "dynamicoverlay_commands.h"
#undef COMMAND
#undef SKIP
#undef INT
#undef CHARS
#define COMMAND( name, param, ret, atomic, code ) \
static int Command##name##Exec( filter_t *p_filter, \
const commandparams_t *p_gparams, \
commandresults_t *p_gresults, \
filter_sys_t *p_sys ) \
{ \
const struct commandparams##name##_t *p_params = &p_gparams->name; \
struct commandresults##name##_t *p_results = &p_gresults->name; \
code \
}
#include "dynamicoverlay_commands.h"
#undef COMMAND
#define INT( name ) \
{ \
int ret = BufferPrintf( p_output, " %d", p_myresults->name ); \
if( ret != VLC_SUCCESS ) { \
return ret; \
} \
}
#define CHARS( name, count ) \
{ \
int ret = BufferAdd( p_output, p_myresults->name, count ); \
if( ret != VLC_SUCCESS ) { \
return ret; \
} \
}
#define COMMAND( name, param, ret, atomic, code ) \
static int Command##name##Unparse( const commandresults_t *p_results, \
buffer_t *p_output ) \
{ \
const struct commandresults##name##_t *p_myresults = &p_results->name; \
ret \
return VLC_SUCCESS; \
}
#include "dynamicoverlay_commands.h"
#undef COMMAND
#undef INT
#undef CHARS
static commanddesc_t p_commands[] =
{
#define COMMAND( name, param, ret, atomic, code ) \
{ #name, atomic, Command##name##Parse, Command##name##Exec, Command##name##Unparse },
#include "dynamicoverlay_commands.h"
#undef COMMAND
};
#define NUMCOMMANDS (sizeof(p_commands)/sizeof(commanddesc_t))
/*****************************************************************************
* Create: allocates adjust video thread output method
*****************************************************************************
......@@ -399,10 +124,7 @@ static int Create( vlc_object_t *p_this )
var_AddCallback( p_filter, "overlay-input", AdjustCallback, p_sys );
var_AddCallback( p_filter, "overlay-output", AdjustCallback, p_sys );
msg_Dbg( p_filter, "%d commands are available:", NUMCOMMANDS );
for( size_t i_index = 0; i_index < NUMCOMMANDS; ++i_index )
msg_Dbg( p_filter, " %s", p_commands[i_index].psz_command );
RegisterCommand( p_filter );
return VLC_SUCCESS;
}
......@@ -421,6 +143,7 @@ static void Destroy( vlc_object_t *p_this )
QueueDestroy( &p_filter->p_sys->pending );
QueueDestroy( &p_filter->p_sys->processed );
ListDestroy( &p_filter->p_sys->overlays );
UnregisterCommand( p_filter );
free( p_filter->p_sys->psz_inputfile );
free( p_filter->p_sys->psz_outputfile );
......@@ -502,74 +225,51 @@ static subpicture_t *Filter( filter_t *p_filter, mtime_t date )
/* Parse any complete commands */
char *p_end, *p_cmd;
while( ( p_end = memchr( p_sys->input.p_begin, '\n',
p_sys->input.i_length ) ) )
p_sys->input.i_length ) ) )
{
commanddesc_t *p_cur = NULL;
vlc_bool_t b_found = VLC_FALSE;
size_t i_index = 0;
*p_end = '\0';
p_cmd = p_sys->input.p_begin;
p_cmd = BufferGetToken( &p_sys->input );
commanddesc_t *p_lower = p_commands;
commanddesc_t *p_upper = p_commands + NUMCOMMANDS;
size_t i_index = 0;
while( 1 )
msg_Info( p_filter, "Search command: %s", p_cmd );
for( i_index = 0; i_index < p_sys->i_commands; i_index++ )
{
if( ( p_cmd[i_index] == '\0' ) ||
isspace( p_cmd[i_index] ) )
p_cur = p_sys->pp_commands[i_index];
if( !strncmp( p_cur->psz_command, p_cmd, strlen(p_cur->psz_command) ) )
{
p_cmd[strlen(p_cur->psz_command)] = '\0';
b_found = VLC_TRUE;
break;
}
commanddesc_t *p_cur = p_lower;
while( ( p_cur < p_upper ) &&
( p_cur->psz_command[i_index] != p_cmd[i_index] ) )
{
++p_cur;
}
p_lower = p_cur;
while( ( p_cur < p_upper ) &&
( p_cur->psz_command[i_index] == p_cmd[i_index] ) )
{
++p_cur;
}
p_upper = p_cur;
++i_index;
}
if( p_lower >= p_upper )
if( !b_found )
{
/* No matching command */
p_cmd[i_index] = '\0';
msg_Err( p_filter, "Got invalid command: %s", p_cmd );
BufferPrintf( &p_sys->output, "FAILURE: %d Invalid Command\n", VLC_EGENERIC );
}
else if ( p_lower + 1 < p_upper )
{
/* Command is not a unique prefix of a command */
p_cmd[i_index] = '\0';
msg_Err( p_filter, "Got ambiguous command: %s", p_cmd );
msg_Err( p_filter, "Possible completions are:" );
for( ; p_lower < p_upper; ++p_lower )
{
msg_Err( p_filter, " %s", p_lower->psz_command );
}
BufferPrintf( &p_sys->output, "FAILURE: %d Invalid Command\n", VLC_EGENERIC );
}
else
{
/* Command is valid */
command_t *p_command = malloc( sizeof( command_t ) );
if( !p_command )
msg_Info( p_filter, "Got valid command: %s", p_cmd );
command_t *p_cmddesc = malloc( sizeof( command_t ) );
if( !p_cmddesc )
return NULL;
p_command->p_command = p_lower;
p_command->p_command->pf_parser( p_cmd + i_index, p_end,
&p_command->params );
p_cmd = p_cmd + strlen(p_cur->psz_command) +1;
p_cmddesc->p_command = p_cur;
p_cmddesc->p_command->pf_parser( p_cmd, p_end,
&p_cmddesc->params );
if( ( p_command->p_command->b_atomic == VLC_TRUE ) &&
if( ( p_cmddesc->p_command->b_atomic == VLC_TRUE ) &&
( p_sys->b_atomic == VLC_TRUE ) )
QueueEnqueue( &p_sys->atomic, p_command );
QueueEnqueue( &p_sys->atomic, p_cmddesc );
else
QueueEnqueue( &p_sys->pending, p_command );
p_cmd[i_index] = '\0';
msg_Dbg( p_filter, "Got valid command: %s", p_cmd );
QueueEnqueue( &p_sys->pending, p_cmddesc );
}
BufferDel( &p_sys->input, p_end - p_sys->input.p_begin + 1 );
......@@ -581,7 +281,7 @@ static subpicture_t *Filter( filter_t *p_filter, mtime_t date )
{
p_command->i_status =
p_command->p_command->pf_execute( p_filter, &p_command->params,
&p_command->results, p_sys );
&p_command->results );
QueueEnqueue( &p_sys->processed, p_command );
}
......@@ -651,18 +351,25 @@ static subpicture_t *Filter( filter_t *p_filter, mtime_t date )
while( (p_overlay = ListWalk( &p_sys->overlays )) )
{
msg_Dbg( p_filter, "Displaying overlay: %4.4s, %d, %d, %d",
&p_overlay->format.i_chroma, p_overlay->i_x, p_overlay->i_y,
(char*)&p_overlay->format.i_chroma, p_overlay->i_x, p_overlay->i_y,
p_overlay->i_alpha );
if( p_overlay->format.i_chroma == VLC_FOURCC('T','E','X','T') )
{
*pp_region = p_spu->pf_create_region( p_filter,
*pp_region = p_spu->pf_create_region( VLC_OBJECT(p_filter),
&p_overlay->format );
if( !*pp_region )
break;
(*pp_region)->psz_text = strdup( p_overlay->data.p_text );
(*pp_region)->p_style = malloc( sizeof(struct text_style_t) );
if( !(*pp_region)->p_style )
{
msg_Err( p_filter, "cannot allocate subpicture region" );
continue;
p_spu->pf_destroy_region( VLC_OBJECT(p_filter), (*pp_region) );
*pp_region = NULL;
break;
}
(*pp_region)->psz_text = strdup( p_overlay->data.p_text );
memcpy( (*pp_region)->p_style, &p_overlay->fontstyle, sizeof(text_style_t) );
}
else
{
......@@ -677,7 +384,8 @@ static subpicture_t *Filter( filter_t *p_filter, mtime_t date )
continue;
}
vout_CopyPicture( p_filter, &clone, p_overlay->data.p_pic );
*pp_region = p_spu->pf_make_region( p_filter, &p_overlay->format,
*pp_region = p_spu->pf_make_region( VLC_OBJECT(p_filter),
&p_overlay->format,
&clone );
if( !*pp_region )
{
......@@ -701,6 +409,12 @@ static int AdjustCallback( vlc_object_t *p_this, char const *psz_var,
void *p_data )
{
filter_sys_t *p_sys = (filter_sys_t *)p_data;
VLC_UNUSED(p_this); VLC_UNUSED(psz_var); VLC_UNUSED(oldval); VLC_UNUSED(newval);
VLC_UNUSED(p_this); VLC_UNUSED(oldval);
if( !strncmp( psz_var, "overlay-input", 13 ) )
p_sys->psz_inputfile = newval.psz_string;
else if( !strncmp( psz_var, "overlay-output", 14 ) )
p_sys->psz_outputfile = newval.psz_string;
return VLC_EGENERIC;
}
......@@ -24,6 +24,9 @@
#ifndef DYNAMIC_OVERLAY_H
#define DYNAMIC_OVERLAY_H 1
#include <vlc/vlc.h>
#include <vlc_filter.h>
/*****************************************************************************
* buffer_t: Command and response buffer
*****************************************************************************/
......@@ -42,61 +45,42 @@ int BufferDestroy( buffer_t *p_buffer );
int BufferAdd( buffer_t *p_buffer, const char *p_data, size_t i_len );
int BufferPrintf( buffer_t *p_buffer, const char *p_fmt, ... );
int BufferDel( buffer_t *p_buffer, int i_len );
char *BufferGetToken( buffer_t *p_buffer );
/*****************************************************************************
* Command structures
*****************************************************************************/
#define INT( name ) int name;
#define CHARS( name, count ) char name[count];
#define COMMAND( name, param, ret, atomic, code ) \
struct commandparams##name##_t \
{ \
param \
};
#include "dynamicoverlay_commands.h"
#undef COMMAND
#undef INT
#undef CHARS
union commandparams_t
/** struct commandparams_t - command params structure */
typedef struct commandparams_t
{
#define COMMAND( name, param, ret, atomic, code ) struct commandparams##name##_t name;
#include "dynamicoverlay_commands.h"
#undef COMMAND
};
typedef union commandparams_t commandparams_t;
#define INT( name ) int name;
#define CHARS( name, count ) char name[count];
#define COMMAND( name, param, ret, atomic, code ) \
struct commandresults##name##_t \
{ \
ret \
};
#include "dynamicoverlay_commands.h"
#undef COMMAND
#undef INT
#undef CHARS
union commandresults_t {
#define COMMAND( name, param, ret, atomic, code ) struct commandresults##name##_t name;
#include "dynamicoverlay_commands.h"
#undef COMMAND
};
typedef union commandresults_t commandresults_t;
int32_t i_id; /*< overlay id */
int32_t i_shmid; /*< shared memory identifier */
vlc_fourcc_t fourcc;/*< chroma */
int32_t i_x; /*< x position of overlay */
int32_t i_y; /*< y position of overlay */
int32_t i_width; /*< width of overlay */
int32_t i_height; /*< height of overlay */
int32_t i_alpha; /*< alpha value of overlay */
struct text_style_t fontstyle; /*< text style */
vlc_bool_t b_visible; /*< visibility flag of overlay */
} commandparams_t;
typedef struct commanddesc_t
{
const char *psz_command;
vlc_bool_t b_atomic;
int ( *pf_parser ) ( const char *psz_command, const char *psz_end,
int ( *pf_parser ) ( char *psz_command, char *psz_end,
commandparams_t *p_params );
int ( *pf_execute ) ( filter_t *p_filter, const commandparams_t *p_params,
commandresults_t *p_results,
struct filter_sys_t *p_sys );
int ( *pf_unparser ) ( const commandresults_t *p_results,
buffer_t *p_output );
commandparams_t *p_results );
int ( *pf_unparse ) ( const commandparams_t *p_results,
buffer_t *p_output );
} commanddesc_t;
typedef struct command_t
......@@ -104,11 +88,13 @@ typedef struct command_t
struct commanddesc_t *p_command;
int i_status;
commandparams_t params;
commandresults_t results;
commandparams_t results;
struct command_t *p_next;
} command_t;
void RegisterCommand( filter_t *p_filter );
void UnregisterCommand( filter_t *p_filter );
/*****************************************************************************
* queue_t: Command queue
*****************************************************************************/
......@@ -125,4 +111,60 @@ int QueueEnqueue( queue_t *p_queue, command_t *p_cmd );
command_t *QueueDequeue( queue_t *p_queue );
int QueueTransfer( queue_t *p_sink, queue_t *p_source );
/*****************************************************************************
* overlay_t: Overlay descriptor
*****************************************************************************/
typedef struct overlay_t
{
int i_x, i_y;
int i_alpha;
vlc_bool_t b_active;
video_format_t format;
struct text_style_t fontstyle;
union {
picture_t *p_pic;
char *p_text;
} data;
} overlay_t;
overlay_t *OverlayCreate( void );
int OverlayDestroy( overlay_t *p_ovl );
/*****************************************************************************
* list_t: Command queue
*****************************************************************************/
typedef struct list_t
{
overlay_t **pp_head, **pp_tail;
} list_t;
int ListInit( list_t *p_list );
int ListDestroy( list_t *p_list );
ssize_t ListAdd( list_t *p_list, overlay_t *p_new );
int ListRemove( list_t *p_list, size_t i_idx );
overlay_t *ListGet( list_t *p_list, size_t i_idx );
overlay_t *ListWalk( list_t *p_list );
/*****************************************************************************
* filter_sys_t: adjust filter method descriptor
*****************************************************************************/
struct filter_sys_t
{
buffer_t input, output;
int i_inputfd, i_outputfd;
char *psz_inputfile, *psz_outputfile;
commanddesc_t **pp_commands; /* array of commands */
size_t i_commands;
vlc_bool_t b_updated, b_atomic;
queue_t atomic, pending, processed;
list_t overlays;
};
#endif
/*****************************************************************************
* dynamicoverlay_commands.def : dynamic overlay plugin commands
* dynamicoverlay_buffer.h : dynamic overlay buffer
*****************************************************************************
* Copyright (C) 2008 the VideoLAN team
* $Id$
......@@ -27,6 +27,10 @@
#endif
#include <vlc/vlc.h>
#include <vlc_osd.h>
#include <vlc_filter.h>
#include <ctype.h>
#include "dynamicoverlay.h"
......@@ -55,6 +59,20 @@ int BufferDestroy( buffer_t *p_buffer )
return VLC_SUCCESS;
}
char *BufferGetToken( buffer_t *p_buffer )
{
char *p_char = p_buffer->p_begin;
while( isspace( p_char[0] ) || p_char[0] == '\0' )
{
if( p_char <= (p_buffer->p_begin + p_buffer->i_length) )
p_char++;
else
return NULL;
}
return p_char;
}
int BufferAdd( buffer_t *p_buffer, const char *p_data, size_t i_len )
{
if( ( p_buffer->i_size - p_buffer->i_length -
......
/*****************************************************************************
* dynamicoverlay_commands.c : dynamic overlay plugin commands
*****************************************************************************
* Copyright (C) 2008 the VideoLAN team
* $Id$
*
* Author: Søren Bøg <avacore@videolan.org>
* Jean-Paul Saman <jpsaman@videolan.org>
*
* This program 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.
*
* This program 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <vlc/vlc.h>
#include <vlc_arrays.h>
#include <vlc_vout.h>
#include <vlc_filter.h>
#include <vlc_osd.h>
#include <string.h>
#include <ctype.h>
#include <sys/shm.h>
#include "dynamicoverlay.h"
/*****************************************************************************
* overlay_t: Overlay descriptor
*****************************************************************************/
overlay_t *OverlayCreate( void )
{
overlay_t *p_ovl = malloc( sizeof( overlay_t ) );
if( p_ovl == NULL )
return NULL;
memset( p_ovl, 0, sizeof( overlay_t ) );
p_ovl->i_x = p_ovl->i_y = 0;
p_ovl->i_alpha = 0xFF;
p_ovl->b_active = VLC_FALSE;
vout_InitFormat( &p_ovl->format, VLC_FOURCC( '\0','\0','\0','\0') , 0, 0,
VOUT_ASPECT_FACTOR );
memcpy( &p_ovl->fontstyle, &default_text_style, sizeof(struct text_style_t) );
p_ovl->data.p_text = NULL;
return p_ovl;
}
int OverlayDestroy( overlay_t *p_ovl )
{
if( p_ovl->data.p_text != NULL )
free( p_ovl->data.p_text );
return VLC_SUCCESS;
}
/*****************************************************************************
* Command parsers
*****************************************************************************/
static int skip_space( char **psz_command )
{
char *psz_temp = *psz_command;
while( isspace( *psz_temp ) )
{
++psz_temp;
}
if( psz_temp == *psz_command )
{
return VLC_EGENERIC;
}
*psz_command = psz_temp;
return VLC_SUCCESS;
}
static int parse_digit( char **psz_command, int32_t *value )
{
char *psz_temp;
*value = strtol( *psz_command, &psz_temp, 10 );
if( psz_temp == *psz_command )
{
return VLC_EGENERIC;
}
*psz_command = psz_temp;
return VLC_SUCCESS;
}
static int parse_char( char **psz_command, char **psz_end,
int count, char *psz_value )
{
if( *psz_end - *psz_command < count )
{
return VLC_EGENERIC;
}
memcpy( psz_value, *psz_command, count );
*psz_command += count;
return VLC_SUCCESS;
}
static int parser_DataSharedMem( char *psz_command,
char *psz_end,
commandparams_t *p_params )
{
/* Parse: 0 128 128 RGBA 9404459 */
skip_space( &psz_command );
if( isdigit( *psz_command ) )
{
if( parse_digit( &psz_command, &p_params->i_id ) == VLC_EGENERIC )
return VLC_EGENERIC;
}
skip_space( &psz_command );
if( isdigit( *psz_command ) )
{
if( parse_digit( &psz_command, &p_params->i_width ) == VLC_EGENERIC )
return VLC_EGENERIC;
}
skip_space( &psz_command );
if( isdigit( *psz_command ) )
{
if( parse_digit( &psz_command, &p_params->i_height ) == VLC_EGENERIC )
return VLC_EGENERIC;
}
skip_space( &psz_command );
if( isascii( *psz_command ) )
{
if( parse_char( &psz_command, &psz_end, 4, (char*)&p_params->fourcc )
== VLC_EGENERIC )
return VLC_EGENERIC;
}
skip_space( &psz_command );
if( isdigit( *psz_command ) )
{
if( parse_digit( &psz_command, &p_params->i_shmid ) == VLC_EGENERIC )
return VLC_EGENERIC;
}
return VLC_SUCCESS;
}
static int parser_Id( char *psz_command, char *psz_end,
commandparams_t *p_params )
{
(void)(psz_end);
skip_space( &psz_command );
if( isdigit( *psz_command ) )
{
if( parse_digit( &psz_command, &p_params->i_id ) == VLC_EGENERIC )
return VLC_EGENERIC;
}
return VLC_SUCCESS;
}
static int parser_None( char *psz_command, char *psz_end,
commandparams_t *p_params )
{
(void)(psz_command);
(void)(psz_end);
(void)(p_params);
return VLC_SUCCESS;
}
static int parser_SetAlpha( char *psz_command, char *psz_end,
commandparams_t *p_params )
{
(void)(psz_end);
skip_space( &psz_command );
if( isdigit( *psz_command ) )
{
if( parse_digit( &psz_command, &p_params->i_id ) == VLC_EGENERIC )
return VLC_EGENERIC;
}
skip_space( &psz_command );
if( isdigit( *psz_command ) )
{
if( parse_digit( &psz_command, &p_params->i_alpha ) == VLC_EGENERIC )
return VLC_EGENERIC;
}
return VLC_SUCCESS;
}
static int parser_SetPosition( char *psz_command, char *psz_end,
commandparams_t *p_params )
{
(void)(psz_end);
skip_space( &psz_command );
if( isdigit( *psz_command ) )
{
if( parse_digit( &psz_command, &p_params->i_id ) == VLC_EGENERIC )
return VLC_EGENERIC;
}
skip_space( &psz_command );
if( isdigit( *psz_command ) )
{
if( parse_digit( &psz_command, &p_params->i_x ) == VLC_EGENERIC )
return VLC_EGENERIC;
}
skip_space( &psz_command );
if( isdigit( *psz_command ) )
{
if( parse_digit( &psz_command, &p_params->i_y ) == VLC_EGENERIC )
return VLC_EGENERIC;
}
return VLC_SUCCESS;
}
static int parser_SetTextAlpha( char *psz_command, char *psz_end,
commandparams_t *p_params )
{
(void)(psz_end);
skip_space( &psz_command );
if( isdigit( *psz_command ) )
{
if( parse_digit( &psz_command, &p_params->i_id ) == VLC_EGENERIC )
return VLC_EGENERIC;
}
skip_space( &psz_command );
if( isdigit( *psz_command ) )
{
if( parse_digit( &psz_command, &p_params->fontstyle.i_font_alpha ) == VLC_EGENERIC )
return VLC_EGENERIC;
}
return VLC_SUCCESS;
}
static int parser_SetTextColor( char *psz_command, char *psz_end,
commandparams_t *p_params )
{
int r, g, b;
(void)(psz_end);
skip_space( &psz_command );
if( isdigit( *psz_command ) )
{
if( parse_digit( &psz_command, &p_params->i_id ) == VLC_EGENERIC )
return VLC_EGENERIC;
}
skip_space( &psz_command );
if( isdigit( *psz_command ) )
{
if( parse_digit( &psz_command, &r ) == VLC_EGENERIC )
return VLC_EGENERIC;
}
skip_space( &psz_command );
if( isdigit( *psz_command ) )
{
if( parse_digit( &psz_command, &g ) == VLC_EGENERIC )
return VLC_EGENERIC;
}
skip_space( &psz_command );
if( isdigit( *psz_command ) )
{
if( parse_digit( &psz_command, &b ) == VLC_EGENERIC )
return VLC_EGENERIC;
}
p_params->fontstyle.i_font_color = (r<<24) | (g<<16) | (b<<8);
return VLC_SUCCESS;
}
static int parser_SetTextSize( char *psz_command, char *psz_end,
commandparams_t *p_params )
{
(void)(psz_end);
skip_space( &psz_command );
if( isdigit( *psz_command ) )
{
if( parse_digit( &psz_command, &p_params->i_id ) == VLC_EGENERIC )
return VLC_EGENERIC;
}
skip_space( &psz_command );
if( isdigit( *psz_command ) )
{
if( parse_digit( &psz_command, &p_params->fontstyle.i_font_size ) == VLC_EGENERIC )
return VLC_EGENERIC;
}
return VLC_SUCCESS;
}
static int parser_SetVisibility( char *psz_command, char *psz_end,
commandparams_t *p_params )
{
(void)(psz_end);
skip_space( &psz_command );
if( isdigit( *psz_command ) )
{
if( parse_digit( &psz_command, &p_params->i_id ) == VLC_EGENERIC )
return VLC_EGENERIC;
}
skip_space( &psz_command );
if( isdigit( *psz_command ) )
{
int32_t i_vis = 0;
if( parse_digit( &psz_command, &i_vis ) == VLC_EGENERIC )
return VLC_EGENERIC;
p_params->b_visible = (i_vis == 1) ? VLC_TRUE : VLC_FALSE;
}
return VLC_SUCCESS;
}
/*****************************************************************************
* Command unparser functions
*****************************************************************************/
static int unparse_default( const commandparams_t *p_results,
buffer_t *p_output )
{
(void)(p_results);
VLC_UNUSED(p_output);
return VLC_SUCCESS;
}
static int unparse_GenImage( const commandparams_t *p_results,
buffer_t *p_output )
{
int ret = BufferPrintf( p_output, " %d", p_results->i_id );
if( ret != VLC_SUCCESS )
return ret;
return VLC_SUCCESS;
}
static int unparse_GetAlpha( const commandparams_t *p_results,
buffer_t *p_output )
{
int ret = BufferPrintf( p_output, " %d", p_results->i_alpha );
if( ret != VLC_SUCCESS )
return ret;
return VLC_SUCCESS;
}
static int unparse_GetPosition( const commandparams_t *p_results,
buffer_t *p_output )
{
int ret = BufferPrintf( p_output, " %d", p_results->i_x );
if( ret != VLC_SUCCESS )
return ret;
ret = BufferPrintf( p_output, " %d", p_results->i_y );
if( ret != VLC_SUCCESS )
return ret;
return VLC_SUCCESS;
}
static int unparse_GetTextAlpha( const commandparams_t *p_results,
buffer_t *p_output )
{
int ret = BufferPrintf( p_output, " %d", p_results->fontstyle.i_font_alpha );
if( ret != VLC_SUCCESS )
return ret;
return VLC_SUCCESS;
}
static int unparse_GetTextColor( const commandparams_t *p_results,
buffer_t *p_output )
{
int ret = BufferPrintf( p_output, " %d", (p_results->fontstyle.i_font_color & 0xff0000)>>24 );
if( ret != VLC_SUCCESS )
return ret;
ret = BufferPrintf( p_output, " %d", (p_results->fontstyle.i_font_color & 0x00ff00)>>16 );
if( ret != VLC_SUCCESS )
return ret;
ret = BufferPrintf( p_output, " %d", (p_results->fontstyle.i_font_color & 0x0000ff)>>8 );
if( ret != VLC_SUCCESS )
return ret;
return VLC_SUCCESS;
}
static int unparse_GetTextSize( const commandparams_t *p_results,
buffer_t *p_output )
{
int ret = BufferPrintf( p_output, " %d", p_results->fontstyle.i_font_size );
if( ret != VLC_SUCCESS )
return ret;
return VLC_SUCCESS;
}
static int unparse_GetVisibility( const commandparams_t *p_results,
buffer_t *p_output )
{
int ret = BufferPrintf( p_output, " %d", (p_results->b_visible ? 1 : 0) );
if( ret != VLC_SUCCESS ) {
return ret;
}
return VLC_SUCCESS;
}
/*****************************************************************************
* Command functions
*****************************************************************************/
static int exec_DataSharedMem( filter_t *p_filter,
const commandparams_t *p_params,
commandparams_t *p_results )
{
filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
struct shmid_ds shminfo;
overlay_t *p_ovl;
size_t i_size;
(void)(p_results);
p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
if( p_ovl == NULL )
{
msg_Err( p_filter, "Invalid overlay: %d", p_params->i_id );
return VLC_EGENERIC;
}
if( shmctl( p_params->i_shmid, IPC_STAT, &shminfo ) == -1 )
{
msg_Err( p_filter, "Unable to access shared memory" );
return VLC_EGENERIC;
}
i_size = shminfo.shm_segsz;
if( p_params->fourcc == VLC_FOURCC('T','E','X','T') )
{
char *p_data;
if( (p_params->i_height != 1) || (p_params->i_width < 1) )
{
msg_Err( p_filter,
"Invalid width and/or height. when specifing text height "
"must be 1 and width the number of bytes in the string, "
"including the null terminator" );
return VLC_EGENERIC;
}
if( (size_t)p_params->i_width > i_size )
{
msg_Err( p_filter,
"Insufficient data in shared memory. need %d, got %d",
p_params->i_width, i_size );
return VLC_EGENERIC;
}
p_ovl->data.p_text = malloc( p_params->i_width );
if( p_ovl->data.p_text == NULL )
{
msg_Err( p_filter, "Unable to allocate string storage" );
return VLC_ENOMEM;
}
vout_InitFormat( &p_ovl->format, VLC_FOURCC('T','E','X','T'),
0, 0, 0 );
p_data = shmat( p_params->i_shmid, NULL, SHM_RDONLY );
if( p_data == NULL )
{
msg_Err( p_filter, "Unable to attach to shared memory" );
free( p_ovl->data.p_text );
p_ovl->data.p_text = NULL;
return VLC_ENOMEM;
}
memcpy( p_ovl->data.p_text, p_data, p_params->i_width );
shmdt( p_data );
}
else
{
uint8_t *p_data, *p_in;
size_t i_neededsize = 0;
p_ovl->data.p_pic = malloc( sizeof( picture_t ) );
if( p_ovl->data.p_pic == NULL )
{
msg_Err( p_filter, "Unable to allocate picture structure" );
return VLC_ENOMEM;
}
vout_InitFormat( &p_ovl->format, p_params->fourcc,
p_params->i_width, p_params->i_height,
VOUT_ASPECT_FACTOR );
if( vout_AllocatePicture( p_filter, p_ovl->data.p_pic,
p_ovl->format.i_chroma, p_params->i_width,
p_params->i_height, p_ovl->format.i_aspect ) )
{
msg_Err( p_filter, "Unable to allocate picture" );
free( p_ovl->data.p_pic );
p_ovl->data.p_pic = NULL;
return VLC_ENOMEM;
}
for( size_t i_plane = 0; i_plane < (size_t)p_ovl->data.p_pic->i_planes;
++i_plane )
{
i_neededsize += p_ovl->data.p_pic->p[i_plane].i_visible_lines *
p_ovl->data.p_pic->p[i_plane].i_visible_pitch;
}
if( i_neededsize > i_size )
{
msg_Err( p_filter,
"Insufficient data in shared memory. need %d, got %d",
i_neededsize, i_size );
p_ovl->data.p_pic->pf_release( p_ovl->data.p_pic );
free( p_ovl->data.p_pic );
p_ovl->data.p_pic = NULL;
return VLC_EGENERIC;
}
p_data = shmat( p_params->i_shmid, NULL, SHM_RDONLY );
if( p_data == NULL )
{
msg_Err( p_filter, "Unable to attach to shared memory" );
p_ovl->data.p_pic->pf_release( p_ovl->data.p_pic );
free( p_ovl->data.p_pic );
p_ovl->data.p_pic = NULL;
return VLC_ENOMEM;
}
p_in = p_data;
for( size_t i_plane = 0; i_plane < (size_t)p_ovl->data.p_pic->i_planes;
++i_plane )
{
uint8_t *p_out = p_ovl->data.p_pic->p[i_plane].p_pixels;
for( size_t i_line = 0;
i_line < (size_t)p_ovl->data.p_pic->p[i_plane].i_visible_lines;
++i_line )
{
p_filter->p_libvlc->pf_memcpy( p_out, p_in,
p_ovl->data.p_pic->p[i_plane].i_visible_pitch );
p_out += p_ovl->data.p_pic->p[i_plane].i_pitch;
p_in += p_ovl->data.p_pic->p[i_plane].i_visible_pitch;
}
}
shmdt( p_data );
}
p_sys->b_updated = p_ovl->b_active;
return VLC_SUCCESS;
}
static int exec_DeleteImage( filter_t *p_filter,
const commandparams_t *p_params,
commandparams_t *p_results )
{
(void)(p_results);
filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
p_sys->b_updated = VLC_TRUE;
return ListRemove( &p_sys->overlays, p_params->i_id );
}
static int exec_EndAtomic( filter_t *p_filter,
const commandparams_t *p_params,
commandparams_t *p_results )
{
(void)(p_params);
(void)(p_results);
filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
QueueTransfer( &p_sys->pending, &p_sys->atomic );
p_sys->b_atomic = VLC_FALSE;
return VLC_SUCCESS;
}
static int exec_GenImage( filter_t *p_filter,
const commandparams_t *p_params,
commandparams_t *p_results )
{
(void)(p_params);
filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
overlay_t *p_ovl = OverlayCreate();
if( p_ovl == NULL )
return VLC_ENOMEM;
ssize_t i_idx = ListAdd( &p_sys->overlays, p_ovl );
if( i_idx < 0 )
return i_idx;
p_results->i_id = i_idx;
return VLC_SUCCESS;
}
static int exec_GetAlpha( filter_t *p_filter,
const commandparams_t *p_params,
commandparams_t *p_results )
{
filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
overlay_t *p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
if( p_ovl == NULL )
return VLC_EGENERIC;
p_results->i_alpha = p_ovl->i_alpha;
return VLC_SUCCESS;
}
static int exec_GetPosition( filter_t *p_filter,
const commandparams_t *p_params,
commandparams_t *p_results )
{
filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
overlay_t *p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
if( p_ovl == NULL )
return VLC_EGENERIC;
p_results->i_x = p_ovl->i_x;
p_results->i_y = p_ovl->i_y;
return VLC_SUCCESS;
}
static int exec_GetTextAlpha( filter_t *p_filter,
const commandparams_t *p_params,
commandparams_t *p_results )
{
filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
overlay_t *p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
if( p_ovl == NULL )
return VLC_EGENERIC;
p_results->fontstyle.i_font_alpha = p_ovl->fontstyle.i_font_alpha;
return VLC_SUCCESS;
}
static int exec_GetTextColor( filter_t *p_filter,
const commandparams_t *p_params,
commandparams_t *p_results )
{
filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
overlay_t *p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
if( p_ovl == NULL )
return VLC_EGENERIC;
p_results->fontstyle.i_font_color = p_ovl->fontstyle.i_font_color;
return VLC_SUCCESS;
}
static int exec_GetTextSize( filter_t *p_filter,
const commandparams_t *p_params,
commandparams_t *p_results )
{
filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
overlay_t *p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
if( p_ovl == NULL )
return VLC_EGENERIC;
p_results->fontstyle.i_font_size = p_ovl->fontstyle.i_font_size;
return VLC_SUCCESS;
}
static int exec_GetVisibility( filter_t *p_filter,
const commandparams_t *p_params,
commandparams_t *p_results )
{
filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
overlay_t *p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
if( p_ovl == NULL )
return VLC_EGENERIC;
p_results->b_visible = ( p_ovl->b_active == VLC_TRUE ) ? 1 : 0;
return VLC_SUCCESS;
}
static int exec_SetAlpha( filter_t *p_filter,
const commandparams_t *p_params,
commandparams_t *p_results )
{
(void)(p_results);
filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
overlay_t *p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
if( p_ovl == NULL )
return VLC_EGENERIC;
p_ovl->i_alpha = p_params->i_alpha;
p_sys->b_updated = p_ovl->b_active;
return VLC_SUCCESS;
}
static int exec_SetPosition( filter_t *p_filter,
const commandparams_t *p_params,
commandparams_t *p_results )
{
(void)(p_results);
filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
overlay_t *p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
if( p_ovl == NULL )
return VLC_EGENERIC;
p_ovl->i_x = p_params->i_x;
p_ovl->i_y = p_params->i_y;
p_sys->b_updated = p_ovl->b_active;
return VLC_SUCCESS;
}
static int exec_SetTextAlpha( filter_t *p_filter,
const commandparams_t *p_params,
commandparams_t *p_results )
{
(void)(p_results);
filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
overlay_t *p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
if( p_ovl == NULL )
return VLC_EGENERIC;
p_ovl->fontstyle.i_font_alpha = p_params->fontstyle.i_font_alpha;
p_sys->b_updated = p_ovl->b_active;
return VLC_SUCCESS;
}
static int exec_SetTextColor( filter_t *p_filter,
const commandparams_t *p_params,
commandparams_t *p_results )
{
(void)(p_results);
filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
overlay_t *p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
if( p_ovl == NULL )
return VLC_EGENERIC;
p_ovl->fontstyle.i_font_color = p_params->fontstyle.i_font_color;
p_sys->b_updated = p_ovl->b_active;
return VLC_SUCCESS;
}
static int exec_SetTextSize( filter_t *p_filter,
const commandparams_t *p_params,
commandparams_t *p_results )
{
(void)(p_results);
filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
overlay_t *p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
if( p_ovl == NULL )
return VLC_EGENERIC;
p_ovl->fontstyle.i_font_size = p_params->fontstyle.i_font_size;
p_sys->b_updated = p_ovl->b_active;
return VLC_SUCCESS;
}
static int exec_SetVisibility( filter_t *p_filter,
const commandparams_t *p_params,
commandparams_t *p_results )
{
(void)(p_results);
filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
overlay_t *p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
if( p_ovl == NULL )
return VLC_EGENERIC;
p_ovl->b_active = p_params->b_visible;// ? VLC_FALSE : VLC_TRUE;
p_sys->b_updated = VLC_TRUE;
return VLC_SUCCESS;
}
static int exec_StartAtomic( filter_t *p_filter,
const commandparams_t *p_params,
commandparams_t *p_results )
{
filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
(void)(p_params);
(void)(p_results);
p_sys->b_atomic = VLC_TRUE;
return VLC_SUCCESS;
}
/*****************************************************************************
* Command functions
*****************************************************************************/
static commanddesc_t p_commands[] =
{
{ .psz_command = "DataSharedMem",
.b_atomic = VLC_TRUE,
.pf_parser = parser_DataSharedMem,
.pf_execute = exec_DataSharedMem,
.pf_unparse = unparse_default,
},
{ .psz_command = "DeleteImage",
.b_atomic = VLC_TRUE,
.pf_parser = parser_Id,
.pf_execute = exec_DeleteImage,
.pf_unparse = unparse_default,
},
{ .psz_command = "EndAtomic",
.b_atomic = VLC_FALSE,
.pf_parser = parser_None,
.pf_execute = exec_EndAtomic,
.pf_unparse = unparse_default,
},
{ .psz_command = "GenImage",
.b_atomic = VLC_FALSE,
.pf_parser = parser_None,
.pf_execute = exec_GenImage,
.pf_unparse = unparse_GenImage,
},
{ .psz_command = "GetAlpha",
.b_atomic = VLC_FALSE,
.pf_parser = parser_Id,
.pf_execute = exec_GetAlpha,
.pf_unparse = unparse_GetAlpha,
},
{ .psz_command = "GetPosition",
.b_atomic = VLC_FALSE,
.pf_parser = parser_Id,
.pf_execute = exec_GetPosition,
.pf_unparse = unparse_GetPosition,
},
{ .psz_command = "GetTextAlpha",
.b_atomic = VLC_FALSE,
.pf_parser = parser_Id,
.pf_execute = exec_GetTextAlpha,
.pf_unparse = unparse_GetTextAlpha,
},
{ .psz_command = "GetTextColor",
.b_atomic = VLC_FALSE,
.pf_parser = parser_Id,
.pf_execute = exec_GetTextColor,
.pf_unparse = unparse_GetTextColor,
},
{ .psz_command = "GetTextSize",
.b_atomic = VLC_TRUE,
.pf_parser = parser_Id,
.pf_execute = exec_GetTextSize,
.pf_unparse = unparse_GetTextSize,
},
{ .psz_command = "GetVisibility",
.b_atomic = VLC_FALSE,
.pf_parser = parser_Id,
.pf_execute = exec_GetVisibility,
.pf_unparse = unparse_GetVisibility,
},
{ .psz_command = "SetAlpha",
.b_atomic = VLC_TRUE,
.pf_parser = parser_SetAlpha,
.pf_execute = exec_SetAlpha,
.pf_unparse = unparse_default,
},
{ .psz_command = "SetPosition",
.b_atomic = VLC_TRUE,
.pf_parser = parser_SetPosition,
.pf_execute = exec_SetPosition,
.pf_unparse = unparse_default,
},
{ .psz_command = "SetTextAlpha",
.b_atomic = VLC_TRUE,
.pf_parser = parser_SetTextAlpha,
.pf_execute = exec_SetTextAlpha,
.pf_unparse = unparse_default,
},
{ .psz_command = "SetTextColor",
.b_atomic = VLC_TRUE,
.pf_parser = parser_SetTextColor,
.pf_execute = exec_SetTextColor,
.pf_unparse = unparse_default,
},
{ .psz_command = "SetTextSize",
.b_atomic = VLC_TRUE,
.pf_parser = parser_SetTextSize,
.pf_execute = exec_SetTextSize,
.pf_unparse = unparse_default,
},
{ .psz_command = "SetVisibility",
.b_atomic = VLC_TRUE,
.pf_parser = parser_SetVisibility,
.pf_execute = exec_SetVisibility,
.pf_unparse = unparse_default,
},
{ .psz_command = "StartAtomic",
.b_atomic = VLC_TRUE,
.pf_parser = parser_None,
.pf_execute = exec_StartAtomic,
.pf_unparse = unparse_default,
}
};
void RegisterCommand( filter_t *p_filter )
{
filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
size_t i_index = 0;
p_sys->i_commands = ARRAY_SIZE(p_commands);
p_sys->pp_commands = (commanddesc_t **) calloc( p_sys->i_commands, sizeof(commanddesc_t*) );
if( !p_sys->pp_commands ) return;
for( i_index = 0; i_index < p_sys->i_commands; i_index ++ )
{
p_sys->pp_commands[i_index] = (commanddesc_t *) malloc( sizeof(commanddesc_t) );
if( !p_sys->pp_commands[i_index] ) return;
p_sys->pp_commands[i_index]->psz_command = strdup( p_commands[i_index].psz_command );
p_sys->pp_commands[i_index]->b_atomic = p_commands[i_index].b_atomic;
p_sys->pp_commands[i_index]->pf_parser = p_commands[i_index].pf_parser;
p_sys->pp_commands[i_index]->pf_execute = p_commands[i_index].pf_execute;
p_sys->pp_commands[i_index]->pf_unparse = p_commands[i_index].pf_unparse;
}
msg_Dbg( p_filter, "%d commands are available", p_sys->i_commands );
for( size_t i_index = 0; i_index < p_sys->i_commands; i_index++ )
msg_Dbg( p_filter, " %s", p_sys->pp_commands[i_index]->psz_command );
}
void UnregisterCommand( filter_t *p_filter )
{
filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
size_t i_index = 0;
for( i_index = 0; i_index < p_sys->i_commands; i_index++ )
{
free( p_sys->pp_commands[i_index]->psz_command );
free( p_sys->pp_commands[i_index] );
}
free( p_sys->pp_commands );
p_sys->pp_commands = NULL;
p_sys->i_commands = 0;
}
/*****************************************************************************
* dynamicoverlay_commands.def : dynamic overlay plugin commands
*****************************************************************************
* Copyright (C) 2008 the VideoLAN team
* $Id$
*
* Author: Søren Bøg <avacore@videolan.org>
* Jean-Paul Saman <jpsaman@videolan.org>
*
* This program 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.
*
* This program 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#include <sys/shm.h>
/* Commands must be sorted alphabetically.
I haven't found out how to implement quick sort in cpp */
COMMAND( DataSharedMem, INT( i_id ) INT( i_width ) INT( i_height )
CHARS( p_fourcc, 4 ) INT( i_shmid ), , VLC_TRUE, {
overlay_t *p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
if( p_ovl == NULL ) {
msg_Err( p_filter, "Invalid overlay: %d", p_params->i_id );
return VLC_EGENERIC;
}
struct shmid_ds shminfo;
if( shmctl( p_params->i_shmid, IPC_STAT, &shminfo ) == -1 ) {
msg_Err( p_filter, "Unable to access shared memory" );
return VLC_EGENERIC;
}
size_t i_size = shminfo.shm_segsz;
if( strncmp( p_params->p_fourcc, "TEXT", 4 ) == 0 ) {
if( p_params->i_height != 1 || p_params->i_width < 1 ) {
msg_Err( p_filter,
"Invalid width and/or height. when specifing text height "
"must be 1 and width the number of bytes in the string, "
"including the null terminator" );
return VLC_EGENERIC;
}
if( p_params->i_width > i_size ) {
msg_Err( p_filter,
"Insufficient data in shared memory. need %d, got %d",
p_params->i_width, i_size );
return VLC_EGENERIC;
}
p_ovl->data.p_text = malloc( p_params->i_width );
if( p_ovl->data.p_text == NULL )
{
msg_Err( p_filter, "Unable to allocate string storage" );
return VLC_ENOMEM;
}
vout_InitFormat( &p_ovl->format, VLC_FOURCC( 'T', 'E', 'X', 'T' ), 0, 0,
0 );
char *p_data = shmat( p_params->i_shmid, NULL, SHM_RDONLY );
if( p_data == NULL )
{
msg_Err( p_filter, "Unable to attach to shared memory" );
free( p_ovl->data.p_text );
p_ovl->data.p_text = NULL;
return VLC_ENOMEM;
}
memcpy( p_ovl->data.p_text, p_data, p_params->i_width );
shmdt( p_data );
} else {
p_ovl->data.p_pic = malloc( sizeof( picture_t ) );
if( p_ovl->data.p_pic == NULL )
{
msg_Err( p_filter, "Unable to allocate picture structure" );
return VLC_ENOMEM;
}
vout_InitFormat( &p_ovl->format, VLC_FOURCC( p_params->p_fourcc[0],
p_params->p_fourcc[1],
p_params->p_fourcc[2],
p_params->p_fourcc[3] ),
p_params->i_width, p_params->i_height,
VOUT_ASPECT_FACTOR );
if( vout_AllocatePicture( p_filter, p_ovl->data.p_pic,
p_ovl->format.i_chroma, p_params->i_width,
p_params->i_height, p_ovl->format.i_aspect ) )
{
msg_Err( p_filter, "Unable to allocate picture" );
free( p_ovl->data.p_pic );
p_ovl->data.p_pic = NULL;
return VLC_ENOMEM;
}
size_t i_neededsize = 0;
for( size_t i_plane = 0; i_plane < p_ovl->data.p_pic->i_planes;
++i_plane ) {
i_neededsize += p_ovl->data.p_pic->p[i_plane].i_visible_lines *
p_ovl->data.p_pic->p[i_plane].i_visible_pitch;
}
if( i_neededsize > i_size ) {
msg_Err( p_filter,
"Insufficient data in shared memory. need %d, got %d",
i_neededsize, i_size );
p_ovl->data.p_pic->pf_release( p_ovl->data.p_pic );
free( p_ovl->data.p_pic );
p_ovl->data.p_pic = NULL;
return VLC_EGENERIC;
}
char *p_data = shmat( p_params->i_shmid, NULL, SHM_RDONLY );
if( p_data == NULL )
{
msg_Err( p_filter, "Unable to attach to shared memory" );
p_ovl->data.p_pic->pf_release( p_ovl->data.p_pic );
free( p_ovl->data.p_pic );
p_ovl->data.p_pic = NULL;
return VLC_ENOMEM;
}
char *p_in = p_data;
for( size_t i_plane = 0; i_plane < p_ovl->data.p_pic->i_planes;
++i_plane ) {
char *p_out = p_ovl->data.p_pic->p[i_plane].p_pixels;
for( size_t i_line = 0;
i_line < p_ovl->data.p_pic->p[i_plane].i_visible_lines;
++i_line ) {
p_filter->p_libvlc->pf_memcpy( p_out, p_in,
p_ovl->data.p_pic->p[i_plane].i_visible_pitch );
p_out += p_ovl->data.p_pic->p[i_plane].i_pitch;
p_in += p_ovl->data.p_pic->p[i_plane].i_visible_pitch;
}
}
shmdt( p_data );
}
p_sys->b_updated = p_ovl->b_active;
return VLC_SUCCESS;
} )
COMMAND( DeleteImage, INT( i_id ), , VLC_TRUE, {
p_sys->b_updated = VLC_TRUE;
return ListRemove( &p_sys->overlays, p_params->i_id );
} )
COMMAND( EndAtomic, , , VLC_FALSE, {
QueueTransfer( &p_sys->pending, &p_sys->atomic );
p_sys->b_atomic = VLC_FALSE;
return VLC_SUCCESS;
} )
COMMAND( GenImage, , INT( i_newid ), VLC_FALSE, {
overlay_t *p_ovl = OverlayCreate();
if( p_ovl == NULL ) {
return VLC_ENOMEM;
}
ssize_t i_idx = ListAdd( &p_sys->overlays, p_ovl );
if( i_idx < 0 ) {
return i_idx;
}
p_results->i_newid = i_idx;
return VLC_SUCCESS;
} )
COMMAND( GetAlpha, INT( i_id ), INT( i_alpha ), VLC_FALSE, {
overlay_t *p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
if( p_ovl == NULL ) {
return VLC_EGENERIC;
}
p_results->i_alpha = p_ovl->i_alpha;
return VLC_SUCCESS;
} )
COMMAND( GetPosition, INT( i_id ), INT( i_x ) INT( i_y ), VLC_FALSE, {
overlay_t *p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
if( p_ovl == NULL ) {
return VLC_EGENERIC;
}
p_results->i_x = p_ovl->i_x;
p_results->i_y = p_ovl->i_y;
return VLC_SUCCESS;
} )
COMMAND( GetVisibility, INT( i_id ), INT( i_vis ), VLC_FALSE, {
overlay_t *p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
if( p_ovl == NULL ) {
return VLC_EGENERIC;
}
p_results->i_vis = ( p_ovl->b_active == VLC_TRUE ) ? 1 : 0;
return VLC_SUCCESS;
} )
COMMAND( SetAlpha, INT( i_id ) INT( i_alpha ), , VLC_TRUE, {
overlay_t *p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
if( p_ovl == NULL ) {
return VLC_EGENERIC;
}
p_ovl->i_alpha = p_params->i_alpha;
p_sys->b_updated = p_ovl->b_active;
return VLC_SUCCESS;
} )
COMMAND( SetPosition, INT( i_id ) INT( i_x ) INT( i_y ), , VLC_TRUE, {
overlay_t *p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
if( p_ovl == NULL ) {
return VLC_EGENERIC;
}
p_ovl->i_x = p_params->i_x;
p_ovl->i_y = p_params->i_y;
p_sys->b_updated = p_ovl->b_active;
return VLC_SUCCESS;
} )
COMMAND( SetVisibility, INT( i_id ) INT( i_vis ), , VLC_TRUE, {
overlay_t *p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
if( p_ovl == NULL ) {
return VLC_EGENERIC;
}
p_ovl->b_active = ( p_params->i_vis == 0 ) ? VLC_FALSE : VLC_TRUE;
p_sys->b_updated = VLC_TRUE;
return VLC_SUCCESS;
} )
COMMAND( StartAtomic, , , VLC_FALSE, {
p_sys->b_atomic = VLC_TRUE;
return VLC_SUCCESS;
} )
/*****************************************************************************
* dynamicoverlay_list.h : dynamic overlay list
*****************************************************************************
* Copyright (C) 2008 the VideoLAN team
* $Id$
*
* Author: Søren Bøg <avacore@videolan.org>
* Jean-Paul Saman <jpsaman@videolan.org>
*
* This program 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.
*
* This program 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <vlc/vlc.h>
#include <vlc_osd.h>
#include <fcntl.h>
#include "dynamicoverlay.h"
/*****************************************************************************
* list_t: Command queue
*****************************************************************************/
int ListInit( list_t *p_list )
{
p_list->pp_head = malloc( 16 * sizeof( overlay_t * ) );
if( p_list->pp_head == NULL )
return VLC_ENOMEM;
p_list->pp_tail = p_list->pp_head + 16;
memset( p_list->pp_head, 0, 16 * sizeof( overlay_t * ) );
return VLC_SUCCESS;
}
int ListDestroy( list_t *p_list )
{
for( overlay_t **pp_cur = p_list->pp_head;
pp_cur < p_list->pp_tail;
++pp_cur )
{
if( *pp_cur != NULL )
{
OverlayDestroy( *pp_cur );
free( *pp_cur );
}
}
free( p_list->pp_head );
return VLC_SUCCESS;
}
ssize_t ListAdd( list_t *p_list, overlay_t *p_new )
{
/* Find an available slot */
for( overlay_t **pp_cur = p_list->pp_head;
pp_cur < p_list->pp_tail;
++pp_cur )
{
if( *pp_cur == NULL )
{
*pp_cur = p_new;
return pp_cur - p_list->pp_head;
}
}
/* Have to expand */
size_t i_size = p_list->pp_tail - p_list->pp_head;
size_t i_newsize = i_size * 2;
p_list->pp_head = realloc( p_list->pp_head,
i_newsize * sizeof( overlay_t * ) );
if( p_list->pp_head == NULL )
return VLC_ENOMEM;
p_list->pp_tail = p_list->pp_head + i_newsize;
memset( p_list->pp_head + i_size, 0, i_size * sizeof( overlay_t * ) );
p_list->pp_head[i_size] = p_new;
return i_size;
}
int ListRemove( list_t *p_list, size_t i_idx )
{
int ret;
if( ( i_idx >= (size_t)( p_list->pp_tail - p_list->pp_head ) ) ||
( p_list->pp_head[i_idx] == NULL ) )
{
return VLC_EGENERIC;
}
ret = OverlayDestroy( p_list->pp_head[i_idx] );
free( p_list->pp_head[i_idx] );
p_list->pp_head[i_idx] = NULL;
return ret;
}
overlay_t *ListGet( list_t *p_list, size_t i_idx )
{
if( ( i_idx >= (size_t)( p_list->pp_tail - p_list->pp_head ) ) ||
( p_list->pp_head[i_idx] == NULL ) )
{
return NULL;
}
return p_list->pp_head[i_idx];
}
overlay_t *ListWalk( list_t *p_list )
{
static overlay_t **pp_cur = NULL;
if( pp_cur == NULL )
pp_cur = p_list->pp_head;
else
pp_cur = pp_cur + 1;
for( ; pp_cur < p_list->pp_tail; ++pp_cur )
{
if( ( *pp_cur != NULL ) &&
( (*pp_cur)->b_active == VLC_TRUE )&&
( (*pp_cur)->format.i_chroma != VLC_FOURCC( '\0','\0','\0','\0') ) )
{
return *pp_cur;
}
}
pp_cur = NULL;
return NULL;
}
......@@ -27,6 +27,7 @@
#endif
#include <vlc/vlc.h>
#include <vlc_osd.h>
#include "dynamicoverlay.h"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment