Commit 84cad9ba authored by Andre Pang's avatar Andre Pang
Browse files

* Added Continuous Media Markup Language (CMML) codec

parent 87a35e06
......@@ -2346,6 +2346,16 @@ AX_ADD_LDFLAGS([subsdec],[${LIBICONV}])
AX_ADD_CPPFLAGS([subsdec],[${INCICONV}])
AX_ADD_PLUGINS([subsdec])
dnl
dnl CMML plugin
dnl
AC_ARG_ENABLE(cmml,
[ --enable-cmml CMML support (default enabled)])
if test "${enable_cmml}" != "no"
then
AX_ADD_PLUGINS([cmml])
fi
dnl
dnl Video Filters
......@@ -3776,6 +3786,7 @@ AC_CONFIG_FILES([
modules/audio_mixer/Makefile
modules/audio_output/Makefile
modules/codec/Makefile
modules/codec/cmml/Makefile
modules/codec/ffmpeg/Makefile
modules/codec/ffmpeg/postprocessing/Makefile
modules/codec/ogt/Makefile
......
List of vlc plugins (221)
$Id: LIST,v 1.19 2004/01/05 13:07:02 zorglub Exp $
$Id$
* a52: A/52 basic parser/packetizer
......@@ -70,6 +70,8 @@ $Id: LIST,v 1.19 2004/01/05 13:07:02 zorglub Exp $
* cinepak: Cinepack video decoder
* clone: Clone video filter
* cmml: Continuous Media Markup Language annotations/hyperlinks decoder
* corba: CORBA control module
......
SOURCES_cmml = \
browser_open.c browser_open.h \
cmml.c \
history.c history.h \
intf.c \
xarray.c xarray.h \
xlist.c xlist.h \
xstrcat.h \
xtag.c xtag.h \
xurl.c xurl.h
/*****************************************************************************
* browser_open.c: platform-independent opening of a web browser
*****************************************************************************
* Copyright (C) 2004 Commonwealth Scientific and Industrial Research
* Organisation (CSIRO) Australia
* Copyright (C) 2004 VideoLAN
*
* $Id$
*
* Authors: Andre Pang <Andre.Pang@csiro.au>
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
#include <stdlib.h>
#include <string.h>
#include "xstrcat.h"
int browser_Open( char *psz_url )
{
#ifdef SYS_DARWIN
char *psz_open_commandline;
psz_open_commandline = strdup( "open " );
xstrcat( psz_open_commandline, psz_url );
return system( psz_open_commandline );
#elif defined( WIN32 )
char *psz_open_commandline;
psz_open_commandline = strdup( "explorer " );
xstrcat( psz_open_commandline, psz_url );
return system( psz_open_commandline );
#else
/* Assume we're on a UNIX of some sort */
char *psz_open_commandline;
/* Debian uses www-browser */
psz_open_commandline = strdup( "www-browser" );
xstrcat( psz_open_commandline, psz_url );
if( system( psz_open_commandline ) != 0 )
{
free( psz_open_commandline );
/* Try mozilla */
psz_open_commandline = strdup( "mozilla" );
xstrcat( psz_open_commandline, psz_url );
return system( psz_open_commandline );
}
#endif
}
/*****************************************************************************
* browser_open.h: platform-independent opening of a web browser
*****************************************************************************
* Copyright (C) 2004 Commonwealth Scientific and Industrial Research
* Organisation (CSIRO) Australia
* Copyright (C) 2004 VideoLAN
*
* $Id$
*
* Authors: Andre Pang <Andre.Pang@csiro.au>
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
#ifndef __BROWSER_OPEN_H__
#define __BROWSER_OPEN_H__
int browser_Open( char *psz_url );
#endif /* __BROWSER_OPEN_H__ */
/*****************************************************************************
* cmml.c : CMML annotations/metadata decoder
*****************************************************************************
* Copyright (C) 2003-2004 Commonwealth Scientific and Industrial Research
* Organisation (CSIRO) Australia
* Copyright (C) 2004 VideoLAN
*
* $Id$
*
* Author: Andre Pang <Andre.Pang@csiro.au>
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <vlc/vlc.h>
#include <vlc/decoder.h>
#include <vlc/intf.h>
#include <osd.h>
#include "charset.h"
#include "xtag.h"
#undef CMML_DEBUG
/*****************************************************************************
* decoder_sys_t : decoder descriptor
*****************************************************************************/
struct decoder_sys_t
{
intf_thread_t * p_intf;
};
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static int OpenDecoder ( vlc_object_t * );
static void CloseDecoder ( vlc_object_t * );
static void DecodeBlock ( decoder_t *, block_t ** );
static void ParseText ( decoder_t *, block_t * );
/*****************************************************************************
* Exported prototypes
*****************************************************************************/
int E_(OpenIntf) ( vlc_object_t * );
void E_(CloseIntf) ( vlc_object_t * );
/*****************************************************************************
* Module descriptor.
*****************************************************************************/
vlc_module_begin();
set_description( _("CMML annotations decoder") );
set_capability( "decoder", 50 );
set_callbacks( OpenDecoder, CloseDecoder );
add_shortcut( "cmml" );
add_submodule();
set_capability( "interface", 0 );
set_callbacks( E_(OpenIntf), E_(CloseIntf) );
vlc_module_end();
/*****************************************************************************
* OpenDecoder: probe the decoder and return score
*****************************************************************************
* Tries to launch a decoder and return score so that the interface is able
* to chose.
*****************************************************************************/
static int OpenDecoder( vlc_object_t *p_this )
{
decoder_t *p_dec = (decoder_t*)p_this;
input_thread_t * p_input;
decoder_sys_t *p_sys;
vlc_value_t val;
if( p_dec->fmt_in.i_codec != VLC_FOURCC('c','m','m','l') )
{
return VLC_EGENERIC;
}
p_dec->pf_decode_sub = DecodeBlock;
#ifdef CMML_DEBUG
msg_Dbg( p_dec, "I am at %p", p_dec );
#endif
/* Allocate the memory needed to store the decoder's structure */
if( ( p_dec->p_sys = p_sys =
(decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
{
msg_Err( p_dec, "out of memory" );
return VLC_EGENERIC;
}
/* Let other interested modules know that we're a CMML decoder
* We have to set this variable on the input thread, because there's
* typically more than one decoder running so we can't find the CMML
* decoder succesfully with vlc_object_find. (Any hints on how to achieve
* this would be rather appreciated ;) */
p_input = vlc_object_find( p_dec, VLC_OBJECT_INPUT, FIND_ANYWHERE );
#ifdef CMML_DEBUG
msg_Dbg( p_dec, "p_input is at %p", p_input );
#endif
val.p_address = p_dec;
var_Create( p_input, "has-cmml-decoder",
VLC_VAR_ADDRESS|VLC_VAR_DOINHERIT );
if( var_Set( p_input, "has-cmml-decoder", val ) != VLC_SUCCESS )
{
msg_Dbg( p_dec, "var_Set of has-cmml-decoder failed" );
}
vlc_object_release( p_input );
/* initialise the CMML responder interface */
p_sys->p_intf = intf_Create( p_dec, "cmml" );
p_sys->p_intf->b_block = VLC_FALSE;
intf_RunThread( p_sys->p_intf );
return VLC_SUCCESS;
}
/****************************************************************************
* DecodeBlock: the whole thing
****************************************************************************
* This function must be fed with complete subtitles units.
****************************************************************************/
static void DecodeBlock( decoder_t *p_dec, block_t **pp_block )
{
if( !pp_block || *pp_block == NULL )
{
return;
}
ParseText( p_dec, *pp_block );
block_Release( *pp_block );
*pp_block = NULL;
}
/*****************************************************************************
* CloseDecoder: clean up the decoder
*****************************************************************************/
static void CloseDecoder( vlc_object_t *p_this )
{
decoder_t *p_dec = (decoder_t *)p_this;
decoder_sys_t *p_sys = p_dec->p_sys;
intf_thread_t *p_intf;
/* Destroy the interface object/thread */
p_intf = vlc_object_find( p_dec, VLC_OBJECT_INTF, FIND_CHILD );
if( p_intf != NULL )
{
#ifdef CMML_DEBUG
msg_Dbg( p_dec, "CMML decoder is freeing interface thread" );
#endif
intf_StopThread( p_intf );
vlc_object_detach( p_intf );
vlc_object_release( p_intf );
intf_Destroy( p_intf );
}
p_sys->p_intf = NULL;
free( p_sys );
}
/*****************************************************************************
* ParseText: parse an text subtitle packet and send it to the video output
*****************************************************************************/
static void ParseText( decoder_t *p_dec, block_t *p_block )
{
char *psz_subtitle, *psz_cmml, *psz_url;
XTag *p_clip_parser, *p_anchor;
vlc_value_t val;
/* We cannot display a subpicture with no date */
if( p_block->i_pts == 0 )
{
msg_Warn( p_dec, "subtitle without a date" );
return;
}
/* Check validity of packet data */
if( p_block->i_buffer <= 1 || p_block->p_buffer[0] == '\0' )
{
msg_Warn( p_dec, "empty subtitle" );
return;
}
/* get anchor text from CMML */
/* Copy the whole CMML tag into our own buffer:
allocate i_buffer bytes + 1 for the terminating \0 */
if ( (psz_cmml = malloc( p_block->i_buffer + 1 )) == NULL )
return;
psz_cmml = memcpy( psz_cmml, p_block->p_buffer, p_block->i_buffer );
psz_cmml[p_block->i_buffer] = '\0'; /* terminate the string */
#ifdef CMML_DEBUG
msg_Dbg( p_dec, "psz_cmml is \"%s\"", psz_cmml );
#endif
/* Parse the <clip> part of the CMML */
p_clip_parser = xtag_new_parse( psz_cmml, p_block->i_buffer );
if( !p_clip_parser )
{
msg_Warn( p_dec, "couldn't initialise <clip> parser" );
free( psz_cmml );
return;
}
/* Parse the anchor tag and get its contents */
p_anchor = xtag_first_child( p_clip_parser, "a" );
if( p_anchor != NULL )
{
psz_subtitle = xtag_get_pcdata( p_anchor );
}
else
{
psz_subtitle = strdup( " " );
}
#ifdef CMML_DEBUG
msg_Dbg( p_dec, "psz_subtitle is \"%s\"", psz_subtitle );
#endif
/* get URL from the current clip, if one exists */
psz_url = xtag_get_attribute( p_anchor, "href" );
#ifdef CMML_DEBUG
msg_Dbg( p_dec, "psz_url is \"%s\"", psz_url );
#endif
if( psz_url )
{
char *psz_tmp = strdup( psz_url );
val.p_address = psz_tmp;
if( var_Set( p_dec, "psz-current-anchor-url", val ) != VLC_SUCCESS )
{
(void) var_Create( p_dec, "psz-current-anchor-url",
VLC_VAR_ADDRESS|VLC_VAR_DOINHERIT );
msg_Dbg( p_dec, "creating psz-current-anchor-url" );
if( var_Set( p_dec, "psz-current-anchor-url", val ) != VLC_SUCCESS )
msg_Dbg( p_dec, "var_Set of psz-current-anchor-url failed" );
}
}
if( psz_subtitle )
{
char *psz_tmp = strdup( psz_subtitle );
val.p_address = psz_tmp;
if( var_Set( p_dec, "psz-current-anchor-description", val ) != VLC_SUCCESS )
{
(void) var_Create( p_dec, "psz-current-anchor-description",
VLC_VAR_ADDRESS|VLC_VAR_DOINHERIT );
msg_Dbg( p_dec, "creating psz-current-anchor-description" );
if( var_Set( p_dec, "psz-current-anchor-description", val ) != VLC_SUCCESS )
msg_Dbg( p_dec, "var_Set of psz-current-anchor-description failed" );
}
}
if( psz_subtitle ) free( psz_subtitle );
if( psz_cmml ) free( psz_cmml );
if( p_anchor ) free( p_anchor );
if( p_clip_parser ) free( p_clip_parser );
if( psz_url ) free( psz_url );
}
/*****************************************************************************
* history.c: vlc_history_t (web-browser-like back/forward history) handling
*****************************************************************************
* Copyright (C) 2004 Commonwealth Scientific and Industrial Research
* Organisation (CSIRO) Australia
* Copyright (C) 2004 VideoLAN
*
* $Id$
*
* Authors: Andre Pang <Andre.Pang@csiro.au>
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
#include <vlc/vlc.h>
#include "history.h"
#include "xarray.h"
#ifdef HAVE_STDLIB_H
# include <stdlib.h> /* realloc() */
#endif
#undef HISTORY_DEBUG
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static void history_Dump( history_t *p_history );
/*****************************************************************************
* Local structure lock
*****************************************************************************/
/*****************************************************************************
* Actual history code
*****************************************************************************/
history_t *history_New()
{
history_t *p_new_history;
p_new_history = calloc( 1, sizeof( struct history_t ) );
if( p_new_history == NULL ) return NULL;
p_new_history->p_xarray = xarray_New( 0 );
if( p_new_history->p_xarray == NULL )
{
free( p_new_history );
return NULL;
}
#ifndef HISTORY_DEBUG
/* make dummy reference to history_Dump to avoid compiler warnings */
while (0)
{
void *p_tmp;
p_tmp = history_Dump;
}
#endif
return p_new_history;
}
vlc_bool_t history_GoBackSavingCurrentItem ( history_t *p_history,
history_item_t *p_item )
{
history_PruneAndInsert( p_history, p_item );
/* PruneAndInsert will increment the index, so we need to go
* back one position to reset the index to the place we were at
* before saving the current state, and then go back one more to
* actually go back */
p_history->i_index -= 2;
#ifdef HISTORY_DEBUG
history_Dump( p_history );
#endif
return VLC_TRUE;
}
static void history_Dump( history_t *p_history )
{
unsigned int i_count;
int i;
if( xarray_Count( p_history->p_xarray, &i_count ) != XARRAY_SUCCESS )
return;
for (i = 0; i < (int) i_count; i++)
{
history_item_t *p_item;
void *pv_item;
xarray_ObjectAtIndex( p_history->p_xarray, i, &pv_item );
p_item = (history_item_t *) pv_item;
if( p_item == NULL )
fprintf( stderr, "HISTORY: [%d] NULL\n", i );
else
fprintf( stderr, "HISTORY: [%d] %p (%p->%s)\n", i, p_item,
p_item->psz_uri, p_item->psz_uri );
}
}
vlc_bool_t history_GoForwardSavingCurrentItem ( history_t *p_history,
history_item_t *p_item )
{
#ifdef HISTORY_DEBUG
history_Dump( p_history );
#endif
if( xarray_ReplaceObject( p_history->p_xarray, p_history->i_index, p_item )
== XARRAY_SUCCESS )
{
p_history->i_index++;
return VLC_TRUE;
}
else
{
return VLC_FALSE;
}
}
vlc_bool_t history_CanGoBack( history_t *p_history )
{
if( p_history->i_index > 0 )
return VLC_TRUE;
else
return VLC_FALSE;
}
vlc_bool_t history_CanGoForward( history_t *p_history )
{
unsigned int i_count;
if( xarray_Count( p_history->p_xarray, &i_count ) != XARRAY_SUCCESS )
return VLC_FALSE;
if( p_history->i_index < i_count )
return VLC_TRUE;
else
return VLC_FALSE;
}
history_item_t *history_Item( history_t *p_history )
{
history_item_t *p_item;
void *pv_item;
if( xarray_ObjectAtIndex( p_history->p_xarray, p_history->i_index,
&pv_item )
== XARRAY_SUCCESS )
{
p_item = (history_item_t *) pv_item;
return p_item;
}
else
{
return NULL;