/********************************************************************** * Execute a var command on an object identified by its name **********************************************************************/ int var_Command( vlc_object_t *p_this, const char *psz_name, const char *psz_cmd, const char *psz_arg, char **psz_msg ) { vlc_object_t *p_obj = vlc_object_find_name( p_this->p_libvlc, psz_name ); int i_type, i_ret; if( !p_obj ) { if( psz_msg ) *psz_msg = strdup( "Unknown destination object." ); return VLC_ENOOBJ; } i_type = var_Type( p_obj, psz_cmd ); if( !( i_type&VLC_VAR_ISCOMMAND ) ) { vlc_object_release( p_obj ); if( psz_msg ) *psz_msg = strdup( "Variable doesn't exist or isn't a command." ); return VLC_EGENERIC; } i_type &= VLC_VAR_CLASS; switch( i_type ) { case VLC_VAR_INTEGER: i_ret = var_SetInteger( p_obj, psz_cmd, atoi( psz_arg ) ); break; case VLC_VAR_FLOAT: i_ret = var_SetFloat( p_obj, psz_cmd, us_atof( psz_arg ) ); break; case VLC_VAR_STRING: i_ret = var_SetString( p_obj, psz_cmd, psz_arg ); break; case VLC_VAR_BOOL: i_ret = var_SetBool( p_obj, psz_cmd, atoi( psz_arg ) ); break; default: i_ret = VLC_EGENERIC; break; } vlc_object_release( p_obj ); if( psz_msg ) { if( asprintf( psz_msg, "%s on object %s returned %i (%s)", psz_cmd, psz_name, i_ret, vlc_error( i_ret ) ) == -1) *psz_msg = NULL; } return i_ret; }
/***************************************************************************** * Run: rtci thread ***************************************************************************** * This part of the interface is in a separate thread so that we can call * exec() from within it without annoying the rest of the program. *****************************************************************************/ static void Run( intf_thread_t *p_intf ) { input_thread_t * p_input; playlist_t * p_playlist; char p_buffer[ MAX_LINE_LENGTH + 1 ]; vlc_bool_t b_showpos = config_GetInt( p_intf, "rtci-show-pos" ); int i_size = 0; int i_oldpos = 0; int i_newpos; p_buffer[0] = 0; p_input = NULL; p_playlist = NULL; p_intf->p_sys->b_extend = config_GetInt( p_intf, "rtci-extend" ); /* Register commands that will be cleaned up upon object destruction */ var_Create( p_intf, "quit", VLC_VAR_VOID | VLC_VAR_ISCOMMAND ); var_AddCallback( p_intf, "quit", Quit, NULL ); var_Create( p_intf, "intf", VLC_VAR_STRING | VLC_VAR_ISCOMMAND ); var_AddCallback( p_intf, "intf", Intf, NULL ); var_Create( p_intf, "add", VLC_VAR_STRING | VLC_VAR_ISCOMMAND ); var_AddCallback( p_intf, "add", Playlist, NULL ); var_Create( p_intf, "playlist", VLC_VAR_VOID | VLC_VAR_ISCOMMAND ); var_AddCallback( p_intf, "playlist", Playlist, NULL ); var_Create( p_intf, "play", VLC_VAR_VOID | VLC_VAR_ISCOMMAND ); var_AddCallback( p_intf, "play", Playlist, NULL ); var_Create( p_intf, "stop", VLC_VAR_VOID | VLC_VAR_ISCOMMAND ); var_AddCallback( p_intf, "stop", Playlist, NULL ); var_Create( p_intf, "prev", VLC_VAR_VOID | VLC_VAR_ISCOMMAND ); var_AddCallback( p_intf, "prev", Playlist, NULL ); var_Create( p_intf, "next", VLC_VAR_VOID | VLC_VAR_ISCOMMAND ); var_AddCallback( p_intf, "next", Playlist, NULL ); var_Create( p_intf, "marq-marquee", VLC_VAR_VOID | VLC_VAR_ISCOMMAND ); var_AddCallback( p_intf, "marq-marquee", Other, NULL ); var_Create( p_intf, "marq-x", VLC_VAR_INTEGER | VLC_VAR_ISCOMMAND ); var_AddCallback( p_intf, "marq-x", Other, NULL ); var_Create( p_intf, "marq-y", VLC_VAR_INTEGER | VLC_VAR_ISCOMMAND ); var_AddCallback( p_intf, "marq-y", Other, NULL ); var_Create( p_intf, "marq-timeout", VLC_VAR_INTEGER | VLC_VAR_ISCOMMAND ); var_AddCallback( p_intf, "marq-timeout", Other, NULL ); var_Create( p_intf, "pause", VLC_VAR_VOID | VLC_VAR_ISCOMMAND ); var_AddCallback( p_intf, "pause", Input, NULL ); var_Create( p_intf, "seek", VLC_VAR_INTEGER | VLC_VAR_ISCOMMAND ); var_AddCallback( p_intf, "seek", Input, NULL ); var_Create( p_intf, "title", VLC_VAR_STRING | VLC_VAR_ISCOMMAND ); var_AddCallback( p_intf, "title", Input, NULL ); var_Create( p_intf, "title_n", VLC_VAR_VOID | VLC_VAR_ISCOMMAND ); var_AddCallback( p_intf, "title_n", Input, NULL ); var_Create( p_intf, "title_p", VLC_VAR_VOID | VLC_VAR_ISCOMMAND ); var_AddCallback( p_intf, "title_p", Input, NULL ); var_Create( p_intf, "chapter", VLC_VAR_STRING | VLC_VAR_ISCOMMAND ); var_AddCallback( p_intf, "chapter", Input, NULL ); var_Create( p_intf, "chapter_n", VLC_VAR_VOID | VLC_VAR_ISCOMMAND ); var_AddCallback( p_intf, "chapter_n", Input, NULL ); var_Create( p_intf, "chapter_p", VLC_VAR_VOID | VLC_VAR_ISCOMMAND ); var_AddCallback( p_intf, "chapter_p", Input, NULL ); var_Create( p_intf, "volume", VLC_VAR_STRING | VLC_VAR_ISCOMMAND ); var_AddCallback( p_intf, "volume", Volume, NULL ); var_Create( p_intf, "volup", VLC_VAR_STRING | VLC_VAR_ISCOMMAND ); var_AddCallback( p_intf, "volup", VolumeMove, NULL ); var_Create( p_intf, "voldown", VLC_VAR_STRING | VLC_VAR_ISCOMMAND ); var_AddCallback( p_intf, "voldown", VolumeMove, NULL ); var_Create( p_intf, "adev", VLC_VAR_STRING | VLC_VAR_ISCOMMAND ); var_AddCallback( p_intf, "adev", AudioConfig, NULL ); var_Create( p_intf, "achan", VLC_VAR_STRING | VLC_VAR_ISCOMMAND ); var_AddCallback( p_intf, "achan", AudioConfig, NULL ); #ifdef WIN32 /* Get the file descriptor of the console input */ p_intf->p_sys->hConsoleIn = GetStdHandle(STD_INPUT_HANDLE); if( p_intf->p_sys->hConsoleIn == INVALID_HANDLE_VALUE ) { msg_Err( p_intf, "Couldn't open STD_INPUT_HANDLE" ); p_intf->b_die = VLC_TRUE; } #endif while( !p_intf->b_die ) { char *psz_cmd, *psz_arg; vlc_bool_t b_complete; if( p_intf->p_sys->i_socket_listen != - 1 && p_intf->p_sys->i_socket == -1 ) { p_intf->p_sys->i_socket = net_Accept( p_intf, p_intf->p_sys->i_socket_listen, 0 ); } b_complete = ReadCommand( p_intf, p_buffer, &i_size ); /* 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 && b_showpos ) { i_newpos = 100 * var_GetFloat( p_input, "position" ); if( i_oldpos != i_newpos ) { i_oldpos = i_newpos; msg_rtci( "pos: %d%%\n", i_newpos ); } } /* Is there something to do? */ if( !b_complete ) continue; /* Skip heading spaces */ psz_cmd = p_buffer; while( *psz_cmd == ' ' ) { psz_cmd++; } /* Split psz_cmd at the first space and make sure that * psz_arg is valid */ psz_arg = strchr( psz_cmd, ' ' ); if( psz_arg ) { *psz_arg++ = 0; while( *psz_arg == ' ' ) { psz_arg++; } } else { psz_arg = ""; } /* If the user typed a registered local command, try it */ if( var_Type( p_intf, psz_cmd ) & VLC_VAR_ISCOMMAND ) { vlc_value_t val; int i_ret; val.psz_string = psz_arg; i_ret = var_Set( p_intf, psz_cmd, val ); msg_rtci( "%s: returned %i (%s)\n", psz_cmd, i_ret, vlc_error( i_ret ) ); } /* Or maybe it's a global command */ else if( var_Type( p_intf->p_libvlc, psz_cmd ) & VLC_VAR_ISCOMMAND ) { vlc_value_t val; int i_ret; val.psz_string = psz_arg; /* FIXME: it's a global command, but we should pass the * local object as an argument, not p_intf->p_libvlc. */ i_ret = var_Set( p_intf->p_libvlc, psz_cmd, val ); if( i_ret != 0 ) { msg_rtci( "%s: returned %i (%s)\n", psz_cmd, i_ret, vlc_error( i_ret ) ); } } else if( !strcmp( psz_cmd, "logout" ) ) { /* Close connection */ if( p_intf->p_sys->i_socket != -1 ) { net_Close( p_intf->p_sys->i_socket ); } p_intf->p_sys->i_socket = -1; } else if( !strcmp( psz_cmd, "info" ) ) { if( p_input ) { int i, j; vlc_mutex_lock( &p_input->input.p_item->lock ); for ( i = 0; i < p_input->input.p_item->i_categories; i++ ) { info_category_t *p_category = p_input->input.p_item->pp_categories[i]; msg_rtci( "+----[ %s ]\n", p_category->psz_name ); msg_rtci( "| \n" ); for ( j = 0; j < p_category->i_infos; j++ ) { info_t *p_info = p_category->pp_infos[j]; msg_rtci( "| %s: %s\n", p_info->psz_name, p_info->psz_value ); } msg_rtci( "| \n" ); } msg_rtci( "+----[ end of stream info ]\n" ); vlc_mutex_unlock( &p_input->input.p_item->lock ); } else { msg_rtci( "no input\n" ); } } else if( !strcmp( psz_cmd, "is_playing" ) ) { if( ! p_input ) { msg_rtci( "0\n" ); } else { msg_rtci( "1\n" ); } } else if( !strcmp( psz_cmd, "get_time" ) ) { if( ! p_input ) { msg_rtci("0\n"); } else { vlc_value_t time; var_Get( p_input, "time", &time ); msg_rtci( "%i\n", time.i_time / 1000000); } } else if( !strcmp( psz_cmd, "get_length" ) ) { if( ! p_input ) { msg_rtci("0\n"); } else { vlc_value_t time; var_Get( p_input, "length", &time ); msg_rtci( "%i\n", time.i_time / 1000000); } } else if( !strcmp( psz_cmd, "get_title" ) ) { if( ! p_input ) { msg_rtci("\n"); } else { msg_rtci( "%s\n", p_input->input.p_item->psz_name ); } } else switch( psz_cmd[0] ) { case 'f': case 'F': if( p_input ) { vout_thread_t *p_vout; p_vout = vlc_object_find( p_input, VLC_OBJECT_VOUT, FIND_CHILD ); if( p_vout ) { p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE; vlc_object_release( p_vout ); } } break; case 's': case 'S': ; break; case '?': case 'h': case 'H': msg_rtci(_("+----[ Remote control commands ]\n")); msg_rtci("| \n"); msg_rtci(_("| add XYZ . . . . . . . . . . add XYZ to playlist\n")); msg_rtci(_("| playlist . . . show items currently in playlist\n")); msg_rtci(_("| play . . . . . . . . . . . . . . . . play stream\n")); msg_rtci(_("| stop . . . . . . . . . . . . . . . . stop stream\n")); msg_rtci(_("| next . . . . . . . . . . . . next playlist item\n")); msg_rtci(_("| prev . . . . . . . . . . previous playlist item\n")); msg_rtci(_("| title [X] . . . . set/get title in current item\n")); msg_rtci(_("| title_n . . . . . . next title in current item\n")); msg_rtci(_("| title_p . . . . previous title in current item\n")); msg_rtci(_("| chapter [X] . . set/get chapter in current item\n")); msg_rtci(_("| chapter_n . . . . next chapter in current item\n")); msg_rtci(_("| chapter_p . . previous chapter in current item\n")); msg_rtci("| \n"); msg_rtci(_("| seek X . seek in seconds, for instance `seek 12'\n")); msg_rtci(_("| pause . . . . . . . . . . . . . . toggle pause\n")); msg_rtci(_("| f . . . . . . . . . . . . . . toggle fullscreen\n")); msg_rtci(_("| info . . . information about the current stream\n")); msg_rtci("| \n"); msg_rtci(_("| volume [X] . . . . . . . . set/get audio volume\n")); msg_rtci(_("| volup [X] . . . . . raise audio volume X steps\n")); msg_rtci(_("| voldown [X] . . . . lower audio volume X steps\n")); msg_rtci(_("| adev [X] . . . . . . . . . set/get audio device\n")); msg_rtci(_("| achan [X]. . . . . . . . set/get audio channels\n")); msg_rtci("| \n"); if (p_intf->p_sys->b_extend) { msg_rtci(_("| marq-marquee STRING . . overlay STRING in video\n")); msg_rtci(_("| marq-x X . . . . . .offset of marquee, from left\n")); msg_rtci(_("| marq-y Y . . . . . . offset of marquee, from top\n")); msg_rtci(_("| marq-timeout T. . . . .timeout of marquee, in ms\n")); msg_rtci("| \n"); } msg_rtci(_("| help . . . . . . . . . . . . . this help message\n")); msg_rtci(_("| logout . . . . . .exit (if in socket connection)\n")); msg_rtci(_("| quit . . . . . . . . . . . . . . . . . quit vlc\n")); msg_rtci("| \n"); msg_rtci(_("+----[ end of help ]\n")); break; case '\0': /* Ignore empty lines */ break; default: msg_rtci(_("unknown command `%s', type `help' for help\n"), psz_cmd); break; } /* Command processed */ i_size = 0; p_buffer[0] = 0; } if( p_input ) { vlc_object_release( p_input ); p_input = NULL; } if( p_playlist ) { vlc_object_release( p_playlist ); p_playlist = NULL; } }
/***************************************************************************** * VLC error code translation *****************************************************************************/ int vlclua_push_ret( lua_State *L, int i_error ) { lua_pushnumber( L, i_error ); lua_pushstring( L, vlc_error( i_error ) ); return 2; }