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