mirror of https://code.videolan.org/videolan/vlc
* modules/control/http.c: brand new (and also basic) HTTP interface plugin for vlc (uses port 8080 by default).
This commit is contained in:
parent
1c04b2adf9
commit
ee2bc403e0
|
@ -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
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
SOURCES_gestures = modules/control/gestures.c
|
||||
SOURCES_http = modules/control/http.c
|
||||
|
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue