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