예제 #1
0
파일: net.c 프로젝트: DakaiTV/DakaiVLC
static int vlclua_net_accept( lua_State *L )
{
    vlc_object_t *p_this = vlclua_get_this( L );
    int **ppi_fd = (int**)luaL_checkudata( L, 1, "net_listen" );
    int i_fd = net_Accept( p_this, *ppi_fd );

    lua_pushinteger( L, vlclua_fd_map_safe( L, i_fd ) );
    return 1;
}
예제 #2
0
파일: rtci.c 프로젝트: forthyen/SDesk
/*****************************************************************************
 * 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;
    }
}
예제 #3
0
파일: rtmp.c 프로젝트: banketree/faplayer
/*****************************************************************************
 * Open: open the rtmp connection
 *****************************************************************************/
static int Open( vlc_object_t *p_this )
{
    sout_access_out_t *p_access = (sout_access_out_t *) p_this;
    sout_access_out_sys_t *p_sys;
    char *psz, *p;
    int length_path, length_media_name;
    int i;

    if( !( p_sys = calloc ( 1, sizeof( sout_access_out_sys_t ) ) ) )
        return VLC_ENOMEM;
    p_access->p_sys = p_sys;

    p_sys->p_thread =
        vlc_object_create( p_access, sizeof( rtmp_control_thread_t ) );
    if( !p_sys->p_thread )
    {
        free( p_sys );
        return VLC_ENOMEM;
    }
    vlc_object_attach( p_sys->p_thread, p_access );

    /* Parse URI - remove spaces */
    p = psz = strdup( p_access->psz_path );
    while( ( p = strchr( p, ' ' ) ) != NULL )
        *p = '+';
    vlc_UrlParse( &p_sys->p_thread->url, psz, 0 );
    free( psz );

    if( p_sys->p_thread->url.psz_host == NULL
        || *p_sys->p_thread->url.psz_host == '\0' )
    {
         msg_Warn( p_access, "invalid host" );
         goto error;
    }

    if( p_sys->p_thread->url.i_port <= 0 )
        p_sys->p_thread->url.i_port = 1935;

    if ( p_sys->p_thread->url.psz_path == NULL )
    {
        msg_Warn( p_access, "invalid path" );
        goto error;
    }

    length_path = strlen( p_sys->p_thread->url.psz_path );
    char* psz_tmp = strrchr( p_sys->p_thread->url.psz_path, '/' );
    if( !psz_tmp )
        goto error;
    length_media_name = strlen( psz_tmp ) - 1;

    p_sys->p_thread->psz_application = strndup( p_sys->p_thread->url.psz_path + 1, length_path - length_media_name - 2 );
    p_sys->p_thread->psz_media = strdup( p_sys->p_thread->url.psz_path + ( length_path - length_media_name ) );

    msg_Dbg( p_access, "rtmp: host='%s' port=%d path='%s'",
             p_sys->p_thread->url.psz_host, p_sys->p_thread->url.i_port, p_sys->p_thread->url.psz_path );

    if( p_sys->p_thread->url.psz_username && *p_sys->p_thread->url.psz_username )
    {
        msg_Dbg( p_access, "      user='******'", p_sys->p_thread->url.psz_username );
    }

    /* Initialize thread variables */
    p_sys->p_thread->b_error= 0;
    p_sys->p_thread->p_fifo_input = block_FifoNew();
    p_sys->p_thread->p_empty_blocks = block_FifoNew();
    p_sys->p_thread->has_audio = 0;
    p_sys->p_thread->has_video = 0;
    p_sys->p_thread->metadata_received = 0;
    p_sys->p_thread->first_media_packet = 1;
    p_sys->p_thread->flv_tag_previous_tag_size = 0x00000000; /* FLV_TAG_FIRST_PREVIOUS_TAG_SIZE */

    p_sys->p_thread->flv_body = rtmp_body_new( -1 );
    p_sys->p_thread->flv_length_body = 0;

    p_sys->p_thread->chunk_size_recv = 128; /* RTMP_DEFAULT_CHUNK_SIZE */
    p_sys->p_thread->chunk_size_send = 128; /* RTMP_DEFAULT_CHUNK_SIZE */
    for(i = 0; i < 64; i++)
    {
        memset( &p_sys->p_thread->rtmp_headers_recv[i], 0, sizeof( rtmp_packet_t ) );
        p_sys->p_thread->rtmp_headers_send[i].length_header = -1;
        p_sys->p_thread->rtmp_headers_send[i].stream_index = -1;
        p_sys->p_thread->rtmp_headers_send[i].timestamp = -1;
        p_sys->p_thread->rtmp_headers_send[i].timestamp_relative = -1;
        p_sys->p_thread->rtmp_headers_send[i].length_encoded = -1;
        p_sys->p_thread->rtmp_headers_send[i].length_body = -1;
        p_sys->p_thread->rtmp_headers_send[i].content_type = -1;
        p_sys->p_thread->rtmp_headers_send[i].src_dst = -1;
        p_sys->p_thread->rtmp_headers_send[i].body = NULL;
    }

    vlc_cond_init( &p_sys->p_thread->wait );
    vlc_mutex_init( &p_sys->p_thread->lock );

    p_sys->p_thread->result_connect = 1;
    /* p_sys->p_thread->result_publish = only used on access */
    p_sys->p_thread->result_play = 1;
    p_sys->p_thread->result_stop = 0;
    p_sys->p_thread->fd = -1;

    /* Open connection */
    if( var_CreateGetBool( p_access, "rtmp-connect" ) > 0 )
    {
#if 0
        p_sys->p_thread->fd = net_ConnectTCP( p_access,
                                              p_sys->p_thread->url.psz_host,
                                              p_sys->p_thread->url.i_port );
#endif
        msg_Err( p_access, "to be implemented" );
        goto error2;
    }
    else
    {
        int *p_fd_listen;

        p_sys->active = 0;
        p_fd_listen = net_ListenTCP( p_access, p_sys->p_thread->url.psz_host,
                                     p_sys->p_thread->url.i_port );
        if( p_fd_listen == NULL )
        {
            msg_Warn( p_access, "cannot listen to %s port %i",
                      p_sys->p_thread->url.psz_host,
                      p_sys->p_thread->url.i_port );
            goto error2;
        }

        do
            p_sys->p_thread->fd = net_Accept( p_access, p_fd_listen );
        while( p_sys->p_thread->fd == -1 );
        net_ListenClose( p_fd_listen );

        if( rtmp_handshake_passive( p_this, p_sys->p_thread->fd ) < 0 )
        {
            msg_Err( p_access, "handshake passive failed");
            goto error2;
        }
    }

    if( vlc_clone( &p_sys->p_thread->thread, ThreadControl, p_sys->p_thread,
                   VLC_THREAD_PRIORITY_INPUT ) )
    {
        msg_Err( p_access, "cannot spawn rtmp control thread" );
        goto error2;
    }

    if( !p_sys->active )
    {
        if( rtmp_connect_passive( p_sys->p_thread ) < 0 )
        {
            msg_Err( p_access, "connect passive failed");
            vlc_cancel( p_sys->p_thread->thread );
            vlc_join( p_sys->p_thread->thread, NULL );
            goto error2;
        }
    }

    p_access->pf_write = Write;
    p_access->pf_seek = Seek;

    return VLC_SUCCESS;

error2:
    vlc_cond_destroy( &p_sys->p_thread->wait );
    vlc_mutex_destroy( &p_sys->p_thread->lock );

    free( p_sys->p_thread->psz_application );
    free( p_sys->p_thread->psz_media );

    if( p_sys->p_thread->fd != -1 )
        net_Close( p_sys->p_thread->fd );
error:
    vlc_UrlClean( &p_sys->p_thread->url );
    vlc_object_release( p_sys->p_thread );
    free( p_sys );

    return VLC_EGENERIC;
}
예제 #4
0
/*****************************************************************************
 * Run: main loop
 *****************************************************************************/
static void Run( intf_thread_t *p_intf )
{
    intf_sys_t     *p_sys = p_intf->p_sys;
    struct timeval  timeout;
    char           *psz_password;

    psz_password = config_GetPsz( p_intf, "telnet-password" );

    while( !p_intf->b_die )
    {
        fd_set fds_read, fds_write;
        int    i_handle_max = 0;
        int    i_ret, i_len, fd, i;

        /* if a new client wants to communicate */
        fd = net_Accept( p_intf, p_sys->pi_fd, p_sys->i_clients > 0 ? 0 : -1 );
        if( fd > 0 )
        {
            telnet_client_t *cl;

            /* to be non blocking */
#if defined( WIN32 ) || defined( UNDER_CE )
            {
                unsigned long i_dummy = 1;
                ioctlsocket( fd, FIONBIO, &i_dummy );
            }
#else
            fcntl( fd, F_SETFL, O_NONBLOCK );
#endif
            cl = malloc( sizeof( telnet_client_t ));
            cl->i_tel_cmd = 0;
            cl->fd = fd;
            cl->buffer_write = NULL;
            cl->p_buffer_write = cl->buffer_write;
            Write_message( cl, NULL, "Password: \xff\xfb\x01", WRITE_MODE_PWD );

            TAB_APPEND( p_sys->i_clients, p_sys->clients, cl );
        }

        /* to do a proper select */
        FD_ZERO( &fds_read );
        FD_ZERO( &fds_write );

        for( i = 0 ; i < p_sys->i_clients ; i++ )
        {
            telnet_client_t *cl = p_sys->clients[i];

            if( cl->i_mode == WRITE_MODE_PWD || cl->i_mode == WRITE_MODE_CMD )
            {
                FD_SET( cl->fd , &fds_write );
            }
            else
            {
                FD_SET( cl->fd , &fds_read );
            }
            i_handle_max = __MAX( i_handle_max, cl->fd );
        }

        timeout.tv_sec = 0;
        timeout.tv_usec = 500*1000;

        i_ret = select( i_handle_max + 1, &fds_read, &fds_write, 0, &timeout );
        if( i_ret == -1 && errno != EINTR )
        {
            msg_Warn( p_intf, "cannot select sockets" );
            msleep( 1000 );
            continue;
        }
        else if( i_ret <= 0 )
        {
            continue;
        }

        /* check if there is something to do with the socket */
        for( i = 0 ; i < p_sys->i_clients ; i++ )
        {
            telnet_client_t *cl = p_sys->clients[i];

            if( FD_ISSET(cl->fd , &fds_write) && cl->i_buffer_write > 0 )
            {
                i_len = send( cl->fd , cl->p_buffer_write ,
                              cl->i_buffer_write , 0 );
                if( i_len > 0 )
                {
                    cl->p_buffer_write += i_len;
                    cl->i_buffer_write -= i_len;
                }
            }
            else if( FD_ISSET( cl->fd, &fds_read) )
            {
                int i_end = 0;
                int i_recv;

                while( (i_recv=recv( cl->fd, cl->p_buffer_read, 1, 0 )) > 0 &&
                       cl->p_buffer_read - cl->buffer_read < 999 )
                {
                    switch( cl->i_tel_cmd )
                    {
                    case 0:
                        switch( *(uint8_t *)cl->p_buffer_read )
                        {
                        case '\r':
                            break;
                        case '\n':
                            *cl->p_buffer_read = '\n';
                            i_end = 1;
                            break;
                        case TEL_IAC: // telnet specific command
                            cl->i_tel_cmd = 1;
                            cl->p_buffer_read++;
                            break;
                        default:
                            cl->p_buffer_read++;
                            break;
                        }
                        break;
                    case 1:
                        switch( *(uint8_t *)cl->p_buffer_read )
                        {
                        case TEL_WILL: case TEL_WONT:
                        case TEL_DO: case TEL_DONT:
                            cl->i_tel_cmd++;
                            cl->p_buffer_read++;
                            break;
                        default:
                            cl->i_tel_cmd = 0;
                            cl->p_buffer_read--;
                            break;
                        }
                        break;
                    case 2:
                        cl->i_tel_cmd = 0;
                        cl->p_buffer_read -= 2;
                        break;
                    }

                    if( i_end != 0 ) break;
                }

                if( cl->p_buffer_read - cl->buffer_read == 999 )
                {
                    Write_message( cl, NULL, "Line too long\r\n",
                                   cl->i_mode + 2 );
                }

                if( i_recv == 0  || ( i_recv == -1 &&  errno != EAGAIN && errno != 0 ) )
                {
                    net_Close( cl->fd );
                    TAB_REMOVE( p_intf->p_sys->i_clients ,
                                p_intf->p_sys->clients , cl );
                    free( cl );
                }
            }
        }

        /* and now we should bidouille the data we received / send */
        for( i = 0 ; i < p_sys->i_clients ; i++ )
        {
            telnet_client_t *cl = p_sys->clients[i];

            if( cl->i_mode >= WRITE_MODE_PWD && cl->i_buffer_write == 0 )
            {
               // we have finished to send
               cl->i_mode -= 2; // corresponding READ MODE
            }
            else if( cl->i_mode == READ_MODE_PWD &&
                     *cl->p_buffer_read == '\n' )
            {
                *cl->p_buffer_read = '\0';
                if( strcmp( psz_password, cl->buffer_read ) == 0 )
                {
                    Write_message( cl, NULL, "\xff\xfc\x01\r\nWelcome, "
                                   "Master\r\n> ", WRITE_MODE_CMD );
                }
                else
                {
                    /* wrong password */
                    Write_message( cl, NULL,
                                   "\r\nWrong password.\r\nPassword: "******"logout", 6 ) ||
                    !strncmp( cl->buffer_read, "quit", 4 )  ||
                    !strncmp( cl->buffer_read, "exit", 4 ) )
                {
                    net_Close( cl->fd );
                    TAB_REMOVE( p_intf->p_sys->i_clients ,
                                p_intf->p_sys->clients , cl );
                    free( cl );
                }
                else if( !strncmp( cl->buffer_read, "shutdown", 8 ) )
                {
                    msg_Err( p_intf, "shutdown requested" );
                    p_intf->p_vlc->b_die = VLC_TRUE;
                }
                else
                {
                    vlm_message_t *message;

                    /* create a standard string */
                    *cl->p_buffer_read = '\0';

                    vlm_ExecuteCommand( p_sys->mediatheque, cl->buffer_read,
                                        &message );
                    Write_message( cl, message, NULL, WRITE_MODE_CMD );
                    vlm_MessageDelete( message );
                }
            }
        }
    }
}