]> git.sesse.net Git - vlc/commitdiff
* modules/control/http.c: brand new (and also basic) HTTP interface plugin for vlc...
authorGildas Bazin <gbazin@videolan.org>
Sat, 26 Apr 2003 21:36:23 +0000 (21:36 +0000)
committerGildas Bazin <gbazin@videolan.org>
Sat, 26 Apr 2003 21:36:23 +0000 (21:36 +0000)
configure.ac.in
modules/control/Modules.am
modules/control/http.c [new file with mode: 0644]

index 597a8194bf72abe173cbd9174705cbb903ddbbf7..32c644ef0203517ea6f06b240de9124a4bc506b0 100644 (file)
@@ -132,6 +132,7 @@ case "x${target_os}" in
         LDFLAGS_access_output_udp="${LDFLAGS_access_output_udp} -lws2_32"
         LDFLAGS_sap="${LDFLAGS_sap} -lws2_32"
         LDFLAGS_slp="${LDFLAGS_slp} -lws2_32"
+        LDFLAGS_http="${LDFLAGS_http} -lws2_32"
         LDFLAGS_httpd="${LDFLAGS_httpd} -lws2_32"
     fi
     ;;
@@ -291,6 +292,7 @@ AC_CHECK_FUNCS(send,,[
     LDFLAGS_access_udp="${LDFLAGS_access_udp} -lsocket"
     LDFLAGS_access_ftp="${LDFLAGS_access_ftp} -lsocket"
     LDFLAGS_sap="${LDFLAGS_sap} -lsocket"
+    LDFLAGS_http="${LDFLAGS_http} -lsocket"
     LDFLAGS_access_output_udp="${LDFLAGS_access_output_udp} -lsocket"
 )])
 
@@ -831,7 +833,7 @@ PLUGINS="${PLUGINS} id3 m3u"
 PLUGINS="${PLUGINS} rawvideo"
 PLUGINS="${PLUGINS} wav araw demuxdump demuxsub adpcm a52sys au"
 PLUGINS="${PLUGINS} access_file access_udp access_http ipv4 access_mms"
-PLUGINS="${PLUGINS} access_ftp access_directory sap httpd"
+PLUGINS="${PLUGINS} access_ftp access_directory sap httpd http"
 
 dnl
 dnl Some plugins aren't useful on some platforms
index 0aca56dea5a2b8cacadfd90196db1ef4f423f8f6..6fad06e8a86abcf376010943711455874306d547 100644 (file)
@@ -1 +1,2 @@
 SOURCES_gestures = modules/control/gestures.c
+SOURCES_http = modules/control/http.c
diff --git a/modules/control/http.c b/modules/control/http.c
new file mode 100644 (file)
index 0000000..be7df33
--- /dev/null
@@ -0,0 +1,431 @@
+/*****************************************************************************
+ * http.c :  http remote control plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: http.c,v 1.1 2003/04/26 21:36:23 gbazin Exp $
+ *
+ * Authors: Gildas Bazin <gbazin@netcourrier.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., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h>                                      /* malloc(), free() */
+#include <string.h>
+
+#include <errno.h>                                                 /* ENOMEM */
+#include <stdio.h>
+#include <ctype.h>
+#include <signal.h>
+
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+
+#ifdef HAVE_UNISTD_H
+#    include <unistd.h>
+#endif
+
+#ifdef HAVE_SYS_TIME_H
+#    include <sys/time.h>
+#endif
+#include <sys/types.h>
+
+#include "httpd.h"
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int  Activate     ( vlc_object_t * );
+static void Close        ( vlc_object_t * );
+static void Run          ( intf_thread_t *p_intf );
+
+static int  httpd_page_interface_get( httpd_file_callback_args_t *p_args,
+                                      uint8_t *p_request, int i_request,
+                                      uint8_t **pp_data, int *pi_data );
+
+/*****************************************************************************
+ * intf_sys_t: description and status of interface
+ *****************************************************************************/
+struct intf_sys_t
+{
+    httpd_t             *p_httpd;
+    httpd_host_t        *p_httpd_host;
+
+    input_thread_t *    p_input;
+};
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+#define PORT_TEXT N_( "http interface bind port" )
+#define PORT_LONGTEXT N_( \
+    "You can set the port on which the http interface will accept connections" )
+#define ADDR_TEXT N_( "http interface bind address" )
+#define ADDR_LONGTEXT N_( \
+    "You can set the address on which the http interface will bind" )
+
+vlc_module_begin();
+    add_category_hint( N_("HTTP remote control"), NULL, VLC_TRUE );
+    add_string( "http-addr", NULL, NULL, PORT_TEXT, PORT_LONGTEXT, VLC_TRUE );
+    add_integer( "http-port", 8080, NULL, ADDR_TEXT, ADDR_LONGTEXT, VLC_TRUE );
+    set_description( _("HTTP remote control interface") );
+    set_capability( "interface", 10 );
+    set_callbacks( Activate, Close );
+vlc_module_end();
+
+/*****************************************************************************
+ * Activate: initialize and create stuff
+ *****************************************************************************/
+static int Activate( vlc_object_t *p_this )
+{
+    intf_thread_t *p_intf = (intf_thread_t*)p_this;
+
+    /* Allocate instance and initialize some members */
+    p_intf->p_sys = malloc( sizeof( intf_sys_t ) );
+    if( p_intf->p_sys == NULL )
+    {
+        return VLC_EGENERIC;
+    };
+
+    p_intf->p_sys->p_httpd = NULL;
+    p_intf->p_sys->p_httpd_host = NULL;
+
+    p_intf->pf_run = Run;
+
+    CONSOLE_INTRO_MSG;
+
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * CloseIntf: destroy interface
+ *****************************************************************************/
+void Close ( vlc_object_t *p_this )
+{
+    intf_thread_t *p_intf = (intf_thread_t *)p_this;
+
+    if( p_intf->p_sys->p_httpd_host )
+        p_intf->p_sys->p_httpd->pf_unregister_host( p_intf->p_sys->p_httpd,
+                                                 p_intf->p_sys->p_httpd_host );
+
+    if( p_intf->p_sys->p_httpd )
+        httpd_Release( p_intf->p_sys->p_httpd );
+
+    /* Destroy structure */
+    free( p_intf->p_sys );
+}
+
+/*****************************************************************************
+ * Run: http interface thread
+ *****************************************************************************/
+static void Run( intf_thread_t *p_intf )
+{
+    input_thread_t *p_input = NULL;
+    playlist_t     *p_playlist = NULL;
+    httpd_file_t   *p_page_intf;
+
+#if 0
+    input_info_category_t * p_category;
+    input_info_t * p_info;
+
+    off_t      i_oldpos = 0;
+    off_t      i_newpos;
+    double     f_ratio = 1.0;
+#endif
+
+    /* Get bind address and port */
+    char *psz_bind_addr = config_GetPsz( p_intf, "http-addr" );
+    int i_bind_port = config_GetInt( p_intf, "http-port" );
+    if( !psz_bind_addr ) psz_bind_addr = strdup( "" );
+
+    p_intf->p_sys->p_httpd = httpd_Find( VLC_OBJECT(p_intf), VLC_TRUE );
+    if( !p_intf->p_sys->p_httpd )
+    {
+        msg_Err( p_intf, "cannot start httpd daemon" );
+        free( p_intf->p_sys );
+        return;
+    }
+
+    p_intf->p_sys->p_httpd_host =
+        p_intf->p_sys->p_httpd->pf_register_host( p_intf->p_sys->p_httpd,
+                                                  psz_bind_addr, i_bind_port );
+
+    if( !p_intf->p_sys->p_httpd_host )
+    {
+        msg_Err( p_intf, "cannot listen on %s:%d", psz_bind_addr, i_bind_port);
+        httpd_Release( p_intf->p_sys->p_httpd );
+        free( p_intf->p_sys );
+        return;
+    }
+
+    msg_Info( p_intf, "http interface started" );
+
+    /*
+     * Register our interface page with the httpd daemon
+     */
+    p_page_intf = p_intf->p_sys->p_httpd->pf_register_file(
+                      p_intf->p_sys->p_httpd, "/", "text/html",
+                      NULL, NULL, httpd_page_interface_get,
+                      NULL, (httpd_file_callback_args_t*)p_intf );
+
+    while( !p_intf->b_die )
+    {
+
+        /* Manage the input part */
+        if( p_input == NULL )
+        {
+            if( p_playlist )
+            {
+                p_input = vlc_object_find( p_playlist, VLC_OBJECT_INPUT,
+                                                       FIND_CHILD );
+            }
+            else
+            {
+                p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT,
+                                                   FIND_ANYWHERE );
+                if( p_input )
+                {
+                    p_playlist = vlc_object_find( p_input, VLC_OBJECT_PLAYLIST,
+                                                           FIND_PARENT );
+                }
+            }
+        }
+        else if( p_input->b_dead )
+        {
+            vlc_object_release( p_input );
+            p_input = NULL;
+        }
+
+        if( p_input )
+        {
+            /* Get position */
+            vlc_mutex_lock( &p_input->stream.stream_lock );
+            if( !p_input->b_die && p_input->stream.i_mux_rate )
+            {
+#if 0
+#define A p_input->stream.p_selected_area
+                f_ratio = 1.0 / ( 50 * p_input->stream.i_mux_rate );
+                i_newpos = A->i_tell * f_ratio;
+
+                if( i_oldpos != i_newpos )
+                {
+                    i_oldpos = i_newpos;
+                    printf( "pos: %li s / %li s\n", (long int)i_newpos,
+                            (long int)(f_ratio * A->i_size) );
+                }
+#undef S
+#endif
+            }
+            vlc_mutex_unlock( &p_input->stream.stream_lock );
+        }
+
+        /* Wait a bit */
+        msleep( INTF_IDLE_SLEEP );
+    }
+
+    p_intf->p_sys->p_httpd->pf_unregister_file( p_intf->p_sys->p_httpd,
+                                                p_page_intf );
+
+    if( p_input )
+    {
+        vlc_object_release( p_input );
+        p_input = NULL;
+    }
+
+    if( p_playlist )
+    {
+        vlc_object_release( p_playlist );
+        p_playlist = NULL;
+    }
+}
+
+/*****************************************************************************
+ * Local functions
+ *****************************************************************************/
+static int httpd_page_interface_update( intf_thread_t *p_intf,
+                                        playlist_t *p_playlist,
+                                        uint8_t **pp_data, int *pi_data );
+
+static void uri_extract_value( char *psz_uri, char *psz_name,
+                               char *psz_value, int i_value_max )
+{
+    char *p;
+
+    p = strstr( psz_uri, psz_name );
+    if( p )
+    {
+        int i_len;
+
+        p += strlen( psz_name );
+        if( *p == '=' ) p++;
+
+        if( strchr( p, '&' ) )
+        {
+            i_len = strchr( p, '&' ) - p;
+        }
+        else
+        {
+            i_len = strlen( p );
+        }
+        i_len = __MIN( i_value_max - 1, i_len );
+        if( i_len > 0 )
+        {
+            strncpy( psz_value, p, i_len );
+            psz_value[i_len] = '\0';
+        }
+        else
+        {
+            strncpy( psz_value, "", i_value_max );
+        }
+    }
+    else
+    {
+        strncpy( psz_value, "", i_value_max );
+    }
+}
+
+static int httpd_page_interface_get( httpd_file_callback_args_t *p_args,
+                                     uint8_t *p_request, int i_request,
+                                     uint8_t **pp_data, int *pi_data )
+{
+    intf_thread_t *p_intf = (intf_thread_t *)p_args;
+    playlist_t *p_playlist;
+    int i_ret;
+
+    p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
+    if( !p_playlist )
+    {
+        return VLC_EGENERIC;
+    }
+
+    if( i_request > 0)
+    {
+        char action[512];
+
+        uri_extract_value( p_request, "action", action, 512 );
+
+        if( !strcmp( action, "play" ) )
+        {
+            int i_item;
+            uri_extract_value( p_request, "item", action, 512 );
+            i_item = atol( action );
+            playlist_Command( p_playlist, PLAYLIST_GOTO, i_item );
+            msg_Dbg( p_intf, "requested playlist item: %i", i_item );
+        }
+        else if( !strcmp( action, "stop" ) )
+        {
+            playlist_Command( p_playlist, PLAYLIST_STOP, 0 );
+            msg_Dbg( p_intf, "requested playlist stop" );
+        }
+        else if( !strcmp( action, "pause" ) )
+        {
+            playlist_Command( p_playlist, PLAYLIST_PAUSE, 0 );
+            msg_Dbg( p_intf, "requested playlist pause" );
+        }
+        else if( !strcmp( action, "next" ) )
+        {
+            playlist_Command( p_playlist, PLAYLIST_GOTO,
+                              p_playlist->i_index + 1 );
+            msg_Dbg( p_intf, "requested playlist next" );
+        }
+        else if( !strcmp( action, "previous" ) )
+        {
+            playlist_Command( p_playlist, PLAYLIST_GOTO,
+                              p_playlist->i_index - 1 );
+            msg_Dbg( p_intf, "requested playlist previous" );
+        }
+        else if( !strcmp( action, "add" ) )
+        {
+            uri_extract_value( p_request, "mrl", action, 512 );
+            playlist_Add( p_playlist, action,
+                          PLAYLIST_APPEND, PLAYLIST_END );
+            msg_Dbg( p_intf, "requested playlist add: %s", action );
+        }
+    }
+
+    i_ret = httpd_page_interface_update( p_intf, p_playlist, pp_data, pi_data);
+
+    vlc_object_release( p_playlist );
+
+    return i_ret;
+}
+
+static int httpd_page_interface_update( intf_thread_t *p_intf,
+                                        playlist_t *p_playlist,
+                                        uint8_t **pp_data, int *pi_data )
+{
+    int i;
+    char *p;
+
+    p = *pp_data = malloc( 10240 );
+
+    p += sprintf( p, "<html>\n" );
+    p += sprintf( p, "<head>\n" );
+    p += sprintf( p, "<title>VLC Media Player</title>\n" );
+    p += sprintf( p, "</head>\n" );
+    p += sprintf( p, "<body>\n" );
+    p += sprintf( p, "<h2><center><a href=\"http://www.videolan.org\">"
+                     "VLC Media Player</a> (http interface)</center></h2>\n" );
+
+    /*
+     * Display the controls
+     */
+    p += sprintf( p, "<hr />\n" );
+
+    p += sprintf( p, "<td><form method=\"get\" action=\"\">"
+        "<input type=\"submit\" name=\"action\" value=\"stop\" />"
+        "<input type=\"submit\" name=\"action\" value=\"pause\" />"
+        "<input type=\"submit\" name=\"action\" value=\"previous\" />"
+        "<input type=\"submit\" name=\"action\" value=\"next\" />"
+        "</form></td><br />\n" );
+
+    p += sprintf( p, "<td><form method=\"get\" action=\"\" "
+                     "enctype=\"text/plain\" >"
+        "Media Resource Locator: "
+        "<input type=\"text\" name=\"mrl\" size=\"40\" />"
+        "<input type=\"submit\" name=\"action\" value=\"add\" />"
+        "</form></td>\n" );
+
+    p += sprintf( p, "<hr />\n" );
+
+    /*
+     * Display the playlist items
+     */
+    for ( i = 0; i < p_playlist->i_size; i++ )
+    {
+        if( i == p_playlist->i_index ) p += sprintf( p, "<b>" );
+
+        p += sprintf( p, "<a href=?action=play&item=%i>", i );
+        p += sprintf( p, "%i - %s", i,
+                      p_playlist->pp_items[i]->psz_name );
+        p += sprintf( p, "</a>" );
+
+        if( i == p_playlist->i_index ) p += sprintf( p, "</b>" );
+        p += sprintf( p, "<br />\n" );
+    }
+    if ( i == 0 )
+    {
+        p += sprintf( p, "no entries\n" );
+    }
+
+    p += sprintf( p, "</body>\n" );
+    p += sprintf( p, "</html>\n" );
+
+    *pi_data = strlen( *pp_data ) + 1;
+
+    return VLC_SUCCESS;
+}