X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fcontrol%2Flog.c;h=5442870b06d6364ee484669115986bf3f6a48731;hb=2f63e68b447e5b2484954f60b90d430afd887b98;hp=01917ca93f8ff3571f54c0938d56885086c6610c;hpb=3b0c979e83cd90528cc0894bf0c7e7f3d03ef399;p=vlc diff --git a/src/control/log.c b/src/control/log.c index 01917ca93f..5442870b06 100644 --- a/src/control/log.c +++ b/src/control/log.c @@ -22,169 +22,202 @@ * 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 ) +libvlc_log_t *libvlc_log_open( libvlc_instance_t *p_instance ) { - struct libvlc_log_t *p_log = - (struct libvlc_log_t *)malloc(sizeof(struct libvlc_log_t)); - - if( !p_log ) RAISENULL( "Out of memory" ); + struct libvlc_log_t *p_log = malloc(sizeof(*p_log)); + if (unlikely(p_log == NULL)) + { + libvlc_printerr ("Not enough memory"); + return NULL; + } 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 ) { free( p_log ); - RAISENULL( "Out of memory" ); + libvlc_printerr ("Not enough memory"); + return NULL; } libvlc_retain( p_instance ); 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, p_e ); - 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 ) { - if( p_log && p_log->p_messages ) - { - struct libvlc_log_iterator_t *p_iter = - (struct libvlc_log_iterator_t *)malloc(sizeof(struct libvlc_log_iterator_t)); + if (p_log == NULL) + return NULL; - if( !p_iter ) RAISENULL( "Out of memory" ); + struct libvlc_log_iterator_t *p_iter = malloc (sizeof (*p_iter)); + if (unlikely(p_iter == NULL)) + { + libvlc_printerr ("Not enough memory"); + return NULL; + } - 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); + /* FIXME: break constant pointer constraints */ + msg_cb_data_t *data = &((libvlc_log_t *)p_log)->data; - return p_iter; - } - RAISENULL("Invalid log object!"); + 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; } -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, - struct libvlc_log_message_t *buffer, - libvlc_exception_t *p_e ) + libvlc_log_message_t *buffer ) { - if( p_iter ) + unsigned i_pos; + + if( !p_iter ) + return NULL; + assert (buffer != NULL); + + i_pos = p_iter->i_pos; + if( i_pos != p_iter->i_end ) { - if( buffer && (sizeof(struct libvlc_log_message_t) == buffer->sizeof_msg) ) - { - int 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; - buffer->i_severity = msg->i_type; - buffer->psz_type = msg_GetObjectTypeName(msg->i_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); - - return buffer; - } - RAISENULL("No more messages"); - } - RAISENULL("Invalid message buffer!"); + msg_item_t *msg; + 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; + vlc_spin_unlock (&p_iter->p_data->lock); + p_iter->i_pos++; + + return buffer; } - RAISENULL("Invalid log iterator!"); + return NULL; } -