www.pudn.com > kceasy-0.19-rc1-src.rar > svlc_event.c


/***************************************************************************** 
 * svlc_event.c: a simple shared library wrapper around libvlc 
 ***************************************************************************** 
 * Copyright (C) 2004 Markus Kern  
 * 
 * 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 "config.h" 
 
//#include  
 
#define __BUILTIN__ 
#define __VLC__ 
 
#include  
#include  
#include  
#include  
#include  
 
#include "svlc_event.h" 
 
#define EVENT_THREAD_SLEEP 100 /* ms */ 
 
/****************************************************************************** 
 * Some internal helper functions 
 *****************************************************************************/ 
 
#ifdef DEBUG 
 
/* This resides in libvcl.c but is not in the headers. */ 
vlc_t * vlc_current_object (int i_object); 
 
static char * state_str (SVlcPlaybackState state) 
{ 
	switch (state) 
	{ 
	case SVLC_PLAYBACK_CLOSED:  return "Closed"; 
	case SVLC_PLAYBACK_LOADING: return "Loading"; 
	case SVLC_PLAYBACK_OPEN:    return "Open"; 
	case SVLC_PLAYBACK_PLAYING: return "Playing"; 
	case SVLC_PLAYBACK_PAUSED:  return "Paused"; 
	case SVLC_PLAYBACK_STOPPED: return "Stopped"; 
	default:                    return "UNKNOWN"; 
	}; 
} 
 
static void log_state_change (HSVLC svlc, SVlcPlaybackState old_state, 
                              SVlcPlaybackState new_state) 
{ 
    vlc_t *vlc; 
 
    if (!(vlc = vlc_current_object (svlc->vlc))) 
        return; 
  
    msg_Dbg (vlc, "STATE CHANGE: %s => %s", 
	         state_str (old_state), state_str (new_state)); 
 
    vlc_object_release (vlc); 
} 
 
#endif 
 
/***************************************************************************** 
 * Polling thread 
 *****************************************************************************/ 
 
#if 0 
 
/* polling thread function */ 
static void event_thread_func (svlc_event_thread_t *thread) 
{ 
#if 0 
    playlist_t *playlist; 
 
	/* find playlist */ 
    if (!(playlist = vlc_object_find (vlc, VLC_OBJECT_PLAYLIST, FIND_CHILD))) 
	{ 
 
	} 
 
	/* start with closed state */	 
	svlc_event_set_playback_state (thread->svlc, SVLC_PLAYBACK_CLOSED); 
#endif 
     
	/* tell creating thread that we're ready */ 
    vlc_thread_ready (thread); 
 
	while (!thread->b_die) 
	{ 
		msleep (EVENT_THREAD_SLEEP); 
	} 
 
#if 0 
	/* end with closed state */	 
	svlc_event_set_playback_state (thread->svlc, SVLC_PLAYBACK_CLOSED); 
 
	vlc_object_release (playlist); 
#endif 
} 
 
/* create and start event polling thread */ 
svlc_event_thread_t * svlc_event_create_thread (HSVLC svlc, vlc_t *vlc) 
{ 
	svlc_event_thread_t *thread; 
 
    if(!(thread = vlc_object_create (vlc, sizeof (svlc_event_thread_t)))) 
    { 
        msg_Err (vlc, "out of memory"); 
        return NULL; 
    } 
 
	thread->svlc = svlc; 
 
	/* start thread and wait till it is ready */ 
    if (vlc_thread_create( thread, "svlc_event_thread", event_thread_func, 
                           VLC_THREAD_PRIORITY_LOW, VLC_TRUE ) != 0) 
    { 
        msg_Err (thread, "cannot spawn event polling thread"); 
        vlc_object_destroy (thread); 
        return NULL; 
    } 
 
#if 0 
    /* The object has been initialized, now attach it */ 
    vlc_object_attach (thread, vlc); 
#endif 
 
	return thread; 
} 
 
/* join and free event polling thread */ 
vlc_bool_t svlc_event_join_thread (svlc_event_thread_t *thread) 
{ 
	/* wait for thread completion */ 
	thread->b_die = 1; 
    vlc_thread_join (thread); 
 
	/* free object */ 
    vlc_object_destroy (thread); 
 
	return VLC_TRUE; 
} 
 
#endif 
 
/***************************************************************************** 
 * Handlers for VLC variable changes 
 *****************************************************************************/ 
 
static int popup_callback (vlc_object_t *this, char const *cmd, 
                           vlc_value_t oldval, vlc_value_t newval, 
                           void *data) 
{ 
	HSVLC svlc = (HSVLC)data; 
 
	if (newval.b_bool != oldval.b_bool) 
	{ 
		SVlcCbDisplayPopupData popup_data; 
		popup_data.show = newval.b_bool; 
 
		svlc->callback (svlc, SVLC_CB_DISPLAY_POPUP, (void*)&popup_data, 
		                svlc->udata); 
	} 
 
    return VLC_SUCCESS; 
} 
 
static int key_pressed_callback (vlc_object_t *this, char const *cmd, 
                                 vlc_value_t oldval, vlc_value_t newval, 
                                 void *data) 
{ 
	HSVLC svlc = (HSVLC)data; 
	SVlcCbKeyPressedData key_data; 
 
#ifdef DEBUG 
	vlc_t *vlc = (vlc_t *)this; 
    msg_Dbg (vlc, "cmd=%s old=%d new=%d", cmd, 
	         oldval.i_int, newval.i_int); 
#endif 
 
	key_data.key = newval.i_int; 
 
	svlc->callback (svlc, SVLC_CB_KEY_PRESSED, (void*)&key_data, 
	                svlc->udata); 
 
    return VLC_SUCCESS; 
} 
 
static int intf_change_callback (vlc_object_t *this, char const *cmd, 
                                 vlc_value_t oldval, vlc_value_t newval, 
                                 void *data) 
{ 
	HSVLC svlc = (HSVLC)data; 
    input_thread_t *input = (input_thread_t *)this; 
	SVlcPlaybackState new_state; 
 
#if 0 
    msg_Dbg (input, "cmd=%s old=%d new=%d", cmd, 
	         oldval.i_int, newval.i_int); 
#endif 
 
	/* check for state changes */ 
 
	switch (input->i_state) 
	{ 
	case INIT_S:	new_state = SVLC_PLAYBACK_LOADING; break; 
	case PLAYING_S:	new_state = SVLC_PLAYBACK_PLAYING; break; 
	case PAUSE_S:	new_state = SVLC_PLAYBACK_PAUSED;  break; 
	case END_S:     new_state = SVLC_PLAYBACK_STOPPED; break; 
	default:        new_state = svlc->playback_state; /* change nothing */ 
	} 
 
	if(input->b_error) 
		new_state = SVLC_PLAYBACK_ERROR; /* implies SVLC_PLAYBACK_CLOSED */ 
 
	/* if we go from loading to playing squeze an open in */ 
	if (svlc->playback_state == SVLC_PLAYBACK_LOADING && 
	    new_state == SVLC_PLAYBACK_PLAYING) 
		svlc_event_set_playback_state (svlc, SVLC_PLAYBACK_OPEN); 
 
	svlc_event_set_playback_state (svlc, new_state); 
 
	/* currently stopping means closing as well */ 
	if (new_state == SVLC_PLAYBACK_STOPPED) 
		svlc_event_set_playback_state (svlc, SVLC_PLAYBACK_CLOSED); 
 
 
	/* update position */ 
 
	if (svlc->cb_events & SVLC_CB_POSITION_CHANGE && 
	    svlc->playback_state == SVLC_PLAYBACK_PLAYING) 
	{ 
		vlc_value_t val; 
		SVlcCbPositionChangeData position_data; 
 
		var_Get (input, "position", &val); 
		position_data.position = val.f_float; 
 
		var_Get (input, "length", &val); 
		position_data.duration = val.i_time / 1000; 
 
/* 
		msg_Dbg (input, "POSITION: %f", position_data.position); 
*/ 
 
		/* call back to user */ 
		svlc->callback (svlc, SVLC_CB_POSITION_CHANGE, (void*)&position_data, 
			            svlc->udata); 
	} 
 
    return VLC_SUCCESS; 
} 
 
/* we use this to hook the new input */ 
static int input_change_callback (vlc_object_t *this, char const *cmd, 
                                  vlc_value_t oldval, vlc_value_t newval, 
                                  void *data) 
{ 
	HSVLC svlc = (HSVLC)data; 
    playlist_t *playlist = (playlist_t *)this; 
 
#ifdef DEBUG 
    msg_Dbg (playlist, "cmd=%s old=%d new=%d", cmd, 
	         oldval.i_int, newval.i_int); 
#endif 
 
	/* Clearly we are loading with a new input */ 
	svlc_event_set_playback_state (svlc, SVLC_PLAYBACK_LOADING); 
 
	/* hook new input */ 
    vlc_mutex_lock (&playlist->object_lock); 
 
	var_AddCallback (playlist->p_input, "intf-change", 
		             intf_change_callback, (void*)svlc); 
     
	vlc_mutex_unlock (&playlist->object_lock); 
 
    return VLC_SUCCESS; 
} 
 
/***************************************************************************** 
 * Event registration 
 *****************************************************************************/ 
 
vlc_bool_t svlc_event_register_callbacks (HSVLC svlc, vlc_t *vlc) 
{ 
	input_thread_t *input; 
	playlist_t     *playlist; 
 
	/* vlc events */ 
 
	if (svlc->cb_events & SVLC_CB_KEY_PRESSED) 
	{ 
		var_AddCallback (vlc, "key-pressed", key_pressed_callback, 
		                 (void*)svlc); 
	} 
 
	/* input events */ 
 
    if ((input = vlc_object_find (vlc, VLC_OBJECT_INPUT, FIND_CHILD))) 
	{ 
		vlc_object_release (input); 
	} 
 
	/* playlist events */ 
 
    if ((playlist = vlc_object_find (vlc, VLC_OBJECT_PLAYLIST, FIND_CHILD))) 
	{ 
		if (svlc->cb_events & SVLC_CB_DISPLAY_POPUP) 
			var_AddCallback (playlist, "intf-popupmenu", 
			                 popup_callback, (void*)svlc); 
 
		/* we always want this to hook the input if neccessary */ 
		var_AddCallback (playlist, "playlist-current", 
		                 input_change_callback, (void*)svlc); 
 
		vlc_object_release (playlist); 
	} 
 
	return VLC_TRUE; 
} 
 
vlc_bool_t svlc_event_unregister_callbacks (HSVLC svlc, vlc_t *vlc) 
{ 
	input_thread_t *input; 
	playlist_t     *playlist; 
 
	/* vlc events */ 
 
	if (svlc->cb_events & SVLC_CB_KEY_PRESSED) 
	{ 
		var_DelCallback (vlc, "key-pressed", key_pressed_callback, 
		                 (void*)svlc); 
	} 
 
	/* input events */ 
    if ((input = vlc_object_find (vlc, VLC_OBJECT_INPUT, FIND_CHILD))) 
	{ 
		vlc_object_release (input); 
	} 
 
	/* playlist events */ 
 
    if ((playlist = vlc_object_find (vlc, VLC_OBJECT_PLAYLIST, FIND_CHILD))) 
	{ 
		if (svlc->cb_events & SVLC_CB_DISPLAY_POPUP) 
			var_DelCallback (playlist, "intf-popupmenu", 
			                 popup_callback, (void*)svlc); 
 
		/* we always want this to hook the input if neccessary */ 
		var_DelCallback (playlist, "playlist-current", 
		                 input_change_callback, (void*)svlc); 
		 
		vlc_object_release (playlist); 
	} 
 
	return VLC_TRUE; 
} 
 
vlc_bool_t svlc_event_set_playback_state (HSVLC svlc, 
										  SVlcPlaybackState new_state) 
{ 
	SVlcCbStateData state_data; 
 
	if (new_state == svlc->playback_state) 
		return VLC_FALSE; 
 
	state_data.old_state = svlc->playback_state; 
	state_data.new_state = new_state; 
 
	svlc->playback_state = new_state; 
 
#ifdef DEBUG 
	log_state_change (svlc, state_data.old_state, state_data.new_state); 
#endif 
 
	if (svlc->cb_events & SVLC_CB_STATE_CHANGE) 
	{ 
		/* call back to user */ 
		svlc->callback (svlc, SVLC_CB_STATE_CHANGE, (void*)&state_data, 
		                svlc->udata); 
	} 
 
    return VLC_SUCCESS; 
}