New Version 1.6
[lcr.git] / action_vbox.cpp
1 /*****************************************************************************\
2 **                                                                           **
3 ** PBX4Linux                                                                 **
4 **                                                                           **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg                                              **
7 **                                                                           **
8 ** dialing for answering machine is processed here                           **
9 **                                                                           **
10 \*****************************************************************************/ 
11
12 #include "main.h"
13
14
15 // note: the given display message (e_vbox_display) may include "%s" for the counter
16
17 /*
18  * these are the state, the vbox is in. if the current tone has been played,
19  * an action will be calles as defined in vbox_message_eof(), which is called 
20  * from Epoint:handler().
21  * also this state is used to determine the correct processing of the current key press
22  */
23 enum {
24         VBOX_STATE_MENU,                /* tell the menu */
25 VBOX_STATE_CALLINFO_BEGIN, /* this value defines the start of callinfo */
26         VBOX_STATE_CALLINFO_INTRO,      /* tell that the "call is received at" */
27         VBOX_STATE_CALLINFO_MONTH,      /* tell the month */
28         VBOX_STATE_CALLINFO_DAY,        /* tell the day */
29         VBOX_STATE_CALLINFO_HOUR,       /* tell the hour */
30         VBOX_STATE_CALLINFO_OCLOCK,     /* tell the word "o'clock" */
31         VBOX_STATE_CALLINFO_MIN,        /* tell the minute */
32         VBOX_STATE_CALLINFO_MINUTES,    /* tell the word "minutes" */
33         VBOX_STATE_CALLINFO_DIGIT,      /* tell the digits */
34 VBOX_STATE_CALLINFO_END, /* this value defines the end of callingo */
35         VBOX_STATE_NOTHING,             /* tells that no calls are recorded */
36         VBOX_STATE_PLAY,                /* play the current recording */
37         VBOX_STATE_PAUSE,               /* tell that the recording is paused */
38         VBOX_STATE_RECORD_ASK,  /* ask for recording */ 
39         VBOX_STATE_RECORD_PLAY, /* play recording */    
40         VBOX_STATE_RECORD_RECORD,       /* record recording */  
41         VBOX_STATE_STORE_ASK,   /* ask for store */
42         VBOX_STATE_DELETE_ASK,  /* ask for delete */
43         VBOX_STATE_STORE_DONE,  /* tell that message is store */
44         VBOX_STATE_DELETE_DONE, /* tell that message is delete */
45 };
46
47 const char *months_english[] = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
48 const char *months_german[] = {"Jan","Feb","Maer","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"};
49
50 struct vbox_menu {
51         const char digit;
52         const char *english;
53         const char *german;
54 } vbox_menu[] = {
55         {'1', "<< previous", "<< zurueck"},
56         {'2', "-> play", "-> anhoeren"},
57         {'3', ">> next", ">> vor"},
58         {'4', "<  rewind", "<  rueckspulen"},
59         {'5', "[] stop", "[] stop"},
60         {'6', ">  wind", ">  vorspulen"},
61         {'7', "() record", "() Aufnahme"},
62         {'8', "=  store", "=  speichern"},
63         {'9', "X  delete", "X  loeschen"},
64         {'0', "*  call", "*  anrufen"},
65         {'\0', NULL, NULL}
66 };
67
68 /*
69  * initialize the vbox. this is called at process_dialing(), when the VBOX_PLAY
70  * action has been selected by the caller
71  */
72 void EndpointAppPBX::action_init_vbox_play(void)
73 {
74         int                     language = e_ext.vbox_language;
75         struct route_param      *rparam;
76         struct lcr_msg          *message;
77         struct port_list        *portlist = ea_endpoint->ep_portlist;
78
79         /* get extension */
80         SCPY(e_vbox, e_ext.number);
81         if ((rparam = routeparam(e_action, PARAM_EXTENSION)))
82                 SCPY(e_vbox, rparam->string_value);
83         if (e_vbox[0] == '\0') {
84                 /* facility rejected */
85                 message_disconnect_port(portlist, CAUSE_FACILITYREJECTED, LOCATION_PRIVATE_LOCAL, "");
86                 new_state(EPOINT_STATE_OUT_DISCONNECT);
87                 set_tone(portlist,"cause_22");
88                 return;
89         }
90
91         /* connect, but still accept more digits */
92         new_state(EPOINT_STATE_IN_OVERLAP);
93         if (e_ext.number[0])
94                 e_dtmf = 1;
95         message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
96         message_put(message);
97         logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
98
99         /* initialize the vbox */
100         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) initializing answering vbox state\n", ea_endpoint->ep_serial);
101
102         e_vbox_state = VBOX_STATE_MENU;
103         SCPY(e_vbox_display, (char *)((language)?"druecke 2 f. wiedergabe":"press 2 to play"));
104         e_vbox_display_refresh = 1;
105         set_tone_vbox("menu");
106
107         e_vbox_menu = -1;
108         e_vbox_play = 0;
109         vbox_index_read(e_vbox_play);
110         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) number of calls: %d\n", ea_endpoint->ep_serial, e_vbox_index_num);
111
112         if (e_vbox_index_num == 0) {
113                 e_vbox_state = VBOX_STATE_NOTHING;
114                 SCPY(e_vbox_display, (char *)((language)?"keine Anrufe":"no calls"));
115                 e_vbox_display_refresh = 1;
116                 set_tone_vbox("nothing");
117         }
118 }
119
120 /*
121  * read index list, and fill the index variables with the given position
122  * if the index is empty (or doesn't exist), the variables are not filled.
123  * but alway the e_vbox_index_num is given.
124  */
125 void EndpointAppPBX::vbox_index_read(int num)
126 {
127         FILE *fp;
128         char filename[256];
129         char buffer[256];
130         char name[sizeof(buffer)];
131         char callerid[sizeof(buffer)];
132         int year, mon, mday, hour, min;
133         int i;
134
135         e_vbox_index_num = 0;
136
137         SPRINT(filename, "%s/%s/vbox/index", EXTENSION_DATA, e_vbox);
138         if (!(fp = fopen(filename, "r"))) {
139                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no files in index\n", ea_endpoint->ep_serial);
140                 return;
141         }
142         fduse++;
143
144         i = 0;
145         while((fgets(buffer,sizeof(buffer),fp))) {
146                 buffer[sizeof(buffer)-1] = '\0';
147                 if (buffer[0]) buffer[strlen(buffer)-1] = '\0';
148
149                 name[0] = callerid[0] = '\0';
150                 mon = mday = hour = min = 0;
151                 sscanf(buffer, "%s %d %d %d %d %d %s", name, &year, &mon, &mday, &hour, &min, callerid);
152
153                 if (name[0]=='\0' || name[0]=='#')
154                         continue;
155
156                 /* the selected entry */
157                 if (i == num) {
158                         SCPY(e_vbox_index_file, name);
159                         e_vbox_index_year = year;
160                         e_vbox_index_mon = mon;
161                         e_vbox_index_mday = mday;
162                         e_vbox_index_hour = hour;
163                         e_vbox_index_min = min;
164                         SCPY(e_vbox_index_callerid, callerid);
165                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) read entry #%d: '%s', %02d:%02d %02d:%02d cid='%s'\n", ea_endpoint->ep_serial, i, name, mon+1, mday, hour, min, callerid);
166                 }
167
168                 i++;
169         }
170
171         e_vbox_index_num = i;
172
173         fclose(fp);
174         fduse--;
175 }
176
177
178 /*
179  * removes given index from list
180  * after removing, the list should be reread, since e_vbox_index_num
181  * and the current variabled do not change
182  */
183 void EndpointAppPBX::vbox_index_remove(int num)
184 {
185         FILE *fpr, *fpw;
186         char buffer[256];
187         int i;
188         char filename1[256], filename2[256];
189
190         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing entrie #%d\n", ea_endpoint->ep_serial, num);
191
192         SPRINT(filename1, "%s/%s/vbox/index", EXTENSION_DATA, e_vbox);
193         SPRINT(filename2, "%s/%s/vbox/index-temp", EXTENSION_DATA, e_vbox);
194         if (!(fpr = fopen(filename1, "r"))) {
195                 return;
196         }
197         if (!(fpw = fopen(filename2, "w"))) {
198                 fclose(fpr);
199                 return;
200         }
201         fduse += 2;
202
203         i = 0;
204         while((fgets(buffer,sizeof(buffer),fpr))) {
205                 buffer[sizeof(buffer)-1] = '\0';
206                 if (buffer[0]) buffer[strlen(buffer)-1] = '\0';
207
208                 if (buffer[0]=='\0' || buffer[0]=='#') {
209                         fprintf(fpw, "%s\n", buffer);
210                         continue;       
211                 }
212
213                 /* the selected entry will not be written */
214                 if (i != num) {
215                         fprintf(fpw, "%s\n", buffer);
216                 }
217
218                 i++;
219         }
220
221         fclose(fpr);
222         fclose(fpw);
223         fduse -= 2;
224
225         rename(filename2, filename1);
226 }
227
228
229 /*
230  * process dialing of vbox_play (actually the menu)
231  * it is depended by the state, which action is performed
232  */
233 void EndpointAppPBX::action_dialing_vbox_play(void)
234 {
235         int language = e_ext.vbox_language;
236         struct port_list *portlist;
237         class Port *port;
238         
239         portlist = ea_endpoint->ep_portlist;
240
241         if (e_extdialing[0] == '\0') {
242                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) called with no digit\n", ea_endpoint->ep_serial);
243                 return;
244         }
245
246         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing digit: %c\n", ea_endpoint->ep_serial, e_extdialing[0]);
247
248         e_vbox_display_refresh = 1;
249
250         if (e_vbox_state == VBOX_STATE_RECORD_RECORD) {
251                 if (e_extdialing[0] == '1' || e_extdialing[0] == '0') {
252                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) stopping recording of announcement.\n", ea_endpoint->ep_serial);
253
254                         port = find_port_id(portlist->port_id);
255                         if (port)
256                                 port->close_record((e_extdialing[0]=='1')?6000:0, 2000); /* append beep */
257                         goto record_ask;
258                 }
259                 goto done;
260         }
261
262         if (e_vbox_state == VBOX_STATE_RECORD_PLAY) {
263                 if (e_extdialing[0] == '1') {
264                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) stopping playback of announcement.\n", ea_endpoint->ep_serial);
265
266                         goto record_ask;
267                 }
268                 goto done;
269         }
270
271         if (e_vbox_state == VBOX_STATE_RECORD_ASK) {
272                 switch(e_extdialing[0]) {
273                         case '3':
274                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) quit recoding menu.\n", ea_endpoint->ep_serial);
275                         ask_abort:
276                         /* abort */
277                         e_vbox_state = VBOX_STATE_MENU;
278                         SCPY(e_vbox_display, (char *)((language)?"druecke 2 f. wiedergabe":"press 2 to play"));
279                         set_tone_vbox("menu");
280                         break;
281
282                         case '2':
283                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) play recoding.\n", ea_endpoint->ep_serial);
284                         /* play announcement */
285                         e_vbox_counter = 0;
286                         e_vbox_counter_last = 0;
287                         e_vbox_counter_max = 0;
288                         e_vbox_speed = 1;
289                         e_vbox_state = VBOX_STATE_RECORD_PLAY;
290                         if (e_ext.vbox_language)
291                                 SCPY(e_vbox_display, "Wied., 1=stop %s");
292                         else
293                                 SCPY(e_vbox_display, "play, 1=stop %s");
294                         if (e_ext.vbox_display == VBOX_DISPLAY_BRIEF)
295                                 SCPY(e_vbox_display, "1=stop %s");
296                         set_play_vbox("announcement", 0);
297                         break;
298
299                         case '1':
300                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) record announcement.\n", ea_endpoint->ep_serial);
301                         /* close recording if already recording */
302                         port = find_port_id(portlist->port_id);
303                         if (port) {
304                                 port->close_record(0,0); 
305                                 port->open_record(CODEC_MONO, 1, 4000, e_ext.number, 0, "", 0); /* record announcement, skip the first 4000 samples */
306                         }
307                         e_vbox_state = VBOX_STATE_RECORD_RECORD;
308                         if (e_ext.vbox_language)
309                                 SCPY(e_vbox_display, "Aufnahme, 1=stop");
310                         else
311                                 SCPY(e_vbox_display, "recording, 1=stop");
312                         set_tone_vbox(NULL);
313                         break;
314
315                         default:
316                         ;
317                 }
318                 goto done;
319         }
320
321         if (e_vbox_state==VBOX_STATE_STORE_ASK || e_vbox_state==VBOX_STATE_DELETE_ASK) {
322                 char filename[256], filename2[256];
323
324                 switch(e_extdialing[0]) {
325                         case '3':
326                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) quit store/delete menu.\n", ea_endpoint->ep_serial);
327                         goto ask_abort;
328
329                         case '1':
330                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do store/delete.\n", ea_endpoint->ep_serial);
331                         SPRINT(filename, "%s/%s/vbox/%s", EXTENSION_DATA, e_vbox, e_vbox_index_file);
332
333                         /* move file */
334                         if (e_vbox_state == VBOX_STATE_STORE_ASK) {
335                                 SPRINT(filename, "%s/%s/recordings", EXTENSION_DATA, e_vbox);
336                                 if (mkdir(filename, 0755) < 0) {
337                                         if (errno != EEXIST) {
338                                                 PERROR("EPOINT(%d) cannot create directory '%s'\n", ea_endpoint->ep_serial, filename);
339                                                 goto done;
340                                         }
341                                 }
342                                 SPRINT(filename2, "%s/%s/recordings/%s", EXTENSION_DATA, e_vbox, e_vbox_index_file);
343                                 rename(filename, filename2);
344                                 e_vbox_state = VBOX_STATE_STORE_DONE;
345                                 if (e_ext.vbox_language)
346                                         SCPY(e_vbox_display, "Nachricht gespeichert!");
347                                 else
348                                         SCPY(e_vbox_display, "Message stored!");
349                                 set_tone_vbox("store_done");
350                         }
351
352                         /* remove file */
353                         if (e_vbox_state == VBOX_STATE_DELETE_ASK) {
354                                 remove(filename);
355                                 e_vbox_state = VBOX_STATE_DELETE_DONE;
356                                 if (e_ext.vbox_language)
357                                         SCPY(e_vbox_display, "Nachricht geloescht!");
358                                 else
359                                         SCPY(e_vbox_display, "Message deleted!");
360                                 set_tone_vbox("delete_done");
361                         }
362
363                         /* remove from list */
364                         vbox_index_remove(e_vbox_play);
365                         vbox_index_read(e_vbox_play);
366                         /* stay at the last message+1, so we always get "no messages" */
367                         if (e_vbox_play>e_vbox_index_num && e_vbox_play) {
368                                 e_vbox_play = e_vbox_index_num-1;
369                         }
370                         default:
371                         ;
372                 }
373                 goto done;
374         }
375
376         /* dialing during menu */
377         switch(e_extdialing[0]) {
378                 /* process the vbox functions */
379                 case '1': /* previous */
380                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) previous call is selected.\n", ea_endpoint->ep_serial);
381                 if (e_vbox_index_num == 0) { /* nothing to play */
382                         no_calls:
383                         e_vbox_state = VBOX_STATE_MENU;
384                         SCPY(e_vbox_display, (char *)((language)?"keine Anrufe":"no calls"));
385                         set_tone_vbox("nothing");
386                         break;
387                 }
388                 e_vbox_play--;
389                 if (e_vbox_play < 0) {
390                         e_vbox_play = 0;
391
392                         e_vbox_state = VBOX_STATE_MENU;
393                         SCPY(e_vbox_display, (char *)((language)?"kein vorheriger Anruf":"no previous call"));
394                         set_tone_vbox("nothing");
395                         break;
396                 }
397                 /* announce call */
398                 announce_call:
399                 e_vbox_state = VBOX_STATE_CALLINFO_INTRO;
400                 SPRINT(e_vbox_display, "#%d", e_vbox_play+1);
401                 vbox_index_read(e_vbox_play);
402                 if (e_vbox_index_mon!=now_tm->tm_mon || e_vbox_index_year!=now_tm->tm_year) {
403                         UPRINT(strchr(e_vbox_display,'\0'), " %s", (language)?months_german[e_vbox_index_mon]:months_english[e_vbox_index_mon]);
404                 }
405                 if (e_vbox_index_mday!=now_tm->tm_mday || e_vbox_index_mon!=now_tm->tm_mon || e_vbox_index_year!=now_tm->tm_year) {
406                         UPRINT(strchr(e_vbox_display,'\0'), " %d", e_vbox_index_mday);
407                 }
408                 UPRINT(strchr(e_vbox_display,'\0'), " %02d:%02d", e_vbox_index_hour, e_vbox_index_min);
409                 if (e_ext.vbox_display == VBOX_DISPLAY_DETAILED)
410                         UPRINT(strchr(e_vbox_display,'\0'), " (%s)", e_vbox_index_callerid);
411                 set_tone_vbox("intro");
412                 break;
413
414                 case '2': /* play */
415                 if (e_vbox_play >= e_vbox_index_num)
416                         goto no_messages;
417                 if (e_vbox_index_num == 0) { /* nothing to play */
418                         goto no_calls;
419                 }
420                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) play call #%d.\n", ea_endpoint->ep_serial, e_vbox_play+1);
421                 if (e_vbox_state>VBOX_STATE_CALLINFO_BEGIN && e_vbox_state<VBOX_STATE_CALLINFO_END) {
422                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) play call #%d. abborting announcement and starting with playback\n", ea_endpoint->ep_serial, e_vbox_play+1);
423                         /* the callinfo is played, so we start with the call */
424                         e_vbox_counter = 0;
425                         e_vbox_counter_last = 0;
426                         e_vbox_counter_max = 0;
427                         e_vbox_speed = 1;
428                         e_vbox_state = VBOX_STATE_PLAY;
429                         SPRINT(e_vbox_display, "#%d %%s", e_vbox_play+1);
430                         if (e_ext.vbox_display == VBOX_DISPLAY_DETAILED)
431                                 UPRINT(strchr(e_vbox_display,'\0'), " (%s)", e_vbox_index_callerid);
432                         set_play_vbox(e_vbox_index_file, 0);
433                         break;
434                 } else
435                 if (e_vbox_state==VBOX_STATE_PLAY && e_vbox_speed!=1) {
436                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) play call #%d. play speed is different from 1, so we play now with normal speed\n", ea_endpoint->ep_serial, e_vbox_play+1);
437                         /* we set play speed to normal */
438                         e_vbox_speed = 1;
439                         set_play_speed(e_vbox_speed);
440                 } else
441                 if (e_vbox_state == VBOX_STATE_PLAY) {
442                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) play call #%d. play speed is equals 1, so we pause\n", ea_endpoint->ep_serial, e_vbox_play+1);
443                         /* we pause the current play */
444                         e_vbox_state = VBOX_STATE_PAUSE;
445                         SCPY(e_vbox_display, (char *)((language)?"druecke 2 f. wiedergabe":"press 2 to play"));
446                         set_tone_vbox("pause");
447                 } else
448                 if (e_vbox_state == VBOX_STATE_PAUSE) {
449                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) play call #%d. currently pause, so we continue play\n", ea_endpoint->ep_serial, e_vbox_play+1);
450                         /* we continue the current play */
451                         e_vbox_state = VBOX_STATE_PLAY;
452                         SPRINT(e_vbox_display, "#%d %%s", e_vbox_play+1);
453                         if (e_ext.vbox_display == VBOX_DISPLAY_DETAILED)
454                                 UPRINT(strchr(e_vbox_display,'\0'), " (%s)", e_vbox_index_callerid);
455                         set_play_vbox(e_vbox_index_file, e_vbox_counter);
456                 } else {
457                         /* now we have something else going on, so we announce the call */
458                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) play call #%d. announcing call during any other state\n", ea_endpoint->ep_serial, e_vbox_play+1);
459                         goto announce_call;
460                 }
461                 break;
462
463                 case '3': /* next */
464                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) next call is selected.\n", ea_endpoint->ep_serial);
465                 if (e_vbox_index_num == 0) { /* nothing to play */
466                         goto no_calls;
467                 }
468                 e_vbox_play++;
469                 if (e_vbox_play >= e_vbox_index_num) {
470                         no_messages:
471                         e_vbox_play = e_vbox_index_num;
472
473                         e_vbox_state = VBOX_STATE_MENU;
474                         SCPY(e_vbox_display, (char *)((language)?"kein weiterer Anruf":"no next call"));
475                         set_tone_vbox("nothing");
476                         break;
477                 }
478                 /* announce call */
479                 goto announce_call;
480                 break;
481
482                 case '4': /* rewind */
483                 if (e_vbox_state==VBOX_STATE_PLAY) {
484                         if (e_vbox_speed >= -1)
485                                 e_vbox_speed = -1;
486                         e_vbox_speed = e_vbox_speed * 2;
487                         set_play_speed(e_vbox_speed);
488                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) rewind speed has been changed to: %d\n", ea_endpoint->ep_serial, e_vbox_speed);
489                 } 
490                 break;
491
492                 case '5': /* stop */
493                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) stop is pressed, so we hear the menu\n", ea_endpoint->ep_serial);
494                 e_vbox_state = VBOX_STATE_MENU;
495                 SCPY(e_vbox_display, (char *)((language)?"druecke 2 f. wiedergabe":"press 2 to play"));
496                 set_tone_vbox("menu");
497                 break;
498
499                 case '6': /* wind */
500                 if (e_vbox_state==VBOX_STATE_PLAY) {
501                         if (e_vbox_speed <= 1)
502                                 e_vbox_speed = 1;
503                         e_vbox_speed = e_vbox_speed * 2;
504                         set_play_speed(e_vbox_speed);
505                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) wind speed has been changed to: %d\n", ea_endpoint->ep_serial, e_vbox_speed);
506                 } 
507                 break;
508
509                 case '7': /* record announcement */
510                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) entering the record announcement menu\n", ea_endpoint->ep_serial);
511                 record_ask:
512                 e_vbox_state = VBOX_STATE_RECORD_ASK;
513                 SCPY(e_vbox_display, (char *)((language)?"1=Aufn. 2=Wied. 3=nein":"1=record 2=play 3=back"));
514                 set_tone_vbox("record_ask");
515                 break;
516
517                 case '8': /* store file */
518                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) entering the store menu\n", ea_endpoint->ep_serial);
519                 if (e_vbox_play >= e_vbox_index_num)
520                         goto no_messages;
521                 if (e_vbox_index_num == 0) { /* nothing to play */
522                         goto no_calls;
523                 }
524                 e_vbox_state = VBOX_STATE_STORE_ASK;
525                 SCPY(e_vbox_display, (char *)((language)?"speichern 1=ja 3=nein":"store 1=yes 3=back"));
526                 set_tone_vbox("store_ask");
527                 break;
528
529                 case '9': /* delete file */
530                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) entering the delete menu\n", ea_endpoint->ep_serial);
531                 if (e_vbox_play >= e_vbox_index_num)
532                         goto no_messages;
533                 if (e_vbox_index_num == 0) { /* nothing to play */
534                         goto no_calls;
535                 }
536                 e_vbox_state = VBOX_STATE_DELETE_ASK;
537                 SCPY(e_vbox_display, (char *)((language)?"loeschen 1=ja 3=nein":"delete 1=yes 3=back"));
538                 set_tone_vbox("delete_ask");
539                 break;
540
541
542                 /* process the menu */
543                 case '#':
544                 if (e_vbox_menu < 0)
545                         e_vbox_menu = 0;
546                 else
547                         e_vbox_menu++;
548                 if (vbox_menu[e_vbox_menu].english == NULL)
549                         e_vbox_menu = 0;
550                 /* show menu */
551                 show_menu:
552                 SPRINT(e_vbox_display, "%c: %s", vbox_menu[e_vbox_menu].digit, (language)?vbox_menu[e_vbox_menu].german:vbox_menu[e_vbox_menu].english);
553                 break;
554
555                 case '0':
556                 if (e_vbox_menu < 0) { /* only if menu selection is pressed before*/
557                         /* call if phonenumber is given */
558                         if (e_vbox_index_num)
559                         if (e_vbox_index_callerid[0]!='\0' && !!strcmp(e_vbox_index_callerid,"anonymous") && !!strcmp(e_vbox_index_callerid,"unknown")) {
560                                 set_tone(portlist, "dialing");
561                                 SPRINT(e_dialinginfo.id, "extern:%s", e_vbox_index_callerid);
562                                 e_extdialing = e_dialinginfo.id;
563                                 e_action = NULL;
564                                 process_dialing();
565                                 return;
566                         }
567                         break;
568                 }
569                 e_extdialing[0] = vbox_menu[e_vbox_menu].digit;
570                 e_extdialing[1] = '\0';
571                 e_vbox_menu = -1;
572                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) executing selected menu:%d\n", e_extdialing[0]);
573                 action_dialing_vbox_play(); /* redo this method using the digit */
574                 return;
575
576                 case '*':
577                 if (e_vbox_menu < 0)
578                         e_vbox_menu = 0;
579                 else
580                         e_vbox_menu--;
581                 if (e_vbox_menu < 0)
582                         while(vbox_menu[e_vbox_menu+1].english) /* jump to the end */
583                                 e_vbox_menu++;
584                 /* show menu */
585                 goto show_menu;
586                 break;
587
588                 default:
589                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) unsupported digit '%c'\n", ea_endpoint->ep_serial, e_extdialing);
590         }
591
592         done:
593         /* reset menu after dialing a function */
594         if (e_extdialing[0]!='*' && e_extdialing[0]!='#')
595                 e_vbox_menu = -1;
596
597
598         e_extdialing[0] = '\0';
599
600 }
601
602
603 /*
604  * this handler is called by Epoint::handler(), whenever the action is NUMB_ACTION_VBOX_PLAY
605  */
606 void EndpointAppPBX::vbox_handler(void)
607 {
608         /* refresh if counter changes */
609         if (e_vbox_state==VBOX_STATE_PLAY || e_vbox_state==VBOX_STATE_RECORD_PLAY)
610         if (e_vbox_counter != e_vbox_counter_last) {
611                 e_vbox_counter_last = e_vbox_counter;
612                 e_vbox_display_refresh = 1;
613         }
614
615         /* refresh display, if required (include counter) */
616         if (e_vbox_display_refresh && e_ext.vbox_display!=VBOX_DISPLAY_OFF) {
617                 char counter[32];
618                 struct lcr_msg *message;
619
620                 SPRINT(counter, "%02d:%02d", e_vbox_counter/60, e_vbox_counter%60);
621                 if (e_vbox_counter_max)
622                         UPRINT(strchr(counter,'\0'), " of %02d:%02d", e_vbox_counter_max/60, e_vbox_counter_max%60);
623
624                 e_vbox_display_refresh = 0;
625                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
626                 SPRINT(message->param.notifyinfo.display, e_vbox_display, counter);
627                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) terminal %s pending display:%s\n", ea_endpoint->ep_serial, e_ext.number, message->param.notifyinfo.display);
628                 message_put(message);
629                 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
630         }
631 }
632
633
634 /*
635  * the audio file has ended
636  * this is called by Endpoint::message_port(), whenever an audio of has been received
637  */
638 void EndpointAppPBX::vbox_message_eof(void)
639 {
640         char buffer[32];
641         int language = e_ext.vbox_language;
642
643         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) terminal %s end of file during state: %d\n", ea_endpoint->ep_serial, e_ext.number, e_vbox_state);
644
645         switch(e_vbox_state) {
646                 case VBOX_STATE_MENU:
647                 case VBOX_STATE_NOTHING:
648                 e_vbox_state = VBOX_STATE_MENU;
649                 SCPY(e_vbox_display, (char *)((language)?"druecke 2 f. wiedergabe":"press 2 to play"));
650                 e_vbox_display_refresh = 1;
651                 set_tone_vbox("menu");
652                 break;
653
654                 case VBOX_STATE_PLAY:
655                 if (e_vbox_speed > 0) {
656                         e_vbox_state = VBOX_STATE_MENU;
657                         SCPY(e_vbox_display, (char *)((language)?"druecke 3 f. Naechste":"press 3 for next"));
658                         e_vbox_display_refresh = 1;
659                         set_tone_vbox("menu");
660                 } else {
661                         /* if we have endoffile because we were playing backwards, we continue to play forward */
662                         e_vbox_speed = 1;
663                         e_vbox_counter = 1;
664                         set_play_vbox(e_vbox_index_file, e_vbox_counter);
665                 }
666                 break;
667
668                 case VBOX_STATE_PAUSE:
669                 SCPY(e_vbox_display, (char *)((language)?"druecke 2 f. weiterspielen":"press 2 to continue"));
670                 e_vbox_display_refresh = 1;
671                 break;
672
673                 case VBOX_STATE_CALLINFO_INTRO:
674                 if (e_vbox_index_mday==now_tm->tm_mday && e_vbox_index_mon==now_tm->tm_mon && e_vbox_index_year==now_tm->tm_year)
675                         goto skip_day_month;
676                 e_vbox_state = VBOX_STATE_CALLINFO_MONTH; //german day
677                 if (e_ext.vbox_language)
678                         /* german starts with day */
679                         SPRINT(buffer, "day_%02d", e_vbox_index_mday);
680                 else
681                         /* english starts with month */
682                         SPRINT(buffer, "month_%02d", e_vbox_index_mon+1);
683                 set_tone_vbox(buffer);
684                 break;
685
686                 case VBOX_STATE_CALLINFO_MONTH:
687                 e_vbox_state = VBOX_STATE_CALLINFO_DAY; //german month
688                 if (e_ext.vbox_language) {
689                         /* done with month, so we send the month*/
690                         SPRINT(buffer, "month_%02d", e_vbox_index_mon+1);
691                 } else {
692                         /* done with day, so we send the day */
693                         SPRINT(buffer, "day_%02d", e_vbox_index_mday);
694                 }
695                 set_tone_vbox(buffer);
696                 break;
697
698                 case VBOX_STATE_CALLINFO_DAY: //german month
699                 skip_day_month:
700                 e_vbox_state = VBOX_STATE_CALLINFO_HOUR;
701                 if (e_ext.vbox_language) {
702                         if (e_vbox_index_hour == 1)
703                                 SCPY(buffer, "number_ein");
704                         else
705                                 SPRINT(buffer, "number_%02d", e_vbox_index_hour); /* 1-23 hours */
706                 } else {
707                         SPRINT(buffer, "number_%02d", ((e_vbox_index_hour+11)%12)+1); /* 12 hours am/pm */
708                 }
709                 set_tone_vbox(buffer);
710                 break;
711
712                 case VBOX_STATE_CALLINFO_HOUR:
713                 e_vbox_state = VBOX_STATE_CALLINFO_OCLOCK;
714                 if (e_ext.vbox_language) {
715                         set_tone_vbox("oclock");
716                 } else {
717                         if (e_vbox_index_hour >= 12)
718                                 set_tone_vbox("oclock_pm");
719                         else
720                                 set_tone_vbox("oclock_am");
721                 }
722                 break;
723
724                 case VBOX_STATE_CALLINFO_OCLOCK:
725                 e_vbox_state = VBOX_STATE_CALLINFO_MIN;
726                 if (e_ext.vbox_language) {
727 // german says "zwölfuhr und eins"
728 //                      if (e_vbox_index_min == 1)
729 //                              SCPY(buffer, "number_eine");
730 //                      else
731                                 SPRINT(buffer, "number_%02d", e_vbox_index_min); /* 1-59 minutes */
732                 } else {
733                         SPRINT(buffer, "number_%02d", e_vbox_index_min);
734                 }
735                 set_tone_vbox(buffer);
736                 break;
737
738                 case VBOX_STATE_CALLINFO_MIN:
739                 if (e_ext.vbox_language)
740                         goto start_digits;
741                 e_vbox_state = VBOX_STATE_CALLINFO_MINUTES;
742                 if (e_vbox_index_mday == 1)
743                         set_tone_vbox("minute");
744                 else
745                         set_tone_vbox("minutes");
746                 break;
747
748                 case VBOX_STATE_CALLINFO_MINUTES:
749                 start_digits:
750                 e_vbox_state = VBOX_STATE_CALLINFO_DIGIT;
751                 if (e_vbox_index_callerid[0]=='\0' || !strcmp(e_vbox_index_callerid,"anonymous") || !strcmp(e_vbox_index_callerid,"unknown")) {
752                         set_tone_vbox("call_anonymous");
753                         e_vbox_index_callerid_index = strlen(e_vbox_index_callerid);
754                 } else {
755                         set_tone_vbox("call_from");
756                         e_vbox_index_callerid_index = 0;
757                 }
758                 break;
759
760                 case VBOX_STATE_CALLINFO_DIGIT:
761                 while (e_vbox_index_callerid[e_vbox_index_callerid_index] && (e_vbox_index_callerid[e_vbox_index_callerid_index]<'0' || e_vbox_index_callerid[e_vbox_index_callerid_index]>'9'))
762                         e_vbox_index_callerid_index++;
763                 if (e_vbox_index_callerid[e_vbox_index_callerid_index]) {
764                         SPRINT(buffer, "number_%02d", e_vbox_index_callerid[e_vbox_index_callerid_index]-'0');
765                         set_tone_vbox(buffer);
766                         e_vbox_index_callerid_index ++;
767                 } else {
768                         /* the callinfo is played, so we start with the call */
769                         e_vbox_counter = 0;
770                         e_vbox_counter_last = 0;
771                         e_vbox_counter_max = 0;
772                         e_vbox_speed = 1;
773                         e_vbox_state = VBOX_STATE_PLAY;
774                         SPRINT(e_vbox_display, "#%d %%s", e_vbox_play);
775                         if (e_ext.vbox_display == VBOX_DISPLAY_DETAILED)
776                                 UPRINT(strchr(e_vbox_display,'\0'), " (%s)", e_vbox_index_callerid);
777                         e_vbox_display_refresh = 1;
778                         set_play_vbox(e_vbox_index_file, 0);
779                 }
780                 break;
781
782                 case VBOX_STATE_RECORD_ASK:
783                 set_tone_vbox("record_ask");
784                 e_vbox_display_refresh = 1;
785                 break;
786
787                 case VBOX_STATE_STORE_ASK:
788                 set_tone_vbox("store_ask");
789                 e_vbox_display_refresh = 1;
790                 break;
791
792                 case VBOX_STATE_DELETE_ASK:
793                 set_tone_vbox("delete_ask");
794                 e_vbox_display_refresh = 1;
795                 break;
796
797                 case VBOX_STATE_RECORD_PLAY:
798                 e_vbox_state = VBOX_STATE_RECORD_ASK;
799                 SCPY(e_vbox_display, (char *)((language)?"1=Aufn. 2=Wied. 3=nein":"1=record 2=play 3=no"));
800                 e_vbox_display_refresh = 1;
801                 set_tone_vbox("record_ask");
802                 break;
803
804                 case VBOX_STATE_STORE_DONE:
805                 case VBOX_STATE_DELETE_DONE:
806                 if (e_vbox_index_num == 0) { /* nothing to play */
807                         e_vbox_state = VBOX_STATE_MENU;
808                         SCPY(e_vbox_display, (char *)((language)?"keine Anrufe":"no calls"));
809                         e_vbox_display_refresh = 1;
810                         set_tone_vbox("nothing");
811                 } else {
812                         e_vbox_state = VBOX_STATE_MENU;
813                         SCPY(e_vbox_display, (char *)((language)?"druecke 2 f. wiedergabe":"press 2 to play"));
814                         e_vbox_display_refresh = 1;
815                         set_tone_vbox("menu");
816                 }
817                 break;
818
819                 default:
820                 PERROR("vbox_message_eof(ep%d): terminal %s unknown state: %d\n", ea_endpoint->ep_serial, e_ext.number, e_vbox_state);
821         }
822 }
823
824
825
826 /*
827  * set the given vbox-tone with full path (without appending)
828  * the tone is played and after eof, a message is received
829  */
830 void EndpointAppPBX::set_tone_vbox(const char *tone)
831 {
832         struct lcr_msg *message;
833
834         if (tone == NULL)
835                 tone = "";
836
837         if (!ea_endpoint->ep_portlist) {
838                 PERROR("EPOINT(%d) no portlist\n", ea_endpoint->ep_serial);
839         }
840         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_VBOX_TONE);
841         SCPY(message->param.tone.dir, ((e_ext.vbox_language) ? "vbox_german" : "vbox_english"));
842         SCPY(message->param.tone.name, tone);
843         message_put(message);
844
845         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) terminal %s set tone '%s'\n", ea_endpoint->ep_serial, e_ext.number, tone);
846 }
847
848
849 /*
850  * set the given recording file
851  * the appendix is removed
852  * the file is played and after eof, a message is received
853  * the current counter value is also received by a message
854  * set the offset in seconds of the current recording
855  */
856 void EndpointAppPBX::set_play_vbox(const char *file, int offset)
857 {
858         char filename[256];
859         struct lcr_msg *message;
860
861         SPRINT(filename, "%s/%s/vbox/%s", EXTENSION_DATA, e_vbox, file);
862         
863         /* remove .wav */
864         if (!strcmp(filename+strlen(filename)-4, ".wav")) /* filename is always more than 4 digits long */
865                 filename[strlen(filename)-4] = '\0';
866         else // to not check twice
867         /* remove .isdn */
868         if (!strcmp(filename+strlen(filename)-5, ".isdn")) /* filename is always more than 5 digits long */
869                 filename[strlen(filename)-5] = '\0';
870
871         if (!ea_endpoint->ep_portlist) {
872                 PERROR("EPOINT(%d) no portlist\n", ea_endpoint->ep_serial);
873         }
874         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_VBOX_PLAY);
875         SCPY(message->param.play.file, filename);
876         message->param.play.offset = offset;
877         message_put(message);
878
879         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) terminal %s set play '%s'\n", ea_endpoint->ep_serial, e_ext.number, filename);
880 }
881
882
883 /*
884  * change speed of the recording file, the default is 1
885  * negative values cause negative speed
886  */
887 void EndpointAppPBX::set_play_speed(int speed)
888 {
889         struct lcr_msg *message;
890
891         if (!ea_endpoint->ep_portlist) {
892                 PERROR("EPOINT(%d) no portlist\n", ea_endpoint->ep_serial);
893         }
894         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_VBOX_PLAY_SPEED);
895         message->param.speed = speed;
896         message_put(message);
897
898         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) terminal %s set speed '%d'\n", ea_endpoint->ep_serial, e_ext.number, speed);
899 }
900
901
902