1 /*****************************************************************************
2 * audiobargraph_a.c : audiobargraph audio plugin for vlc
3 *****************************************************************************
4 * Copyright (C) 2002-2009 VLC authors and VideoLAN
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 it
11 * under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this program; if not, write to the Free Software Foundation,
22 * 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")
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")
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")
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")
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")
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")
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")
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" )
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" )
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;
133 filter_sys_t *p_sys = p_filter->p_sys = malloc( sizeof( *p_sys ) );
137 p_sys->bargraph = var_CreateGetIntegerCommand( p_filter, "audiobargraph_a-bargraph" );
138 p_sys->bargraph_repetition = var_CreateGetIntegerCommand( p_filter, "audiobargraph_a-bargraph_repetition" );
139 p_sys->silence = var_CreateGetIntegerCommand( p_filter, "audiobargraph_a-silence" );
140 p_sys->address = var_CreateGetStringCommand( p_filter, "audiobargraph_a-address" );
141 p_sys->port = var_CreateGetIntegerCommand( p_filter, "audiobargraph_a-port" );
142 p_sys->time_window = var_CreateGetIntegerCommand( p_filter, "audiobargraph_a-time_window" );
143 p_sys->alarm_threshold = var_CreateGetFloatCommand( p_filter, "audiobargraph_a-alarm_threshold" );
144 p_sys->repetition_time = var_CreateGetIntegerCommand( p_filter, "audiobargraph_a-repetition_time" );
145 p_sys->connection_reset = var_CreateGetIntegerCommand( p_filter, "audiobargraph_a-connection_reset" );
146 if ((p_sys->TCPconnection = net_ConnectTCP(p_this,p_sys->address,p_sys->port)) == -1) {
151 p_sys->nbChannels = 0;
155 p_sys->lastAlarm = 0;
157 p_filter->fmt_in.audio.i_format = VLC_CODEC_FL32;
158 p_filter->fmt_out.audio = p_filter->fmt_in.audio;
159 p_filter->pf_audio_filter = DoWork;
164 /*****************************************************************************
165 * DoWork: treat an audio buffer
166 ****************************************************************************/
167 static block_t *DoWork( filter_t *p_filter, block_t *p_in_buf )
169 filter_sys_t *p_sys = p_filter->p_sys;
171 float *p_sample = (float *)p_in_buf->p_buffer;
172 float *i_value = NULL;
175 //char *message = (char*)malloc(255*sizeof(char));
178 ValueDate_t* new = NULL;
179 ValueDate_t* current = NULL;
183 nbChannels = aout_FormatNbChannels( &p_filter->fmt_in.audio );
184 p_sys->nbChannels = nbChannels;
186 i_value = (float*)malloc(nbChannels * sizeof(float));
188 for (i=0; i<nbChannels; i++) {
192 /* 1 - Compute the peack values */
193 for ( i = 0 ; i < (int)(p_in_buf->i_nb_samples); i++ )
195 for (j=0; j<nbChannels; j++) {
205 if (p_sys->silence) {
206 /* 2 - store the new value */
207 new = (ValueDate_t*)malloc(sizeof(ValueDate_t));
209 new->date = p_in_buf->i_pts;
211 if (p_sys->last != NULL) {
212 p_sys->last->next = new;
215 if (p_sys->first == NULL) {
219 /* 3 - delete too old values */
220 while (p_sys->first->date < (new->date - (p_sys->time_window*1000))) {
221 p_sys->started = 1; // we have enough values to compute a valid total
222 current = p_sys->first;
223 p_sys->first = p_sys->first->next;
227 /* If last message was sent enough time ago */
228 if ((p_sys->started) && (p_in_buf->i_pts > p_sys->lastAlarm + (p_sys->repetition_time*1000))) {
230 /* 4 - compute the RMS */
231 current = p_sys->first;
233 while (current != NULL) {
234 sum += current->value;
236 current = current->next;
241 /* 5 - compare it to the threshold */
242 if (sum < p_sys->alarm_threshold) {
247 snprintf(message,255,"@audiobargraph_v audiobargraph_v-alarm %d\n",i);
249 msg_Dbg( p_filter, "message alarm : %s", message );
250 //TCPconnection = net_ConnectTCP(p_filter,p_sys->address,p_sys->port);
251 net_Write(p_filter, p_sys->TCPconnection, NULL, message, strlen(message));
252 //net_Close(TCPconnection);
254 p_sys->lastAlarm = p_in_buf->i_pts;
258 /*for (i=0; i<nbChannels; i++) {
259 value[i] = abs(i_value[i]*100);
260 if ( value[i] > p_sys->value[i] - 6 )
261 p_sys->value[i] = value[i];
263 p_sys->value[i] = p_sys->value[i] - 6;
266 if (p_sys->bargraph) {
267 /* 6 - sent the message with the values for the BarGraph */
268 if ((nbChannels > 0) && (p_sys->counter%(p_sys->bargraph_repetition) == 0)) {
269 j=snprintf(message,255,"@audiobargraph_v audiobargraph_v-i_values ");
270 for (i=0; i<(nbChannels-1); i++) {
271 j+=snprintf(message+j,255,"%f:", i_value[i]);
273 snprintf(message+j,255,"%f\n", i_value[nbChannels-1]);
274 msg_Dbg( p_filter, "message values : %s", message );
276 //test = send(p_sys->TCPconnection,message,strlen(message),0);
277 //net_Write(p_filter, p_sys->TCPconnection, NULL, message, strlen(message));
279 net_Write(p_filter, p_sys->TCPconnection, NULL, message, strlen(message));
286 if (p_sys->counter > p_sys->bargraph_repetition*100) {
287 if (p_sys->connection_reset) {
288 net_Close(p_sys->TCPconnection);
289 p_sys->TCPconnection = net_ConnectTCP(p_filter,p_sys->address,p_sys->port);
300 /*****************************************************************************
301 * Close: close the plugin
302 *****************************************************************************/
303 static void Close( vlc_object_t *p_this )
305 filter_t * p_filter = (filter_t *)p_this;
306 filter_sys_t *p_sys = p_filter->p_sys;
307 ValueDate_t* current;
310 while (p_sys->first != NULL) {
311 current = p_sys->first;
312 p_sys->first = p_sys->first->next;
315 net_Close(p_sys->TCPconnection);
316 free(p_sys->address);
317 //free(p_sys->value);
318 free( p_filter->p_sys );