X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fcontrol%2Flog.c;h=e6b066d08a67fb325defa7eb3ddd18296933b2ca;hb=8f9c3647ccfcd55cd6835ed90e98766a7f2eb677;hp=182fb8b9fc8898a071d88474aebdf060417ccfbe;hpb=81a45beda78abfe78354d9b348f6dfba1a3b9598;p=vlc diff --git a/src/control/log.c b/src/control/log.c index 182fb8b9fc..e6b066d08a 100644 --- a/src/control/log.c +++ b/src/control/log.c @@ -22,40 +22,71 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + #include "libvlc_internal.h" #include +#include + +/* This API is terminally broken. + * First, it does not implement any kind of notification. + * Second, the iterating scheme is hermetic to any kind of thread-safety + * owing to its constant pointer constraints. + * -- Courmisch + * + * "If you break your leg, don't run to me for sympathy" + * -- some character, Beneath a Steel Sky + */ + +struct msg_cb_data_t +{ + vlc_spinlock_t lock; + msg_item_t *items[VLC_MSG_QSIZE]; + unsigned count; + int verbosity; +}; + +static void handler( msg_cb_data_t *d, msg_item_t *p_item, unsigned i_drop ) +{ + if (p_item->i_type > d->verbosity) + return; + + vlc_spin_lock (&d->lock); + if (d->count < VLC_MSG_QSIZE) + { + d->items[d->count++] = p_item; + msg_Hold (p_item); + } + vlc_spin_unlock (&d->lock); + (void)i_drop; +} struct libvlc_log_t { libvlc_instance_t *p_instance; msg_subscription_t *p_messages; + msg_cb_data_t data; }; struct libvlc_log_iterator_t { - msg_subscription_t *p_messages; - int i_start; - int i_pos; - int i_end; + msg_cb_data_t *p_data; + unsigned i_pos; + unsigned i_end; }; -unsigned libvlc_get_log_verbosity( const libvlc_instance_t *p_instance, libvlc_exception_t *p_e ) +unsigned libvlc_get_log_verbosity( const libvlc_instance_t *p_instance ) { - if( p_instance ) - { - return p_instance->p_libvlc_int->i_verbose; - } - RAISEZERO("Invalid VLC instance!"); + assert( p_instance ); + return p_instance->verbosity; } -void libvlc_set_log_verbosity( libvlc_instance_t *p_instance, unsigned level, libvlc_exception_t *p_e ) +void libvlc_set_log_verbosity( libvlc_instance_t *p_instance, unsigned level ) { - if( p_instance ) - { - p_instance->p_libvlc_int->i_verbose = level; - } - else - RAISEVOID("Invalid VLC instance!"); + assert( p_instance ); + p_instance->verbosity = level; } libvlc_log_t *libvlc_log_open( libvlc_instance_t *p_instance, libvlc_exception_t *p_e ) @@ -66,7 +97,10 @@ libvlc_log_t *libvlc_log_open( libvlc_instance_t *p_instance, libvlc_exception_t if( !p_log ) RAISENULL( "Out of memory" ); p_log->p_instance = p_instance; - p_log->p_messages = msg_Subscribe(p_instance->p_libvlc_int, MSG_QUEUE_NORMAL); + vlc_spin_init( &p_log->data.lock ); + p_log->data.count = 0; + p_log->data.verbosity = p_instance->verbosity; + p_log->p_messages = msg_Subscribe(p_instance->p_libvlc_int, handler, &p_log->data); if( !p_log->p_messages ) { @@ -78,112 +112,110 @@ libvlc_log_t *libvlc_log_open( libvlc_instance_t *p_instance, libvlc_exception_t return p_log; } -void libvlc_log_close( libvlc_log_t *p_log, libvlc_exception_t *p_e ) +void libvlc_log_close( libvlc_log_t *p_log ) { - if( p_log && p_log->p_messages ) - { - msg_Unsubscribe(p_log->p_instance->p_libvlc_int, p_log->p_messages); - libvlc_release( p_log->p_instance ); - free(p_log); - } - else - RAISEVOID("Invalid log object!"); + if( !p_log ) + return; + + assert( p_log->p_messages ); + msg_Unsubscribe(p_log->p_messages); + libvlc_release( p_log->p_instance ); + libvlc_log_clear( p_log ); + vlc_spin_destroy( &p_log->data.lock ); + free(p_log); } -unsigned libvlc_log_count( const libvlc_log_t *p_log, libvlc_exception_t *p_e ) +unsigned libvlc_log_count( const libvlc_log_t *p_log ) { - if( p_log && p_log->p_messages ) - { - int i_start = p_log->p_messages->i_start; - int i_stop = *(p_log->p_messages->pi_stop); - - if( i_stop >= i_start ) - return i_stop-i_start; - else - return VLC_MSG_QSIZE-(i_start-i_stop); - } - RAISEZERO("Invalid log object!"); + if( !p_log ) + return 0; + + msg_cb_data_t *data = &((libvlc_log_t *)p_log)->data; + unsigned ret; + + /* We cannot lock due to constant pointer constraints. Break them. + * Even then, this si not really thread safe anyway. */ + vlc_spin_lock (&data->lock); + ret = data->count; + vlc_spin_unlock (&data->lock); + return ret; } -void libvlc_log_clear( libvlc_log_t *p_log, libvlc_exception_t *p_e ) +void libvlc_log_clear( libvlc_log_t *p_log ) { - if( p_log && p_log->p_messages ) - { - vlc_mutex_lock(p_log->p_messages->p_lock); - p_log->p_messages->i_start = *(p_log->p_messages->pi_stop); - vlc_mutex_unlock(p_log->p_messages->p_lock); - } - else - RAISEVOID("Invalid log object!"); + if( !p_log ) + return; + + vlc_spin_lock (&p_log->data.lock); + msg_item_t *tab[p_log->data.count]; + memcpy (tab, p_log->data.items, sizeof (tab)); + p_log->data.count = 0; + vlc_spin_unlock (&p_log->data.lock); + + for (unsigned i = 0; i < sizeof (tab) / sizeof (tab[0]); i++) + msg_Release (tab[i]); } -libvlc_log_iterator_t *libvlc_log_get_iterator( const libvlc_log_t *p_log, libvlc_exception_t *p_e ) +libvlc_log_iterator_t *libvlc_log_get_iterator( const libvlc_log_t *p_log, + libvlc_exception_t *p_e ) { - if( p_log && p_log->p_messages ) + if( p_log ) { struct libvlc_log_iterator_t *p_iter = (struct libvlc_log_iterator_t *)malloc(sizeof(struct libvlc_log_iterator_t)); + /* FIXME: break constant pointer constraints */ + msg_cb_data_t *data = &((libvlc_log_t *)p_log)->data; if( !p_iter ) RAISENULL( "Out of memory" ); - vlc_mutex_lock(p_log->p_messages->p_lock); - p_iter->p_messages = p_log->p_messages; - p_iter->i_start = p_log->p_messages->i_start; - p_iter->i_pos = p_log->p_messages->i_start; - p_iter->i_end = *(p_log->p_messages->pi_stop); - vlc_mutex_unlock(p_log->p_messages->p_lock); + vlc_spin_lock (&data->lock); + p_iter->p_data = data; + p_iter->i_pos = 0; + p_iter->i_end = data->count; + vlc_spin_unlock (&data->lock); return p_iter; } RAISENULL("Invalid log object!"); } -void libvlc_log_iterator_free( libvlc_log_iterator_t *p_iter, libvlc_exception_t *p_e ) +void libvlc_log_iterator_free( libvlc_log_iterator_t *p_iter ) { - if( p_iter ) - { - free(p_iter); - } - else - RAISEVOID("Invalid log iterator!"); + free( p_iter ); } -int libvlc_log_iterator_has_next( const libvlc_log_iterator_t *p_iter, libvlc_exception_t *p_e ) +int libvlc_log_iterator_has_next( const libvlc_log_iterator_t *p_iter ) { - if( p_iter ) - { - return p_iter->i_pos != p_iter->i_end; - } - RAISEZERO("Invalid log iterator!"); + if( !p_iter ) + return 0; + return p_iter->i_pos != p_iter->i_end; } libvlc_log_message_t *libvlc_log_iterator_next( libvlc_log_iterator_t *p_iter, libvlc_log_message_t *buffer, libvlc_exception_t *p_e ) { - int i_pos; + unsigned i_pos; if( !p_iter ) - RAISENULL("Invalid log iterator!"); - if( !buffer ) - RAISENULL("Invalid message buffer!"); + return NULL; + assert( buffer ); i_pos = p_iter->i_pos; if( i_pos != p_iter->i_end ) { msg_item_t *msg; - vlc_mutex_lock(p_iter->p_messages->p_lock); - msg = p_iter->p_messages->p_msg+i_pos; + vlc_spin_lock (&p_iter->p_data->lock); + msg = p_iter->p_data->items[i_pos]; buffer->i_severity = msg->i_type; buffer->psz_type = msg->psz_object_type; buffer->psz_name = msg->psz_module; buffer->psz_header = msg->psz_header; buffer->psz_message = msg->psz_msg; - p_iter->i_pos = ++i_pos % VLC_MSG_QSIZE; - vlc_mutex_unlock(p_iter->p_messages->p_lock); + vlc_spin_unlock (&p_iter->p_data->lock); + p_iter->i_pos++; return buffer; } RAISENULL("No more messages"); } -