1 /*****************************************************************************
2 * audiobargraph_a.c : audiobargraph audio plugin for vlc
3 *****************************************************************************
4 * Copyright (C) 2002-2009 the VideoLAN team
7 * Authors: Clement CHESNIN <clement.chesnin@gmail.com>
8 * Philippe COENT <philippe.coent@tdf.fr>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
32 #include <vlc_common.h>
33 #include <vlc_plugin.h>
35 #include <vlc_filter.h>
37 #include <vlc_network.h>
40 #define ADDRESS_TEXT N_("TCP address to use (default localhost)")
41 #define ADDRESS_LONGTEXT N_("TCP address to use to communicate with the video "\
42 "part of the Bar Graph (default localhost). " \
43 "In the case of bargraph incrustation, use localhost." )
44 #define PORT_TEXT N_("TCP port to use (default 12345)")
45 #define PORT_LONGTEXT N_("TCP port to use to communicate with the video "\
46 "part of the Bar Graph (default 12345). " \
47 "Use the same port as the one used in the rc interface." )
48 #define BARGRAPH_TEXT N_("Defines if BarGraph information should be sent (default 1)")
49 #define BARGRAPH_LONGTEXT N_("Defines if BarGraph information should be sent. "\
50 "1 if the information should be sent, 0 otherwise (default 1)." )
51 #define BARGRAPH_REPETITION_TEXT N_("Sends the barGraph information every n audio packets (default 4)")
52 #define BARGRAPH_REPETITION_LONGTEXT N_("Defines how often the barGraph information should be sent. "\
53 "Sends the barGraph information every n audio packets (default 4)." )
54 #define SILENCE_TEXT N_("Defines if silence alarm information should be sent (default 1)")
55 #define SILENCE_LONGTEXT N_("Defines if silence alarm information should be sent. "\
56 "1 if the information should be sent, 0 otherwise (default 1)." )
57 #define TIME_WINDOW_TEXT N_("Time window to use in ms (default 5000)")
58 #define TIME_WINDOW_LONGTEXT N_("Time Window during when the audio level is measured in ms for silence detection. "\
59 "If the audio level is under the threshold during this time, "\
60 "an alarm is sent (default 5000)." )
61 #define ALARM_THRESHOLD_TEXT N_("Minimum Audio level to raise the alarm (default 0.1)")
62 #define ALARM_THRESHOLD_LONGTEXT N_("Threshold to be attained to raise an alarm. "\
63 "If the audio level is under the threshold during this time, "\
64 "an alarm is sent (default 0.1)." )
65 #define REPETITION_TIME_TEXT N_("Time between two alarm messages in ms (default 2000)" )
66 #define REPETITION_TIME_LONGTEXT N_("Time between two alarm messages in ms. "\
67 "This value is used to avoid alarm saturation (default 2000)." )
68 #define CONNECTION_RESET_TEXT N_("Force connection reset regularly (default 1)" )
69 #define CONNECTION_RESET_LONGTEXT N_("Defines if the TCP connection should be reset. "\
70 "This is to be used when using with audiobargraph_v (default 1)." )
72 #define CFG_PREFIX "audiobargraph_a-"
74 /*****************************************************************************
76 *****************************************************************************/
77 static int Open( vlc_object_t * );
78 static void Close( vlc_object_t * );
79 static block_t *DoWork( filter_t *, block_t * );
82 set_description( N_("Audio part of the BarGraph function") )
83 set_shortname( N_("Audiobar Graph") )
84 set_capability( "audio filter", 0 )
85 set_category( CAT_AUDIO )
86 set_subcategory( SUBCAT_AUDIO_AFILTER )
88 add_string( CFG_PREFIX "address", "localhost", ADDRESS_TEXT, ADDRESS_LONGTEXT, false )
89 add_integer( CFG_PREFIX "port", 12345, PORT_TEXT, PORT_LONGTEXT, false )
90 add_integer( CFG_PREFIX "bargraph", 1, BARGRAPH_TEXT, BARGRAPH_LONGTEXT, false )
91 add_integer( CFG_PREFIX "bargraph_repetition", 4, BARGRAPH_REPETITION_TEXT, BARGRAPH_REPETITION_LONGTEXT, false )
92 add_integer( CFG_PREFIX "silence", 1, SILENCE_TEXT, SILENCE_LONGTEXT, false )
93 add_integer( CFG_PREFIX "time_window", 5000, TIME_WINDOW_TEXT, TIME_WINDOW_LONGTEXT, false )
94 add_float( CFG_PREFIX "alarm_threshold", 0.1, ALARM_THRESHOLD_TEXT, ALARM_THRESHOLD_LONGTEXT, false )
95 add_integer( CFG_PREFIX "repetition_time", 2000, REPETITION_TIME_TEXT, REPETITION_TIME_LONGTEXT, false )
96 add_integer( CFG_PREFIX "connection_reset", 1, CONNECTION_RESET_TEXT, CONNECTION_RESET_LONGTEXT, false )
98 set_callbacks( Open, Close )
101 typedef struct ValueDate_t {
104 struct ValueDate_t* next;
112 int bargraph_repetition;
115 float alarm_threshold;
117 int connection_reset;
127 /*****************************************************************************
128 * Open: open the visualizer
129 *****************************************************************************/
130 static int Open( vlc_object_t *p_this )
132 filter_t *p_filter = (filter_t *)p_this;
135 if ( !AOUT_FMTS_SIMILAR( &p_filter->fmt_in.audio, &p_filter->fmt_out.audio ) )
137 msg_Err( p_filter, "input and output formats are not similar" );
141 if( p_filter->fmt_in.audio.i_format != VLC_CODEC_FL32 ||
142 p_filter->fmt_out.audio.i_format != VLC_CODEC_FL32 )
144 p_filter->fmt_in.audio.i_format = VLC_CODEC_FL32;
145 p_filter->fmt_out.audio.i_format = VLC_CODEC_FL32;
146 msg_Warn( p_filter, "bad input or output format" );
149 p_filter->pf_audio_filter = DoWork;
151 p_sys = p_filter->p_sys = malloc( sizeof( *p_sys ) );
155 p_sys->bargraph = var_CreateGetIntegerCommand( p_filter, "audiobargraph_a-bargraph" );
156 p_sys->bargraph_repetition = var_CreateGetIntegerCommand( p_filter, "audiobargraph_a-bargraph_repetition" );
157 p_sys->silence = var_CreateGetIntegerCommand( p_filter, "audiobargraph_a-silence" );
158 p_sys->address = var_CreateGetStringCommand( p_filter, "audiobargraph_a-address" );
159 p_sys->port = var_CreateGetIntegerCommand( p_filter, "audiobargraph_a-port" );
160 p_sys->time_window = var_CreateGetIntegerCommand( p_filter, "audiobargraph_a-time_window" );
161 p_sys->alarm_threshold = var_CreateGetFloatCommand( p_filter, "audiobargraph_a-alarm_threshold" );
162 p_sys->repetition_time = var_CreateGetIntegerCommand( p_filter, "audiobargraph_a-repetition_time" );
163 p_sys->connection_reset = var_CreateGetIntegerCommand( p_filter, "audiobargraph_a-connection_reset" );
164 if ((p_sys->TCPconnection = net_ConnectTCP(p_this,p_sys->address,p_sys->port)) == -1) {
169 p_sys->nbChannels = 0;
173 p_sys->lastAlarm = 0;
178 /*****************************************************************************
179 * DoWork: treat an audio buffer
180 ****************************************************************************/
181 static block_t *DoWork( filter_t *p_filter, block_t *p_in_buf )
183 filter_sys_t *p_sys = p_filter->p_sys;
185 float *p_sample = (float *)p_in_buf->p_buffer;
186 float *i_value = NULL;
189 //char *message = (char*)malloc(255*sizeof(char));
192 ValueDate_t* new = NULL;
193 ValueDate_t* current = NULL;
197 nbChannels = aout_FormatNbChannels( &p_filter->fmt_in.audio );
198 p_sys->nbChannels = nbChannels;
200 i_value = (float*)malloc(nbChannels * sizeof(float));
202 for (i=0; i<nbChannels; i++) {
206 /* 1 - Compute the peack values */
207 for ( i = 0 ; i < (int)(p_in_buf->i_nb_samples); i++ )
209 for (j=0; j<nbChannels; j++) {
219 if (p_sys->silence) {
220 /* 2 - store the new value */
221 new = (ValueDate_t*)malloc(sizeof(ValueDate_t));
223 new->date = p_in_buf->i_pts;
225 if (p_sys->last != NULL) {
226 p_sys->last->next = new;
229 if (p_sys->first == NULL) {
233 /* 3 - delete too old values */
234 while (p_sys->first->date < (new->date - (p_sys->time_window*1000))) {
235 p_sys->started = 1; // we have enough values to compute a valid total
236 current = p_sys->first;
237 p_sys->first = p_sys->first->next;
241 /* If last message was sent enough time ago */
242 if ((p_sys->started) && (p_in_buf->i_pts > p_sys->lastAlarm + (p_sys->repetition_time*1000))) {
244 /* 4 - compute the RMS */
245 current = p_sys->first;
247 while (current != NULL) {
248 sum += current->value;
250 current = current->next;
255 /* 5 - compare it to the threshold */
256 if (sum < p_sys->alarm_threshold) {
261 snprintf(message,255,"@audiobargraph_v audiobargraph_v-alarm %d\n",i);
263 msg_Dbg( p_filter, "message alarm : %s", message );
264 //TCPconnection = net_ConnectTCP(p_filter,p_sys->address,p_sys->port);
265 net_Write(p_filter, p_sys->TCPconnection, NULL, message, strlen(message));
266 //net_Close(TCPconnection);
268 p_sys->lastAlarm = p_in_buf->i_pts;
272 /*for (i=0; i<nbChannels; i++) {
273 value[i] = abs(i_value[i]*100);
274 if ( value[i] > p_sys->value[i] - 6 )
275 p_sys->value[i] = value[i];
277 p_sys->value[i] = p_sys->value[i] - 6;
280 if (p_sys->bargraph) {
281 /* 6 - sent the message with the values for the BarGraph */
282 if ((nbChannels > 0) && (p_sys->counter%(p_sys->bargraph_repetition) == 0)) {
283 j=snprintf(message,255,"@audiobargraph_v audiobargraph_v-i_values ");
284 for (i=0; i<(nbChannels-1); i++) {
285 j+=snprintf(message+j,255,"%f:", i_value[i]);
287 snprintf(message+j,255,"%f\n", i_value[nbChannels-1]);
288 msg_Dbg( p_filter, "message values : %s", message );
290 //test = send(p_sys->TCPconnection,message,strlen(message),0);
291 //net_Write(p_filter, p_sys->TCPconnection, NULL, message, strlen(message));
293 net_Write(p_filter, p_sys->TCPconnection, NULL, message, strlen(message));
300 if (p_sys->counter > p_sys->bargraph_repetition*100) {
301 if (p_sys->connection_reset) {
302 net_Close(p_sys->TCPconnection);
303 p_sys->TCPconnection = net_ConnectTCP(p_filter,p_sys->address,p_sys->port);
314 /*****************************************************************************
315 * Close: close the plugin
316 *****************************************************************************/
317 static void Close( vlc_object_t *p_this )
319 filter_t * p_filter = (filter_t *)p_this;
320 filter_sys_t *p_sys = p_filter->p_sys;
321 ValueDate_t* current;
324 while (p_sys->first != NULL) {
325 current = p_sys->first;
326 p_sys->first = p_sys->first->next;
329 net_Close(p_sys->TCPconnection);
330 free(p_sys->address);
331 //free(p_sys->value);
332 free( p_filter->p_sys );