00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include <stdio.h>
00031 #include <stdarg.h>
00032 #include <stdlib.h>
00033 #include <string.h>
00034
00035 #include <vlc/vlc.h>
00036
00037 #ifdef HAVE_FCNTL_H
00038 # include <fcntl.h>
00039 #endif
00040
00041 #include <errno.h>
00042
00043 #ifdef HAVE_UNISTD_H
00044 # include <unistd.h>
00045 #endif
00046
00047 #include "vlc_interface.h"
00048
00049
00050
00051
00052 #if defined(HAVE_VA_COPY)
00053 # define vlc_va_copy(dest,src) va_copy(dest,src)
00054 #elif defined(HAVE___VA_COPY)
00055 # define vlc_va_copy(dest,src) __va_copy(dest,src)
00056 #else
00057 # define vlc_va_copy(dest,src) (dest)=(src)
00058 #endif
00059
00060
00061
00062
00063 static void QueueMsg ( vlc_object_t *, int , const char *,
00064 const char *, va_list );
00065 static void FlushMsg ( msg_bank_t * );
00066 static void PrintMsg ( vlc_object_t *, msg_item_t * );
00067
00074 void __msg_Create( vlc_object_t *p_this )
00075 {
00076
00077 vlc_mutex_init( p_this, &p_this->p_libvlc->msg_bank.lock );
00078
00079 p_this->p_libvlc->msg_bank.b_configured = VLC_FALSE;
00080 p_this->p_libvlc->msg_bank.b_overflow = VLC_FALSE;
00081
00082 p_this->p_libvlc->msg_bank.i_start = 0;
00083 p_this->p_libvlc->msg_bank.i_stop = 0;
00084
00085 p_this->p_libvlc->msg_bank.i_sub = 0;
00086 p_this->p_libvlc->msg_bank.pp_sub = NULL;
00087
00088 #ifdef UNDER_CE
00089 p_this->p_libvlc->msg_bank.logfile =
00090 CreateFile( L"vlc-log.txt", GENERIC_WRITE,
00091 FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
00092 CREATE_ALWAYS, 0, NULL );
00093 SetFilePointer( p_this->p_libvlc->msg_bank.logfile, 0, NULL, FILE_END );
00094 #endif
00095 }
00096
00100 void __msg_Flush( vlc_object_t *p_this )
00101 {
00102 vlc_mutex_lock( &p_this->p_libvlc->msg_bank.lock );
00103
00104 p_this->p_libvlc->msg_bank.b_configured = VLC_TRUE;
00105
00106 #if 0
00107
00108 for( i_index = p_this->p_libvlc->msg_bank.i_start;
00109 i_index != p_this->p_libvlc->msg_bank.i_stop;
00110 i_index = (i_index+1) % VLC_MSG_QSIZE )
00111 {
00112 PrintMsg( p_this, &p_this->p_libvlc->msg_bank.msg[i_index] );
00113 }
00114 #endif
00115
00116 FlushMsg( &p_this->p_libvlc->msg_bank );
00117
00118 vlc_mutex_unlock( &p_this->p_libvlc->msg_bank.lock );
00119 }
00120
00128 void __msg_Destroy( vlc_object_t *p_this )
00129 {
00130 if( p_this->p_libvlc->msg_bank.i_sub )
00131 {
00132 msg_Err( p_this, "stale interface subscribers" );
00133 }
00134
00135
00136 if( !p_this->p_libvlc->msg_bank.b_configured )
00137 {
00138 msg_Flush( p_this );
00139 }
00140 else
00141 {
00142 FlushMsg( &p_this->p_libvlc->msg_bank );
00143 }
00144
00145 #ifdef UNDER_CE
00146 CloseHandle( p_this->p_libvlc->msg_bank.logfile );
00147 #endif
00148
00149
00150 vlc_mutex_destroy( &p_this->p_libvlc->msg_bank.lock );
00151 }
00152
00156 msg_subscription_t *__msg_Subscribe( vlc_object_t *p_this )
00157 {
00158 msg_bank_t *p_bank = &p_this->p_libvlc->msg_bank;
00159 msg_subscription_t *p_sub = malloc( sizeof( msg_subscription_t ) );
00160
00161 vlc_mutex_lock( &p_bank->lock );
00162
00163
00164 INSERT_ELEM( p_bank->pp_sub, p_bank->i_sub, p_bank->i_sub, p_sub );
00165
00166 p_sub->i_start = p_bank->i_start;
00167 p_sub->pi_stop = &p_bank->i_stop;
00168
00169 p_sub->p_msg = p_bank->msg;
00170 p_sub->p_lock = &p_bank->lock;
00171
00172 vlc_mutex_unlock( &p_bank->lock );
00173
00174 return p_sub;
00175 }
00176
00180 void __msg_Unsubscribe( vlc_object_t *p_this, msg_subscription_t *p_sub )
00181 {
00182 msg_bank_t *p_bank = &p_this->p_libvlc->msg_bank;
00183 int i_index;
00184
00185 vlc_mutex_lock( &p_bank->lock );
00186
00187
00188 if( !p_bank->i_sub )
00189 {
00190 msg_Err( p_this, "no subscriber in the list" );
00191 return;
00192 }
00193
00194
00195 for( i_index = 0; i_index < p_bank->i_sub; i_index++ )
00196 {
00197 if( p_bank->pp_sub[ i_index ] == p_sub )
00198 {
00199 break;
00200 }
00201 }
00202
00203 if( p_bank->pp_sub[ i_index ] != p_sub )
00204 {
00205 msg_Err( p_this, "subscriber not found" );
00206 vlc_mutex_unlock( &p_bank->lock );
00207 return;
00208 }
00209
00210
00211 REMOVE_ELEM( p_bank->pp_sub, p_bank->i_sub, i_index );
00212
00213 if( p_sub ) free( p_sub );
00214 vlc_mutex_unlock( &p_bank->lock );
00215 }
00216
00217
00218
00219
00220
00221
00222 void __msg_Generic( vlc_object_t *p_this, int i_type, const char *psz_module,
00223 const char *psz_format, ... )
00224 {
00225 va_list args;
00226
00227 va_start( args, psz_format );
00228 QueueMsg( p_this, i_type, psz_module, psz_format, args );
00229 va_end( args );
00230 }
00231
00232 void __msg_GenericVa( vlc_object_t *p_this, int i_type, const char *psz_module,
00233 const char *psz_format, va_list args )
00234 {
00235 QueueMsg( p_this, i_type, psz_module, psz_format, args );
00236 }
00237
00238
00239 #define DECLARE_MSG_FN( FN_NAME, FN_TYPE ) \
00240 void FN_NAME( vlc_object_t *p_this, const char *psz_format, ... ) \
00241 { \
00242 va_list args; \
00243 va_start( args, psz_format ); \
00244 QueueMsg( (vlc_object_t *)p_this, FN_TYPE, "unknown", \
00245 psz_format, args ); \
00246 va_end( args ); \
00247 } \
00248 struct _
00249
00254 DECLARE_MSG_FN( __msg_Info, VLC_MSG_INFO );
00258 DECLARE_MSG_FN( __msg_Err, VLC_MSG_ERR );
00262 DECLARE_MSG_FN( __msg_Warn, VLC_MSG_WARN );
00266 DECLARE_MSG_FN( __msg_Dbg, VLC_MSG_DBG );
00267
00276 static void QueueMsg( vlc_object_t *p_this, int i_type, const char *psz_module,
00277 const char *psz_format, va_list _args )
00278 {
00279 msg_bank_t * p_bank = &p_this->p_libvlc->msg_bank;
00280 char * psz_str = NULL;
00281 va_list args;
00282 msg_item_t * p_item = NULL;
00283 msg_item_t item;
00284
00285 #if !defined(HAVE_VASPRINTF) || defined(SYS_DARWIN) || defined(SYS_BEOS)
00286 int i_size = strlen(psz_format) + INTF_MAX_MSG_SIZE;
00287 #endif
00288
00289
00290
00291
00292 #if defined(HAVE_VASPRINTF) && !defined(SYS_DARWIN) && !defined( SYS_BEOS )
00293 vlc_va_copy( args, _args );
00294 vasprintf( &psz_str, psz_format, args );
00295 va_end( args );
00296 #else
00297 psz_str = (char*) malloc( i_size * sizeof(char) );
00298 #endif
00299
00300 if( psz_str == NULL )
00301 {
00302 fprintf( stderr, "main warning: can't store message (%s): ",
00303 strerror(errno) );
00304 vlc_va_copy( args, _args );
00305 vfprintf( stderr, psz_format, args );
00306 va_end( args );
00307 fprintf( stderr, "\n" );
00308 return;
00309 }
00310
00311 #if !defined(HAVE_VASPRINTF) || defined(SYS_DARWIN) || defined(SYS_BEOS)
00312 vlc_va_copy( args, _args );
00313 vsnprintf( psz_str, i_size, psz_format, args );
00314 va_end( args );
00315 psz_str[ i_size - 1 ] = 0;
00316 #endif
00317
00318
00319 vlc_mutex_lock( &p_bank->lock );
00320
00321
00322 if( p_bank->b_overflow )
00323 {
00324 FlushMsg( p_bank );
00325
00326 if( ((p_bank->i_stop - p_bank->i_start + 1) % VLC_MSG_QSIZE) == 0 )
00327 {
00328
00329 p_item = &item;
00330 }
00331 else
00332 {
00333
00334 p_bank->b_overflow = VLC_FALSE;
00335 }
00336 }
00337 else if( ((p_bank->i_stop - p_bank->i_start + 2) % VLC_MSG_QSIZE) == 0 )
00338 {
00339 FlushMsg( p_bank );
00340
00341 if( ((p_bank->i_stop - p_bank->i_start + 2) % VLC_MSG_QSIZE) == 0 )
00342 {
00343 p_bank->b_overflow = VLC_TRUE;
00344
00345
00346 p_item = p_bank->msg + p_bank->i_stop;
00347 p_bank->i_stop = (p_bank->i_stop + 1) % VLC_MSG_QSIZE;
00348
00349 p_item->i_type = VLC_MSG_WARN;
00350 p_item->i_object_id = p_this->i_object_id;
00351 p_item->i_object_type = p_this->i_object_type;
00352 p_item->psz_module = strdup( "message" );
00353 p_item->psz_msg = strdup( "message queue overflowed" );
00354
00355 PrintMsg( p_this, p_item );
00356
00357
00358 p_item = &item;
00359 }
00360 }
00361
00362 if( !p_bank->b_overflow )
00363 {
00364
00365 p_item = p_bank->msg + p_bank->i_stop;
00366 p_bank->i_stop = (p_bank->i_stop + 1) % VLC_MSG_QSIZE;
00367 }
00368
00369
00370 p_item->i_type = i_type;
00371 p_item->i_object_id = p_this->i_object_id;
00372 p_item->i_object_type = p_this->i_object_type;
00373 p_item->psz_module = strdup( psz_module );
00374 p_item->psz_msg = psz_str;
00375
00376 PrintMsg( p_this, p_item );
00377
00378 if( p_bank->b_overflow )
00379 {
00380 if( p_item->psz_module )
00381 free( p_item->psz_module );
00382 if( p_item->psz_msg )
00383 free( p_item->psz_msg );
00384 }
00385
00386 vlc_mutex_unlock( &p_bank->lock );
00387 }
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397 static void FlushMsg ( msg_bank_t *p_bank )
00398 {
00399 int i_index, i_start, i_stop;
00400
00401
00402 if( !p_bank->b_configured )
00403 {
00404 return;
00405 }
00406
00407
00408 i_stop = p_bank->i_stop;
00409
00410
00411 for( i_index = 0; i_index < p_bank->i_sub; i_index++ )
00412 {
00413 i_start = p_bank->pp_sub[ i_index ]->i_start;
00414
00415
00416
00417 if( ( i_start < i_stop
00418 && (p_bank->i_stop <= i_start || i_stop <= p_bank->i_stop) )
00419 || ( i_stop < i_start
00420 && (i_stop <= p_bank->i_stop && p_bank->i_stop <= i_start) ) )
00421 {
00422 i_stop = i_start;
00423 }
00424 }
00425
00426
00427 for( i_index = p_bank->i_start;
00428 i_index != i_stop;
00429 i_index = (i_index+1) % VLC_MSG_QSIZE )
00430 {
00431 if( p_bank->msg[i_index].psz_msg )
00432 free( p_bank->msg[i_index].psz_msg );
00433 if( p_bank->msg[i_index].psz_module )
00434 free( p_bank->msg[i_index].psz_module );
00435 }
00436
00437
00438 p_bank->i_start = i_index;
00439 }
00440
00441
00442
00443
00444
00445
00446 static void PrintMsg ( vlc_object_t * p_this, msg_item_t * p_item )
00447 {
00448 # define COL(x) "\033[" #x ";1m"
00449 # define RED COL(31)
00450 # define GREEN COL(32)
00451 # define YELLOW COL(33)
00452 # define WHITE COL(37)
00453 # define GRAY "\033[0m"
00454
00455 #ifdef UNDER_CE
00456 int i_dummy;
00457 #endif
00458 static const char * ppsz_type[4] = { "", " error", " warning", " debug" };
00459 static const char *ppsz_color[4] = { WHITE, RED, YELLOW, GRAY };
00460 char *psz_object = "private";
00461 int i_type = p_item->i_type;
00462
00463 switch( i_type )
00464 {
00465 case VLC_MSG_ERR:
00466 if( p_this->p_libvlc->i_verbose < 0 ) return;
00467 break;
00468 case VLC_MSG_INFO:
00469 if( p_this->p_libvlc->i_verbose < 0 ) return;
00470 break;
00471 case VLC_MSG_WARN:
00472 if( p_this->p_libvlc->i_verbose < 1 ) return;
00473 break;
00474 case VLC_MSG_DBG:
00475 if( p_this->p_libvlc->i_verbose < 2 ) return;
00476 break;
00477 }
00478
00479 switch( p_item->i_object_type )
00480 {
00481 case VLC_OBJECT_ROOT: psz_object = "root"; break;
00482 case VLC_OBJECT_VLC: psz_object = "vlc"; break;
00483 case VLC_OBJECT_MODULE: psz_object = "module"; break;
00484 case VLC_OBJECT_INTF: psz_object = "interface"; break;
00485 case VLC_OBJECT_PLAYLIST: psz_object = "playlist"; break;
00486 case VLC_OBJECT_ITEM: psz_object = "item"; break;
00487 case VLC_OBJECT_INPUT: psz_object = "input"; break;
00488 case VLC_OBJECT_DECODER: psz_object = "decoder"; break;
00489 case VLC_OBJECT_PACKETIZER: psz_object = "packetizer"; break;
00490 case VLC_OBJECT_ENCODER: psz_object = "encoder"; break;
00491 case VLC_OBJECT_VOUT: psz_object = "video output"; break;
00492 case VLC_OBJECT_AOUT: psz_object = "audio output"; break;
00493 case VLC_OBJECT_SOUT: psz_object = "stream output"; break;
00494 case VLC_OBJECT_HTTPD: psz_object = "http daemon"; break;
00495 case VLC_OBJECT_DIALOGS: psz_object = "dialogs provider"; break;
00496 case VLC_OBJECT_VLM: psz_object = "vlm"; break;
00497 case VLC_OBJECT_ANNOUNCE: psz_object = "announce handler"; break;
00498 case VLC_OBJECT_DEMUX: psz_object = "demuxer"; break;
00499 case VLC_OBJECT_ACCESS: psz_object = "access"; break;
00500 }
00501
00502 #ifdef UNDER_CE
00503 # define CE_WRITE(str) WriteFile( p_this->p_libvlc->msg_bank.logfile, \
00504 str, strlen(str), &i_dummy, NULL );
00505 CE_WRITE( p_item->psz_module );
00506 CE_WRITE( " " );
00507 CE_WRITE( psz_object );
00508 CE_WRITE( ppsz_type[i_type] );
00509 CE_WRITE( ": " );
00510 CE_WRITE( p_item->psz_msg );
00511 CE_WRITE( "\r\n" );
00512 FlushFileBuffers( p_this->p_libvlc->msg_bank.logfile );
00513
00514 #else
00515
00516 if( p_this->p_libvlc->b_color )
00517 {
00518 fprintf( stderr, "[" GREEN "%.8i" GRAY "] %s %s%s: %s%s" GRAY "\n",
00519 p_item->i_object_id, p_item->psz_module, psz_object,
00520 ppsz_type[i_type], ppsz_color[i_type],
00521 p_item->psz_msg );
00522 }
00523 else
00524 {
00525 fprintf( stderr, "[%.8i] %s %s%s: %s\n", p_item->i_object_id,
00526 p_item->psz_module, psz_object, ppsz_type[i_type],
00527 p_item->psz_msg );
00528 }
00529
00530 # if defined(WIN32)
00531 fflush( stderr );
00532 # endif
00533 #endif
00534 }