/** * Delete an update_t struct * * \param p_update update_t* pointer * \return nothing */ void update_Delete( update_t *p_update ) { assert( p_update ); if( p_update->p_check ) { vlc_object_kill( p_update->p_check ); vlc_thread_join( p_update->p_check ); vlc_object_release( p_update->p_check ); } if( p_update->p_download ) { vlc_object_kill( p_update->p_download ); vlc_thread_join( p_update->p_download ); vlc_object_release( p_update->p_download ); } vlc_mutex_destroy( &p_update->lock ); free( p_update->release.psz_url ); free( p_update->release.psz_desc ); free( p_update->p_pkey ); free( p_update ); }
/** * Stops and destroys all interfaces * @param p_libvlc the LibVLC instance */ void intf_DestroyAll( libvlc_int_t *p_libvlc ) { intf_thread_t *p_first; vlc_mutex_lock( &lock ); p_first = libvlc_priv( p_libvlc )->p_intf; #ifndef NDEBUG libvlc_priv( p_libvlc )->p_intf = NULL; #endif vlc_mutex_unlock( &lock ); /* Tell the interfaces to die */ for( intf_thread_t *p_intf = p_first; p_intf; p_intf = p_intf->p_next ) vlc_object_kill( p_intf ); /* Cleanup the interfaces */ for( intf_thread_t *p_intf = p_first; p_intf != NULL; ) { intf_thread_t *p_next = p_intf->p_next; if( p_intf->pf_run ) { vlc_cancel( p_intf->thread ); vlc_join( p_intf->thread, NULL ); } module_unneed( p_intf, p_intf->p_module ); config_ChainDestroy( p_intf->p_cfg ); vlc_object_release( p_intf ); p_intf = p_next; } }
void transcode_video_close( sout_stream_t *p_stream, sout_stream_id_t *id ) { if( p_stream->p_sys->i_threads >= 1 ) { vlc_mutex_lock( &p_stream->p_sys->lock_out ); vlc_object_kill( p_stream->p_sys ); vlc_cond_signal( &p_stream->p_sys->cond ); vlc_mutex_unlock( &p_stream->p_sys->lock_out ); vlc_thread_join( p_stream->p_sys ); vlc_mutex_destroy( &p_stream->p_sys->lock_out ); vlc_cond_destroy( &p_stream->p_sys->cond ); } video_timer_close( id->p_encoder ); /* Close decoder */ if( id->p_decoder->p_module ) module_unneed( id->p_decoder, id->p_decoder->p_module ); if( id->p_decoder->p_description ) vlc_meta_Delete( id->p_decoder->p_description ); free( id->p_decoder->p_owner ); /* Close encoder */ if( id->p_encoder->p_module ) module_unneed( id->p_encoder, id->p_encoder->p_module ); /* Close filters */ if( id->p_f_chain ) filter_chain_Delete( id->p_f_chain ); if( id->p_uf_chain ) filter_chain_Delete( id->p_uf_chain ); }
/***************************************************************************** * Close: close the plugin *****************************************************************************/ static void Close( vlc_object_t *p_this ) { filter_t *p_filter = (filter_t *)p_this; filter_sys_t *p_sys = p_filter->p_sys; /* Stop Goom Thread */ vlc_object_kill( p_sys->p_thread ); vlc_mutex_lock( &p_sys->p_thread->lock ); vlc_cond_signal( &p_sys->p_thread->wait ); vlc_mutex_unlock( &p_sys->p_thread->lock ); vlc_thread_join( p_sys->p_thread ); /* Free data */ aout_filter_RequestVout( p_filter, p_sys->p_thread->p_vout, 0 ); vlc_mutex_destroy( &p_sys->p_thread->lock ); vlc_cond_destroy( &p_sys->p_thread->wait ); while( p_sys->p_thread->i_blocks-- ) { block_Release( p_sys->p_thread->pp_blocks[p_sys->p_thread->i_blocks] ); } vlc_object_release( p_sys->p_thread ); free( p_sys ); }
/** **************************************************************************** * Destroy a vlc object (Internal) * * This function destroys an object that has been previously allocated with * vlc_object_create. The object's refcount must be zero and it must not be * attached to other objects in any way. * * This function must be called with cancellation disabled (currently). *****************************************************************************/ static void vlc_object_destroy( vlc_object_t *p_this ) { vlc_object_internals_t *p_priv = vlc_internals( p_this ); /* Send a kill to the object's thread if applicable */ vlc_object_kill( p_this ); /* Call the custom "subclass" destructor */ if( p_priv->pf_destructor ) p_priv->pf_destructor( p_this ); /* Any thread must have been cleaned up at this point. */ assert( !p_priv->b_thread ); /* Destroy the associated variables. */ var_DestroyAll( p_this ); vlc_cond_destroy( &p_priv->var_wait ); vlc_mutex_destroy( &p_priv->var_lock ); free( p_this->psz_header ); free( p_priv->psz_name ); vlc_spin_destroy( &p_priv->ref_spin ); if( p_priv->pipes[1] != -1 && p_priv->pipes[1] != p_priv->pipes[0] ) close( p_priv->pipes[1] ); if( p_priv->pipes[0] != -1 ) close( p_priv->pipes[0] ); if( VLC_OBJECT(p_this->p_libvlc) == p_this ) vlc_mutex_destroy (&(libvlc_priv ((libvlc_int_t *)p_this)->structure_lock)); free( p_priv ); }
/***************************************************************************** * MonitorLibVLCDeath: Used when b_should_run_on_first_thread is set. *****************************************************************************/ static void * MonitorLibVLCDeath( vlc_object_t * p_this ) { intf_thread_t *p_intf = (intf_thread_t *)p_this; libvlc_int_t * p_libvlc = p_intf->p_libvlc; vlc_object_lock( p_libvlc ); while(vlc_object_alive( p_libvlc ) ) { if(p_intf->b_die) { vlc_object_unlock( p_libvlc ); return NULL; } vlc_object_wait( p_libvlc ); } vlc_object_unlock( p_libvlc ); /* Someone killed libvlc */ /* Make sure we kill all interface objects, especially * those that are blocking libvlc (running on main thread) */ vlc_list_t * p_list = vlc_list_find( p_libvlc, VLC_OBJECT_INTF, FIND_CHILD ); for( int i = 0; i < p_list->i_count; i++ ) { vlc_object_t * p_intf = p_list->p_values[i].p_object; vlc_object_kill( p_intf ); } vlc_list_release( p_list ); return NULL; }
/***************************************************************************** * Close: close the ALSA device *****************************************************************************/ static void Close( vlc_object_t *p_this ) { aout_instance_t *p_aout = (aout_instance_t *)p_this; struct aout_sys_t * p_sys = p_aout->output.p_sys; int i_snd_rc; /* Make sure that the thread will stop once it is waken up */ vlc_object_kill( p_aout ); /* make sure the audio output thread is waken up */ vlc_mutex_lock( &p_aout->output.p_sys->lock ); vlc_cond_signal( &p_aout->output.p_sys->wait ); vlc_mutex_unlock( &p_aout->output.p_sys->lock ); /* */ vlc_thread_join( p_aout ); p_aout->b_die = false; i_snd_rc = snd_pcm_close( p_sys->p_snd_pcm ); if( i_snd_rc > 0 ) { msg_Err( p_aout, "failed closing ALSA device (%s)", snd_strerror( i_snd_rc ) ); } #ifdef ALSA_DEBUG snd_output_close( p_sys->p_snd_stderr ); #endif free( p_sys ); }
/** * Check for updates * * \param p_update pointer to update struct * \param pf_callback pointer to a function to call when the update_check is finished * \param p_data pointer to some datas to give to the callback * \returns nothing */ void update_Check( update_t *p_update, void (*pf_callback)( void*, bool ), void *p_data ) { assert( p_update ); // If the object already exist, destroy it if( p_update->p_check ) { vlc_object_kill( p_update->p_check ); vlc_thread_join( p_update->p_check ); vlc_object_release( p_update->p_check ); } update_check_thread_t *p_uct = vlc_custom_create( p_update->p_libvlc, sizeof( *p_uct ), VLC_OBJECT_GENERIC, "update check" ); if( !p_uct ) return; p_uct->p_update = p_update; p_update->p_check = p_uct; p_uct->pf_callback = pf_callback; p_uct->p_data = p_data; vlc_thread_create( p_uct, "check for update", update_CheckReal, VLC_THREAD_PRIORITY_LOW ); }
/***************************************************************************** * CloseVideo: destroy Sys video thread output method ***************************************************************************** * Terminate an output method created by Open *****************************************************************************/ static void Close ( vlc_object_t *p_this ) { vout_thread_t * p_vout = (vout_thread_t *)p_this; msg_Dbg( p_vout, "close" ); if( p_vout->p_sys->p_event ) { vlc_object_detach( p_vout->p_sys->p_event ); /* Kill RunQtThread */ vlc_object_kill( p_vout->p_sys->p_event ); CloseDisplay(p_vout); vlc_thread_join( p_vout->p_sys->p_event ); vlc_object_release( p_vout->p_sys->p_event ); } #ifdef NEED_QTE_MAIN msg_Dbg( p_vout, "releasing gui-helper" ); module_unneed( p_vout, p_vout->p_sys->p_qte_main ); #endif if( p_vout->p_sys ) { free( p_vout->p_sys ); p_vout->p_sys = NULL; } }
static void stop_osdvnc ( filter_t *p_filter ) { filter_sys_t *p_sys = p_filter->p_sys; /* It will unlock socket reading */ vlc_object_kill( p_filter ); /* */ if( p_sys->p_worker_thread ) { msg_Dbg( p_filter, "joining worker_thread" ); vlc_object_kill( p_sys->p_worker_thread ); vlc_thread_join( p_sys->p_worker_thread ); vlc_object_release( p_sys->p_worker_thread ); msg_Dbg( p_filter, "released worker_thread" ); } msg_Dbg( p_filter, "osdvnc stopped" ); }
/*********************************************************************** * Stop ***********************************************************************/ static void ObjectKillChildrens( vlc_object_t *p_obj ) { vlc_list_t *p_list; int i; vlc_object_kill( p_obj ); p_list = vlc_list_children( p_obj ); for( i = 0; i < p_list->i_count; i++ ) ObjectKillChildrens( p_list->p_values[i].p_object ); vlc_list_release( p_list ); }
/** * MonitorLibVLCDeath: Used when b_should_run_on_first_thread is set. * * @param p_this: the interface object */ static void * MonitorLibVLCDeath( vlc_object_t * p_this ) { intf_thread_t *p_intf = (intf_thread_t *)p_this; libvlc_int_t * p_libvlc = p_intf->p_libvlc; int canc = vlc_savecancel (); libvlc_InternalWait( p_libvlc ); vlc_object_kill( p_intf ); /* Kill the stupid first thread interface */ vlc_restorecancel (canc); return NULL; }
/***************************************************************************** * InterfaceWindow::QuitRequested *****************************************************************************/ bool InterfaceWindow::QuitRequested() { if( p_playlist ) { playlist_Stop( p_playlist ); } p_mediaControl->SetStatus(-1, INPUT_RATE_DEFAULT); _StoreSettings(); vlc_object_kill( p_intf ); return( true ); }
/***************************************************************************** * Close: close the DSP audio device *****************************************************************************/ static void Close( vlc_object_t * p_this ) { aout_instance_t *p_aout = (aout_instance_t *)p_this; struct aout_sys_t * p_sys = p_aout->output.p_sys; vlc_object_kill( p_aout ); vlc_thread_join( p_aout ); p_aout->b_die = false; ioctl( p_sys->i_fd, SNDCTL_DSP_RESET, NULL ); close( p_sys->i_fd ); free( p_sys ); }
/***************************************************************************** * CloseAudio: close the audio device *****************************************************************************/ void CloseAudio ( vlc_object_t *p_this ) { aout_instance_t *p_aout = (aout_instance_t *)p_this; int i_ret; vlc_object_kill( p_aout ); vlc_thread_join( p_aout ); if( ( i_ret = snd_pcm_close( p_aout->output.p_sys->p_pcm_handle ) ) < 0 ) { msg_Err( p_aout, "unable to close audio device (%s)", snd_strerror( i_ret ) ); } free( p_aout->output.p_sys->p_silent_buffer ); free( p_aout->output.p_sys ); }
/***************************************************************************** * Close: close our file *****************************************************************************/ static void Close( vlc_object_t * p_this ) { u32 i; aout_instance_t * p_aout = (aout_instance_t *)p_this; struct aout_sys_t * p_sys = p_aout->output.p_sys; vlc_object_kill( p_aout ); vlc_thread_join( p_aout ); p_aout->b_die = false; do { i = p_sys->pPlayer->WaitForBuffer(); } while( i != 0 && i != p_sys->nBuffers ); p_sys->pPlayer->Close(); delete p_sys->pPlayer; free( p_sys->ppBuffers ); free( p_sys ); }
void CThread::Terminate(void) { // Set Termination Flag and EventObject! // and wait for Termination #if defined(_ATMO_VLC_PLUGIN_) if(m_pAtmoThread) { vlc_mutex_lock( &m_TerminateLock ); m_bTerminated = ATMO_TRUE; vlc_cond_signal( &m_TerminateCond ); vlc_mutex_unlock( &m_TerminateLock ); vlc_object_kill( m_pAtmoThread ); vlc_thread_join( m_pAtmoThread ); } #else m_bTerminated = ATMO_TRUE; SetEvent(m_hTerminateEvent); WaitForSingleObject(m_hThread,INFINITE); #endif }
void playlist_Deactivate( playlist_t *p_playlist ) { /* */ playlist_private_t *p_sys = pl_priv(p_playlist); msg_Dbg( p_playlist, "deactivating the playlist" ); PL_LOCK; vlc_object_kill( p_playlist ); vlc_cond_signal( &p_sys->signal ); PL_UNLOCK; vlc_join( p_sys->thread, NULL ); assert( !p_sys->p_input ); /* release input resources */ if( p_sys->p_input_resource ) { input_resource_Terminate( p_sys->p_input_resource ); input_resource_Release( p_sys->p_input_resource ); } p_sys->p_input_resource = NULL; if( var_InheritBool( p_playlist, "media-library" ) ) playlist_MLDump( p_playlist ); PL_LOCK; /* Release the current node */ set_current_status_node( p_playlist, NULL ); /* Release the current item */ set_current_status_item( p_playlist, NULL ); PL_UNLOCK; msg_Dbg( p_playlist, "playlist correctly deactivated" ); }
/** * Starts and runs the interface thread. * * \param p_intf the interface thread * \return VLC_SUCCESS on success, an error number else */ int intf_RunThread( intf_thread_t *p_intf ) { #if defined( __APPLE__ ) || defined( WIN32 ) /* Hack to get Mac OS X Cocoa runtime running * (it needs access to the main thread) */ if( p_intf->b_should_run_on_first_thread ) { if( vlc_thread_create( p_intf, "interface", MonitorLibVLCDeath, VLC_THREAD_PRIORITY_LOW, false ) ) { msg_Err( p_intf, "cannot spawn libvlc death monitoring thread" ); return VLC_EGENERIC; } RunInterface( VLC_OBJECT(p_intf) ); /* Make sure our MonitorLibVLCDeath thread exit */ vlc_object_kill( p_intf ); /* It is monitoring libvlc, not the p_intf */ vlc_object_signal( p_intf->p_libvlc ); vlc_thread_join( p_intf ); vlc_object_detach( p_intf ); vlc_object_release( p_intf ); return VLC_SUCCESS; } #endif /* Run the interface in a separate thread */ if( vlc_thread_create( p_intf, "interface", RunInterface, VLC_THREAD_PRIORITY_LOW, false ) ) { msg_Err( p_intf, "cannot spawn interface thread" ); return VLC_EGENERIC; } return VLC_SUCCESS; }
/***************************************************************************** * Close: free unused data structures *****************************************************************************/ static void Close( vlc_object_t *p_this ) { access_t *p_access = (access_t*)p_this; access_sys_t *p_sys = p_access->p_sys; if( p_sys->p_ev ) { /* stop the event handler */ vlc_object_kill( p_sys->p_ev ); if( p_sys->p_raw1394 ) raw1394_iso_shutdown( p_sys->p_raw1394 ); vlc_thread_join( p_sys->p_ev ); vlc_mutex_destroy( &p_sys->p_ev->lock ); /* Cleanup frame data */ if( p_sys->p_ev->p_frame ) { block_ChainRelease( p_sys->p_ev->p_frame ); p_sys->p_ev->p_frame = NULL; p_sys->p_ev->pp_last = &p_sys->p_frame; } vlc_object_release( p_sys->p_ev ); } if( p_sys->p_frame ) block_ChainRelease( p_sys->p_frame ); if( p_sys->p_raw1394 ) raw1394_destroy_handle( p_sys->p_raw1394 ); AVCClose( p_access ); vlc_mutex_destroy( &p_sys->lock ); free( p_sys ); }
static void* vnc_worker_thread( vlc_object_t *p_thread_obj ) { filter_t* p_filter = (filter_t*)(p_thread_obj->p_parent); filter_sys_t *p_sys = p_filter->p_sys; vlc_object_t *p_update_request_thread; int canc = vlc_savecancel (); msg_Dbg( p_filter, "VNC worker thread started" ); if( !open_vnc_connection ( p_filter ) ) { msg_Err( p_filter, "Could not connect to vnc host" ); goto exit; } if( !handshaking ( p_filter ) ) { msg_Err( p_filter, "Error occured while handshaking vnc host" ); goto exit; } p_sys->b_connection_active = true; /* to enable sending key * and mouse events to host */ /* Create an empty picture for VNC the data */ vlc_mutex_lock( &p_sys->lock ); p_sys->p_pic = picture_New( VLC_CODEC_YUVA, p_sys->i_vnc_width, p_sys->i_vnc_height, 1, 1 ); if( !p_sys->p_pic ) { vlc_mutex_unlock( &p_sys->lock ); goto exit; } p_sys->i_vnc_pixels = p_sys->i_vnc_width * p_sys->i_vnc_height; vlc_mutex_unlock( &p_sys->lock ); /* create the update request thread */ p_update_request_thread = vlc_object_create( p_filter, sizeof( vlc_object_t ) ); vlc_object_attach( p_update_request_thread, p_filter ); if( vlc_thread_create( p_update_request_thread, update_request_thread, VLC_THREAD_PRIORITY_LOW ) ) { vlc_object_release( p_update_request_thread ); msg_Err( p_filter, "cannot spawn vnc update request thread" ); goto exit; } /* connection is initialized, now read and handle server messages */ while( vlc_object_alive( p_thread_obj ) ) { rfbServerToClientMsg msg; int i_msgSize; memset( &msg, 0, sizeof(msg) ); if( !read_exact(p_filter, p_sys->i_socket, (char*)&msg, 1 ) ) { msg_Err( p_filter, "Error while waiting for next server message"); break; } switch (msg.type) { case rfbFramebufferUpdate: i_msgSize = sz_rfbFramebufferUpdateMsg; break; case rfbSetColourMapEntries: i_msgSize = sz_rfbSetColourMapEntriesMsg; break; case rfbBell: i_msgSize = sz_rfbBellMsg; break; case rfbServerCutText: i_msgSize = sz_rfbServerCutTextMsg; break; case rfbReSizeFrameBuffer: i_msgSize = sz_rfbReSizeFrameBufferMsg; break; default: i_msgSize = 0; msg_Err( p_filter, "Invalid message %u received", msg.type ); break; } if( i_msgSize <= 0 ) break; if( --i_msgSize > 0 ) { if ( !read_exact( p_filter, p_sys->i_socket, ((char*)&msg)+1, i_msgSize ) ) { msg_Err( p_filter, "Error while reading message of type %u", msg.type ); break; } } process_server_message( p_filter, &msg); } msg_Dbg( p_filter, "joining update_request_thread" ); vlc_object_kill( p_update_request_thread ); vlc_thread_join( p_update_request_thread ); vlc_object_release( p_update_request_thread ); msg_Dbg( p_filter, "released update_request_thread" ); exit: vlc_mutex_lock( &p_sys->lock ); p_sys->b_connection_active = false; if (p_sys->i_socket >= 0) net_Close(p_sys->i_socket); if( p_sys->p_pic ) picture_Release( p_sys->p_pic ); /* It will hide the subtitle */ p_sys->b_continue = false; p_sys->b_need_update = true; vlc_mutex_unlock( &p_sys->lock ); msg_Dbg( p_filter, "VNC message reader thread ended" ); vlc_restorecancel (canc); return NULL; }
/** * Stops the interface thread * * This function asks the interface thread to stop * \param p_intf the interface thread * \return nothing */ void intf_StopThread( intf_thread_t *p_intf ) { /* Tell the interface to die */ vlc_object_kill( p_intf ); vlc_thread_join( p_intf ); }
/** * Create and start an interface. * * @param p_this the calling vlc_object_t * @param psz_module a preferred interface module * @return VLC_SUCCESS or an error code */ int intf_Create( vlc_object_t *p_this, const char *psz_module ) { libvlc_int_t *p_libvlc = p_this->p_libvlc; intf_thread_t * p_intf; /* Allocate structure */ p_intf = vlc_custom_create( p_libvlc, sizeof( *p_intf ), "interface" ); if( !p_intf ) return VLC_ENOMEM; /* Variable used for interface spawning */ vlc_value_t val, text; var_Create( p_intf, "intf-add", VLC_VAR_STRING | VLC_VAR_HASCHOICE | VLC_VAR_ISCOMMAND ); text.psz_string = _("Add Interface"); var_Change( p_intf, "intf-add", VLC_VAR_SETTEXT, &text, NULL ); #if !defined(WIN32) && defined(HAVE_ISATTY) if( isatty( 0 ) ) #endif { val.psz_string = (char *)"rc"; text.psz_string = (char *)_("Console"); var_Change( p_intf, "intf-add", VLC_VAR_ADDCHOICE, &val, &text ); } val.psz_string = (char *)"telnet"; text.psz_string = (char *)_("Telnet"); var_Change( p_intf, "intf-add", VLC_VAR_ADDCHOICE, &val, &text ); val.psz_string = (char *)"http"; text.psz_string = (char *)_("Web"); var_Change( p_intf, "intf-add", VLC_VAR_ADDCHOICE, &val, &text ); val.psz_string = (char *)"logger"; text.psz_string = (char *)_("Debug logging"); var_Change( p_intf, "intf-add", VLC_VAR_ADDCHOICE, &val, &text ); val.psz_string = (char *)"gestures"; text.psz_string = (char *)_("Mouse Gestures"); var_Change( p_intf, "intf-add", VLC_VAR_ADDCHOICE, &val, &text ); var_AddCallback( p_intf, "intf-add", AddIntfCallback, NULL ); /* Attach interface to LibVLC */ #if defined( __APPLE__ ) p_intf->b_should_run_on_first_thread = false; #endif /* Choose the best module */ p_intf->p_cfg = NULL; char *psz_parser = *psz_module == '$' ? var_CreateGetString(p_intf,psz_module+1) : strdup( psz_module ); char *psz_tmp = config_ChainCreate( &p_intf->psz_intf, &p_intf->p_cfg, psz_parser ); free( psz_tmp ); free( psz_parser ); p_intf->p_module = module_need( p_intf, "interface", p_intf->psz_intf, true ); if( p_intf->p_module == NULL ) { msg_Err( p_intf, "no suitable interface module" ); goto error; } #if defined( __APPLE__ ) /* Hack to get Mac OS X Cocoa runtime running * (it needs access to the main thread) */ if( p_intf->b_should_run_on_first_thread ) { if( vlc_clone( &p_intf->thread, MonitorLibVLCDeath, p_intf, VLC_THREAD_PRIORITY_LOW ) ) { msg_Err( p_intf, "cannot spawn libvlc death monitoring thread" ); goto error; } assert( p_intf->pf_run ); p_intf->pf_run( p_intf ); /* It is monitoring libvlc, not the p_intf */ vlc_object_kill( p_intf->p_libvlc ); vlc_join( p_intf->thread, NULL ); } else #endif /* Run the interface in a separate thread */ if( p_intf->pf_run && vlc_clone( &p_intf->thread, RunInterface, p_intf, VLC_THREAD_PRIORITY_LOW ) ) { msg_Err( p_intf, "cannot spawn interface thread" ); goto error; } vlc_mutex_lock( &lock ); p_intf->p_next = libvlc_priv( p_libvlc )->p_intf; libvlc_priv( p_libvlc )->p_intf = p_intf; vlc_mutex_unlock( &lock ); return VLC_SUCCESS; error: if( p_intf->p_module ) module_unneed( p_intf, p_intf->p_module ); config_ChainDestroy( p_intf->p_cfg ); free( p_intf->psz_intf ); vlc_object_release( p_intf ); return VLC_EGENERIC; }
static void Run(intf_thread_t *p_intf) { intf_sys_t *p_sys = p_intf->p_sys; input_thread_t *p_input = NULL; playlist_t *p_playlist = pl_Get(p_intf); int *pi_fd, i_listen = 0, i_err; p_intf->p_sys->p_playlist = p_playlist; for (pi_fd = p_sys->pi_socket; *pi_fd != -1; pi_fd++) i_listen++; for (; vlc_object_alive(p_intf);) { vlc_value_t val; struct pollfd fd[i_listen + 2]; vlc_testcancel(); if (p_input == NULL) { p_input = playlist_CurrentInput(p_playlist); if (p_input) { var_AddCallback(p_input, "intf-event", InputEvent, p_intf); } } else { if (p_input->b_dead || !vlc_object_alive(p_input)) { var_DelCallback(p_input, "intf-event", InputEvent, p_intf); vlc_object_release(p_input); p_input = NULL; } } memset(&fd, 0, sizeof(fd[0]) * (i_listen + 1)); if (p_sys->i_socket == -1) { for (int i = 0; i < i_listen; i++) { fd[i].fd = p_sys->pi_socket[i]; fd[i].events = POLLIN; fd[i].revents = 0; } } else { fd[0].fd = p_sys->i_wakeup[0]; fd[0].events = POLLIN; fd[0].revents = 0; fd[1].fd = p_sys->i_socket; fd[1].events = POLLIN | (p_sys->i_write_length > 0 ? POLLOUT : 0); fd[1].revents = 0; } i_err = poll(fd, (p_sys->i_socket != -1) ? 2 : i_listen, -1); if (i_err < 0) { msg_Dbg(p_intf, "poll() failed"); vlc_object_kill(p_intf); break; } if (i_err == 0) continue; if (p_sys->i_socket == -1) { for (int i = 0; i < i_listen; i++) { if (fd[i].revents & POLLIN) { int client = net_AcceptSingle(VLC_OBJECT(p_intf), fd[i].fd); if (client == -1) continue; p_sys->i_socket = client; break; } } } else { if (fd[0].revents & POLLIN) { char ch; read(fd[0].fd, &ch, 1); } if (fd[1].revents & (POLLERR|POLLHUP|POLLNVAL)) { net_Close(fd[0].fd); p_sys->i_socket = -1; msg_Dbg(VLC_OBJECT(p_intf), "connection error"); continue; } ssize_t i_len, i_test; if (fd[1].revents & POLLIN) { //msg_Dbg(VLC_OBJECT(p_intf), "poll in"); bool b_line = false; while ((i_len = recv(fd[1].fd, p_sys->p_read_buffer + p_sys->i_read_offset, 1, 0)) > 0) { char ch; ch = p_sys->p_read_buffer[p_sys->i_read_offset]; switch (ch) { case '\r': case '\n': p_sys->p_read_buffer[p_sys->i_read_offset] = '\0'; b_line = true; break; case '\0': b_line = true; break; default: break; } p_sys->i_read_offset++; if (p_sys->i_read_offset == sizeof(p_sys->p_read_buffer) && !b_line) { net_Close(p_sys->i_socket); p_sys->i_socket = -1; msg_Dbg(VLC_OBJECT(p_intf), "input is too long, close connection"); break; } } if (b_line && strlen(p_sys->p_read_buffer)) { p_sys->i_read_offset = 0; //msg_Dbg(VLC_OBJECT(p_intf), "%s\n", p_sys->p_read_buffer); ProcessCommand(p_intf, p_sys->p_read_buffer); } if(i_len == 0) { net_Close(p_sys->i_socket); p_sys->i_socket = -1; msg_Dbg(VLC_OBJECT(p_intf), "connection is closed by client"); } } if (fd[1].revents & POLLOUT) { vlc_mutex_lock(&p_sys->o_write_lock); if (p_sys->i_write_length) { int i_first, i_second; i_first = sizeof(p_sys->p_write_buffer) - p_sys->i_write_offset; i_second = (p_sys->i_write_offset + p_sys->i_write_length) % sizeof(p_sys->p_write_buffer); i_test = 0; if (i_first >= p_sys->i_write_length) i_len = send(fd[1].fd, p_sys->p_write_buffer + p_sys->i_write_offset, p_sys->i_write_length, 0); else { i_len = send(fd[1].fd, p_sys->p_write_buffer + p_sys->i_write_offset, i_first, 0); if (i_len == i_first) i_test = send(fd[1].fd, p_sys->p_write_buffer, i_second, 0); if (i_test > 0) i_len += i_test; } if (i_len > 0) { p_sys->i_write_offset += i_len; p_sys->i_write_offset %= sizeof(p_sys->p_write_buffer); p_sys->i_write_length -= i_len; if (p_sys->i_write_length == 0) p_sys->i_write_offset = 0; } } vlc_mutex_unlock(&p_sys->o_write_lock); } } } }