logger.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:11k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * logger.c : file logging plugin for vlc
  3.  *****************************************************************************
  4.  * Copyright (C) 2002 VideoLAN
  5.  * $Id: logger.c 8958 2004-10-08 10:36:25Z gbazin $
  6.  *
  7.  * Authors: Samuel Hocevar <sam@zoy.org>
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  * 
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  22.  *****************************************************************************/
  23. /*****************************************************************************
  24.  * Preamble
  25.  *****************************************************************************/
  26. #include <stdlib.h>                                      /* malloc(), free() */
  27. #include <string.h>
  28. #include <errno.h>                                                 /* ENOMEM */
  29. #include <stdio.h>
  30. #ifdef UNDER_CE
  31. #   define _IONBF 0x0004
  32. #endif
  33. #include <vlc/vlc.h>
  34. #include <vlc/intf.h>
  35. #define MODE_TEXT 0
  36. #define MODE_HTML 1
  37. #ifdef SYS_DARWIN
  38. #define LOG_DIR "Library/Logs/"
  39. #endif
  40. #define LOG_FILE_TEXT "vlc-log.txt"
  41. #define LOG_FILE_HTML "vlc-log.html"
  42. #define LOG_STRING( msg, file ) fwrite( msg, strlen( msg ), 1, file );
  43. #define TEXT_HEADER "-- logger module started --n"
  44. #define TEXT_FOOTER "-- logger module stopped --n"
  45. #define HTML_HEADER 
  46.     "<html>n" 
  47.     "  <head>n" 
  48.     "    <title>vlc log</title>n" 
  49.     "  </head>n" 
  50.     "  <body bgcolor="#000000" text="#aaaaaa">n" 
  51.     "    <pre>n" 
  52.     "      <b>-- logger module started --</b>n"
  53. #define HTML_FOOTER 
  54.     "      <b>-- logger module stopped --</b>n" 
  55.     "    </pre>n" 
  56.     "  </body>n" 
  57.     "</html>n"
  58. /*****************************************************************************
  59.  * intf_sys_t: description and status of log interface
  60.  *****************************************************************************/
  61. struct intf_sys_t
  62. {
  63.     int i_mode;
  64.     FILE *    p_file; /* The log file */
  65.     msg_subscription_t *p_sub;
  66. };
  67. /*****************************************************************************
  68.  * Local prototypes
  69.  *****************************************************************************/
  70. static int  Open    ( vlc_object_t * );                  
  71. static void Close   ( vlc_object_t * );
  72. static void Run     ( intf_thread_t * );
  73. static void FlushQueue        ( msg_subscription_t *, FILE *, int );
  74. static void TextPrint         ( const msg_item_t *, FILE * );
  75. static void HtmlPrint         ( const msg_item_t *, FILE * );
  76. /*****************************************************************************
  77.  * Module descriptor
  78.  *****************************************************************************/
  79. static char *mode_list[] = { "text", "html" };
  80. static char *mode_list_text[] = { N_("Text"), "HTML" };
  81. #define LOGMODE_TEXT N_("Log format")
  82. #define LOGMODE_LONGTEXT N_("Specify the log format. Available choices are "text" (default) and "html".")
  83. vlc_module_begin();
  84.     set_description( _("File logging interface") );
  85.     add_file( "logfile", NULL, NULL, N_("Log filename"), N_("Specify the log filename."), VLC_FALSE );
  86.     add_string( "logmode", "text", NULL, LOGMODE_TEXT, LOGMODE_LONGTEXT,
  87.                 VLC_FALSE );
  88.         change_string_list( mode_list, mode_list_text, 0 );
  89.     set_capability( "interface", 0 );
  90.     set_callbacks( Open, Close );
  91. vlc_module_end();
  92. /*****************************************************************************
  93.  * Open: initialize and create stuff
  94.  *****************************************************************************/
  95. static int Open( vlc_object_t *p_this )
  96. {   
  97.     intf_thread_t *p_intf = (intf_thread_t *)p_this;
  98.     char *psz_mode, *psz_file;
  99.     CONSOLE_INTRO_MSG;
  100.     msg_Info( p_intf, "Using the logger interface module..." );
  101.     /* Allocate instance and initialize some members */
  102.     p_intf->p_sys = (intf_sys_t *)malloc( sizeof( intf_sys_t ) );
  103.     if( p_intf->p_sys == NULL )
  104.     {
  105.         msg_Err( p_intf, "out of memory" );
  106.         return -1;
  107.     }
  108.     psz_mode = config_GetPsz( p_intf, "logmode" );
  109.     if( psz_mode )
  110.     {
  111.         if( !strcmp( psz_mode, "text" ) )
  112.         {
  113.             p_intf->p_sys->i_mode = MODE_TEXT;
  114.         }
  115.         else if( !strcmp( psz_mode, "html" ) )
  116.         {
  117.             p_intf->p_sys->i_mode = MODE_HTML;
  118.         }
  119.         else
  120.         {
  121.             msg_Err( p_intf, "invalid log mode `%s', using `text'", psz_mode );
  122.             p_intf->p_sys->i_mode = MODE_TEXT;
  123.         }
  124.         free( psz_mode );
  125.     }
  126.     else
  127.     {
  128.         msg_Warn( p_intf, "no log mode specified, using `text'" );
  129.         p_intf->p_sys->i_mode = MODE_TEXT;
  130.     }
  131.     psz_file = config_GetPsz( p_intf, "logfile" );
  132.     if( !psz_file )
  133.     {
  134. #ifdef SYS_DARWIN
  135. char *psz_homedir = p_this->p_vlc->psz_homedir; 
  136.         if( !psz_homedir )
  137.         {
  138.             msg_Err( p_this, "psz_homedir is null" );
  139.             return -1;
  140.         }
  141.         psz_file = (char *)malloc( sizeof("/" LOG_DIR "/" LOG_FILE_HTML) +
  142.                                        strlen(psz_homedir) );
  143.         if( psz_file )
  144.         {
  145.             switch( p_intf->p_sys->i_mode )
  146.             {
  147.             case MODE_HTML:
  148.                 sprintf( psz_file, "%s/" LOG_DIR "/" LOG_FILE_HTML,
  149.                      psz_homedir );
  150.                 break;
  151.             case MODE_TEXT:
  152.             default:
  153.                 sprintf( psz_file, "%s/" LOG_DIR "/" LOG_FILE_TEXT,
  154.                      psz_homedir );
  155.                 break;
  156.             }
  157.         }
  158. #else
  159. switch( p_intf->p_sys->i_mode )
  160.         {
  161.         case MODE_HTML:
  162.             psz_file = strdup( LOG_FILE_HTML );
  163.             break;
  164.         case MODE_TEXT:
  165.         default:
  166.             psz_file = strdup( LOG_FILE_TEXT );
  167.             break;
  168.         }
  169. #endif
  170.         msg_Warn( p_intf, "no log filename provided, using `%s'", psz_file );
  171.     }
  172.     /* Open the log file and remove any buffering for the stream */
  173.     msg_Dbg( p_intf, "opening logfile `%s'", psz_file );
  174.     p_intf->p_sys->p_file = fopen( psz_file, "wt" );
  175.     if( p_intf->p_sys->p_file == NULL )
  176.     {
  177.         msg_Err( p_intf, "error opening logfile `%s'", psz_file );
  178.         free( p_intf->p_sys );
  179.         free( psz_file );
  180.         return -1;
  181.     }
  182.     setvbuf( p_intf->p_sys->p_file, NULL, _IONBF, 0 );
  183.     p_intf->p_sys->p_sub = msg_Subscribe( p_intf );
  184.     free( psz_file );
  185.     switch( p_intf->p_sys->i_mode )
  186.     {
  187.     case MODE_HTML:
  188.         LOG_STRING( HTML_HEADER, p_intf->p_sys->p_file );
  189.         break;
  190.     case MODE_TEXT:
  191.     default:
  192.         LOG_STRING( TEXT_HEADER, p_intf->p_sys->p_file );
  193.         break;
  194.     }
  195.     p_intf->pf_run = Run;
  196.     return 0;
  197. }
  198. /*****************************************************************************
  199.  * Close: destroy interface stuff
  200.  *****************************************************************************/
  201. static void Close( vlc_object_t *p_this )
  202. {       
  203.     intf_thread_t *p_intf = (intf_thread_t *)p_this;
  204.         
  205.     /* Flush the queue and unsubscribe from the message queue */
  206.     FlushQueue( p_intf->p_sys->p_sub, p_intf->p_sys->p_file,
  207.                 p_intf->p_sys->i_mode );
  208.     msg_Unsubscribe( p_intf, p_intf->p_sys->p_sub );
  209.     switch( p_intf->p_sys->i_mode )
  210.     {
  211.     case MODE_HTML:
  212.         LOG_STRING( HTML_FOOTER, p_intf->p_sys->p_file );
  213.         break;
  214.     case MODE_TEXT:
  215.     default:
  216.         LOG_STRING( TEXT_FOOTER, p_intf->p_sys->p_file );
  217.         break;
  218.     }
  219.     /* Close the log file */
  220.     fclose( p_intf->p_sys->p_file );
  221.     /* Destroy structure */
  222.     free( p_intf->p_sys );
  223. }
  224. /*****************************************************************************
  225.  * Run: rc thread
  226.  *****************************************************************************
  227.  * This part of the interface is in a separate thread so that we can call
  228.  * exec() from within it without annoying the rest of the program.
  229.  *****************************************************************************/
  230. static void Run( intf_thread_t *p_intf )
  231. {
  232.     while( !p_intf->b_die )
  233.     {
  234.         FlushQueue( p_intf->p_sys->p_sub, p_intf->p_sys->p_file,
  235.                     p_intf->p_sys->i_mode );
  236.         msleep( INTF_IDLE_SLEEP );
  237.     }
  238. }
  239. /*****************************************************************************
  240.  * FlushQueue: flush the message queue into the log file
  241.  *****************************************************************************/
  242. static void FlushQueue( msg_subscription_t *p_sub, FILE *p_file, int i_mode )
  243. {
  244.     int i_start, i_stop;
  245.     vlc_mutex_lock( p_sub->p_lock );
  246.     i_stop = *p_sub->pi_stop;
  247.     vlc_mutex_unlock( p_sub->p_lock );
  248.     if( p_sub->i_start != i_stop )
  249.     {
  250.         /* Append all messages to log file */
  251.         for( i_start = p_sub->i_start;
  252.              i_start != i_stop;
  253.              i_start = (i_start+1) % VLC_MSG_QSIZE )
  254.         {
  255.             switch( i_mode )
  256.             {
  257.             case MODE_HTML:
  258.                 HtmlPrint( &p_sub->p_msg[i_start], p_file );
  259.                 break;
  260.             case MODE_TEXT:
  261.             default:
  262.                 TextPrint( &p_sub->p_msg[i_start], p_file );
  263.                 break;
  264.             }
  265.         }
  266.         vlc_mutex_lock( p_sub->p_lock );
  267.         p_sub->i_start = i_start;
  268.         vlc_mutex_unlock( p_sub->p_lock );
  269.     }
  270. }
  271. static const char *ppsz_type[4] = { ": ", " error: ",
  272.                                     " warning: ", " debug: " };
  273. static void TextPrint( const msg_item_t *p_msg, FILE *p_file )
  274. {
  275.     LOG_STRING( p_msg->psz_module, p_file );
  276.     LOG_STRING( ppsz_type[p_msg->i_type], p_file );
  277.     LOG_STRING( p_msg->psz_msg, p_file );
  278.     LOG_STRING( "n", p_file );
  279. }
  280. static void HtmlPrint( const msg_item_t *p_msg, FILE *p_file )
  281. {
  282.     static const char *ppsz_color[4] = { "<font color="#ffffff">",
  283.                                          "<font color="#ff6666">",
  284.                                          "<font color="#ffff66">",
  285.                                          "<font color="#aaaaaa">" };
  286.     LOG_STRING( p_msg->psz_module, p_file );
  287.     LOG_STRING( ppsz_type[p_msg->i_type], p_file );
  288.     LOG_STRING( ppsz_color[p_msg->i_type], p_file );
  289.     LOG_STRING( p_msg->psz_msg, p_file );
  290.     LOG_STRING( "</font>n", p_file );
  291. }