[vlc-devel] [PATCH] Open Sound Control support using liblo
Rémi Denis-Courmont
rem at videolan.org
Sun Apr 12 19:40:44 CEST 2009
Hello,
Overall, the patch looks quite good, but I still a few minor coments:
diff --git a/configure.ac b/configure.ac
index 85f314c..4b7e800 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1013,6 +1013,21 @@ fi
;;
esac
+dnl
+dnl liblo based Open Sound Control plugin
+dnl
+AC_ARG_ENABLE(osc,
+ [ --enable-osc Open Sound Control plugin (default
disabled)])
+if test "${enable_osc}" = "yes"; then
+ PKG_CHECK_MODULES(LIBLO, liblo >= 0.26,
+ [AC_DEFINE(HAVE_LIBLO, 1, [Define if you have the liblo library])
Why is this AC_DEFINE? You don't seem to use HAVE_LIBIO anywhere, so
don't bother (with) <config.h>.
+ VLC_ADD_PLUGIN([osc])
+ VLC_ADD_LIBS([osc],[$LIBLO_LIBS])
+ VLC_ADD_CFLAGS([osc],[$LIBLO_CFLAGS])],
+ [AC_MSG_WARN(liblo library not found)])
If --enable-osc was explicitly specified but libio is not found, you
should probably fail hard.
+fi
+
+
dnl Build the gtk_main plugins?
NEED_GTK_MAIN=no
NEED_GNOME_MAIN=no
diff --git a/modules/control/Modules.am b/modules/control/Modules.am
index 61d2988..e88ff40 100644
--- a/modules/control/Modules.am
+++ b/modules/control/Modules.am
@@ -6,6 +6,7 @@ SOURCES_netsync = netsync.c
SOURCES_ntservice = ntservice.c
SOURCES_hotkeys = hotkeys.c
SOURCES_lirc = lirc.c
+SOURCES_osc = osc.c
SOURCES_rc = rc.c
SOURCES_dbus = dbus.c dbus.h
SOURCES_signals = signals.c
diff --git a/modules/control/osc.c b/modules/control/osc.c
new file mode 100644
index 0000000..524999d
--- /dev/null
+++ b/modules/control/osc.c
@@ -0,0 +1,281 @@
+/*****************************************************************************
+ * osc.c : Open Sound Control module for vlc
+
*****************************************************************************
+ * Copyright (C) 2008 the VideoLAN team
I guess 2008-2009 ?
+ * $Id$
+ *
+ * Author: Nicholas J Humfrey <njh at aelius.com>
+ *
+ * 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.
+
*****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+
*****************************************************************************/
+
+#include <fcntl.h>
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
Generally, I recommend including fcntl.h _after_ config.h, so you get
defines that may affect system headers (e.g. _GNU_SOURCE).
+
+#include <vlc_common.h>
+#include <vlc_plugin.h>
+#include <vlc_interface.h>
+#include <vlc_playlist.h>
+
+#include <lo/lo.h>
+
+
+#define OSC_PORT_TEXT N_( "Port Number to listen for OSC messages." )
+#define OSC_PORT_LONGTEXT N_( \
+ "Set the port number that VLC should listen for OSC messages on. "
\
+ "By default it chooses a random port number." )
+
+/* Thread-local variable to store object running the current thread */
+static vlc_threadvar_t thread_object_key;
+static int instance_count = 0;
unsigned.
+static vlc_mutex_t instance_count_lock = VLC_STATIC_MUTEX;
+
+
+/*****************************************************************************
+ * Local prototypes
+
*****************************************************************************/
+static int Open ( vlc_object_t * );
+static void Close ( vlc_object_t * );
+static void Run ( intf_thread_t * );
+
+static void ErrorHandler( int num, const char *msg, const char
*where );
+static int DeckHandler( const char *path, const char *types, lo_arg
**argv,
+ int argc, lo_message msg, void *user_data );
+static int WildcardHandler( const char *path, const char *types, lo_arg
**argv,
+ int argc, lo_message msg, void *user_data );
+
+/*****************************************************************************
+ * Module descriptor
+
*****************************************************************************/
+vlc_module_begin ()
+ set_shortname( N_("OSC") )
+ set_category( CAT_INTERFACE )
+ set_subcategory( SUBCAT_INTERFACE_CONTROL )
+ set_description( N_("Open Sound Control interface") )
+ set_capability( "interface", 0 )
+ set_callbacks( Open, Close )
+
+ add_string( "osc-port", NULL, NULL,
+ OSC_PORT_TEXT, OSC_PORT_LONGTEXT, false )
+vlc_module_end ()
+
+/*****************************************************************************
+ * intf_sys_t: description and status of interface
+
*****************************************************************************/
+struct intf_sys_t
+{
+ lo_server *p_server;
+};
+
+/*****************************************************************************
+ * ErrorHandler: callback for errors reported by liblo
+
*****************************************************************************/
+static void ErrorHandler( int num, const char *msg, const char *where )
+{
+ vlc_object_t *p_this =
(vlc_object_t*)vlc_threadvar_get(thread_object_key);
+ msg_Err( p_this, "liblo error %d: '%s' at '%s'", num, msg, where );
+}
+
+/*****************************************************************************
+ * DeckHandler: callback for /deck/ * messages
+
*****************************************************************************/
+static int DeckHandler( const char *path, const char *types, lo_arg
**argv,
+ int argc, lo_message msg, void *user_data )
+{
+ vlc_object_t *p_this = (vlc_object_t*)user_data;
+ char* psz_from = lo_address_get_url( lo_message_get_source(msg) );
+ playlist_t *p_playlist = NULL;
Assignment is not used.
+ int i_ret = 0;
+
+ msg_Info( p_this, "Recieved '%s' from '%s'.", path, psz_from );
+ free(psz_from);
+
+ p_playlist = pl_Hold( (vlc_object_t*) p_this );
Casting should not be needed here.
+ if ( !strcmp( path, "/deck/play" ) )
+ {
+ if (playlist_Status(p_playlist) == PLAYLIST_STOPPED) {
+ playlist_item_t *p_root = p_playlist->p_root_onelevel;
+ playlist_item_t *first_item = playlist_GetNextLeaf(
+ p_playlist, p_root, NULL, false, false );
+ if (first_item != NULL)
+ {
+ msg_Dbg( p_this, "Playing item id %d",
first_item->i_id );
+ playlist_Control( p_playlist, PLAYLIST_VIEWPLAY,
+ pl_Unlocked, NULL, first_item );
+ } else {
+ msg_Err( p_this, "Failed to find item on playlist to
play." );
+ }
+ } else {
+ msg_Dbg( p_this, "Resuming playback." );
+ playlist_Play( p_playlist );
+ }
+ }
+ else if ( !strcmp( path, "/deck/pause" ) )
+ {
+ playlist_Pause( p_playlist );
+ }
+ else if ( !strcmp( path, "/deck/stop" ) )
+ {
+ playlist_Stop( p_playlist );
+ }
+ else if ( !strcmp( path, "/deck/eject" ) )
+ {
+ playlist_Stop( p_playlist );
+ playlist_Clear( p_playlist, pl_Unlocked );
+ }
+ else if ( !strcmp( path, "/deck/load" ) )
+ {
+ playlist_Stop( p_playlist );
+ /* Add the item to the start of the playlist */
+ playlist_Add( p_playlist, &argv[0]->s, NULL, PLAYLIST_INSERT,
+ 0, true, pl_Unlocked );
+ }
+ else
+ {
+ /* We shouldn't get here, should only get paths we added
methods for */
+ msg_Err( p_this, "unhandled OSC message by DeckHandler: '%s'",
path );
+ i_ret = 1;
+ }
+ pl_Release( (vlc_object_t*) p_this );
Again, you shouldn't need to cast here.
+
+ return i_ret;
+}
+
+/*****************************************************************************
+ * WildcardHandler: callback for any unmatched messages
+
*****************************************************************************/
+static int WildcardHandler( const char *path, const char *types, lo_arg
**argv,
+ int argc, lo_message msg, void *user_data )
+{
+ vlc_object_t *p_this = (vlc_object_t*)user_data;
+ char* psz_from = lo_address_get_url( lo_message_get_source(msg) );
+
+ msg_Info( p_this, "unhandled OSC message: '%s' with args '%s'
from '%s'.\n",
+ path, types, psz_from );
+ free(psz_from);
+ return 1;
+}
+
+/*****************************************************************************
+ * Open: initialize interface
+
*****************************************************************************/
+static int Open( vlc_object_t *p_this )
+{
+ intf_thread_t *p_intf = (intf_thread_t *)p_this;
+ intf_sys_t *p_sys;
+ char *psz_port = NULL;
+ char *psz_url = NULL;
+
+ /* Allocate instance and initialize some members */
+ p_intf->p_sys = p_sys = malloc( sizeof( intf_sys_t ) );
+ if( p_sys == NULL )
+ return VLC_ENOMEM;
+
+ p_intf->pf_run = Run;
+
+ /* Get the port number parameter */
+ psz_port = var_CreateGetString( p_intf, "osc-port" );
+ if ( psz_port && *psz_port == '\0' )
+ {
+ psz_port = NULL;
+ }
+
+ /* Store pointer to self in a thread-local variable
+ (this is a work-around for the ErrorHandler callback) */
+ vlc_mutex_lock( &instance_count_lock );
+ if( instance_count++ == 0 )
+ vlc_threadvar_create( &thread_object_key, NULL );
+ vlc_mutex_unlock( &instance_count_lock );
+ vlc_threadvar_set( thread_object_key, p_this );
+
+ /* Create the liblo server structure */
+ msg_Dbg( p_this, "creating new lo_server(port=%s)", psz_port );
+ p_sys->p_server = lo_server_new( psz_port, ErrorHandler );
+ if( p_sys->p_server == NULL )
+ {
+ msg_Err( p_intf, "liblo initialisation failed" );
+ Close( p_this );
+ return VLC_EGENERIC;
+ }
+
+ /* Add callback handers to the server */
+ lo_server_add_method( p_sys->p_server, "/deck/play", NULL,
+ DeckHandler, p_intf );
+ lo_server_add_method( p_sys->p_server, "/deck/pause", NULL,
+ DeckHandler, p_intf );
+ lo_server_add_method( p_sys->p_server, "/deck/stop", NULL,
+ DeckHandler, p_intf );
+ lo_server_add_method( p_sys->p_server, "/deck/eject", NULL,
+ DeckHandler, p_intf );
+ lo_server_add_method( p_sys->p_server, "/deck/load", "s",
+ DeckHandler, p_intf );
+
+ /* add method that will match any path and args */
+ lo_server_add_method( p_sys->p_server, NULL, NULL,
+ WildcardHandler, p_intf );
+
+ /* Display our URL */
+ psz_url = lo_server_get_url( p_sys->p_server );
+ msg_Info( p_intf, "Listening for OSC messages on: %s", psz_url );
+
+ return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * Close: destroy interface
+
*****************************************************************************/
+static void Close( vlc_object_t *p_this )
+{
+ intf_thread_t *p_intf = (intf_thread_t *)p_this;
+ intf_sys_t *p_sys = p_intf->p_sys;
+
+ /* Destroy structure */
+ if (p_sys->p_server) lo_server_free( p_sys->p_server );
+ free( p_sys );
+
+ /* Delete thread-local variable, if we are the last instance */
+ vlc_mutex_lock( &instance_count_lock );
+ if( --instance_count == 0 )
+ vlc_threadvar_delete( &thread_object_key );
+ vlc_mutex_unlock( &instance_count_lock );
+}
+
+/*****************************************************************************
+ * Run: main loop
+
*****************************************************************************/
+static void Run( intf_thread_t *p_intf )
+{
+ intf_sys_t *p_sys = p_intf->p_sys;
+ int i_cancel, i_msg_available;
Is it so that ErrorHandler cannot be called from this thread?
I would have expected a vlc_threadvar_set() call here.
+
+ for( ;; )
+ {
+ /* Wait for a message / check if scheduled message needs
processing */
+ i_msg_available = lo_server_wait( p_sys->p_server, 100 );
+ if (i_msg_available<=0) continue;
Is 100 some kind of timeout value? If so, why can you not use an
infinite (or really long timeout)?
+
+ /* Recieve the message: hard work is perfomed in the callbacks
*/
+ i_cancel = vlc_savecancel();
+ lo_server_recv( p_sys->p_server );
+ vlc_restorecancel( i_cancel );
+ }
+}
Le dimanche 12 avril 2009, Nicholas J Humfrey a écrit :
> Is there anything left stopping the patch being integrated into the
> master branch?
Convincing the release manager (not me!) that this can violate the
feature freeze, or wait for the VLC 1.1 defrost.
Thanks and best regards,
--
Rémi Denis-Courmont
http://www.remlab.net/
More information about the vlc-devel
mailing list