home *** CD-ROM | disk | FTP | other *** search
/ Super PC 31 / Super PC 31 (Shareware).iso / spc / inter / speakf / fuente / answer.c next >
Encoding:
C/C++ Source or Header  |  1995-12-01  |  14.3 KB  |  472 lines

  1. /*
  2.  
  3.                 Answering Machine
  4.                 
  5. */
  6.  
  7. #include "netfone.h"
  8.  
  9. #define answerBufferSize 2048            // Buffer for reading message file
  10.  
  11. #ifdef answerBufferSize
  12. static char answerBuffer[answerBufferSize];
  13. #endif
  14.  
  15. char answerFileName[MAX_PATH] = "";        // Answering machine file name
  16. int answerRecord = TRUE;                // Record incoming messages
  17.  
  18. static FILE *answerFile = NULL;         // Answering machine file descriptor
  19. static long answerLen;                    // Length of answering machine file
  20. static long answerPlayPos;                // Current replay address 
  21. static int replaying = FALSE;            // Nonzero when replay is active
  22. static int currentMessage;                // Current message being replayed
  23. static time_t lastPacket = 0;            // Time of last packet recorded
  24.  
  25. static long FAR *msgTable = NULL;        // Pointers to messages in file
  26. static int msgMax = 0;                    // Message table size
  27. static int msgCount = 0;                // Messages currently in table
  28.  
  29. #define newMessageCriterion    2            // Gap length, in seconds, defining a new message
  30.  
  31. /*    SETMESSAGECOUNT  --  If answering machine is displayed, update the
  32.                          number of messages in the file.  */
  33.  
  34. static void setMessageCount(void)
  35. {
  36.     if (hDlgAnswer != NULL) {
  37.         char mno[24];
  38.         
  39.         if (currentMessage >= 0) {
  40.             wsprintf(mno, Format(42), currentMessage + 1, msgCount);
  41.         } else {
  42.             if (msgCount > 1) {
  43.                 wsprintf(mno, Format(43), msgCount);
  44.             } else {
  45.                 strcpy(mno, msgCount == 1 ? rstring(IDS_T_ONE_MESSAGE) :
  46.                                             rstring(IDS_T_NO_MESSAGES));
  47.             }
  48.         }
  49.         SetDlgItemText(hDlgAnswer, IDC_RP_MSGBOX, mno);
  50.     }
  51. }
  52.  
  53. //    GROWMESSAGETABLE  --  Expand in-memory message table if needed
  54.  
  55. static int growMessageTable(HWND hwnd, int currentMessage)
  56. {
  57.     if (currentMessage >= msgMax) {
  58.         msgMax += 50;
  59.         msgTable = GlobalReAllocPtr(msgTable, msgMax * sizeof(long), 0);
  60.         if (msgTable == NULL) {
  61.             MessageBox(hwnd, rstring(IDS_T_EXPAND_MSG_TABLE_ERR),
  62.                    NULL, MB_OK | MB_ICONEXCLAMATION);
  63.                return FALSE;
  64.         }
  65.     }
  66.     return TRUE;
  67. }
  68.  
  69. /*  ANSWEROPEN  --  Open the answering machine file.  */
  70.  
  71. int answerOpen(void)
  72. {
  73.     answerFile = fopen(answerFileName, "r+b");
  74.     if (answerFile == NULL) {
  75.         answerFile = fopen(answerFileName, "w+b");
  76.     }
  77.     if (answerFile != NULL) {
  78. #ifdef answerBufferSize
  79.         setvbuf(answerFile, answerBuffer, _IOFBF, sizeof answerBuffer);
  80. #endif
  81.         fseek(answerFile, 0L, 2);
  82.         answerLen = ftell(answerFile);
  83.         rewind(answerFile);
  84.     }
  85.     replaying = FALSE;
  86.     return answerFile != NULL;
  87. }
  88.  
  89. //    ANSWERENABLED  --  Determine if recording messages is possible
  90.  
  91. int answerEnabled(void)
  92. {
  93.     return answerFile != NULL;
  94. }
  95.  
  96. /*    ANSWERSAVE  --  If the answering machine is on, save a sound
  97.                     buffer in the answering machine file.  */
  98.                     
  99. void answerSave(struct in_addr IPaddr, LPSTR hostName, soundbuf *sb)
  100. {
  101.     if (answerRecord && answerFile != NULL) {
  102.         struct respHeader r;
  103.         char lh[MAX_HOST];
  104.         long scomp;
  105.         
  106.         fseek(answerFile, answerLen, 0);
  107.         r.hostIPnumber = IPaddr;
  108.         r.itemTime = time(NULL);
  109.         r.hostNameLength = lstrlen(hostName) + 1;
  110.         r.soundBufLength = (WORD) (sb->buffer.buffer_len + (sizeof(soundbuf) - BUFL));
  111.         fwrite(&r, sizeof r, 1, answerFile);
  112.         _fmemcpy(lh, hostName, r.hostNameLength);
  113.         fwrite(lh, r.hostNameLength, 1, answerFile);
  114.         scomp = sb->compression;
  115.         sb->compression = fPlayback | (((r.itemTime - lastPacket) > newMessageCriterion) ?
  116.             fAnsNewMsg : 0) | (scomp & fComp2X);
  117.         lastPacket = r.itemTime; 
  118.         fwrite(sb, r.soundBufLength, 1, answerFile);
  119.         if ((hDlgAnswer != NULL) && (sb->compression & fAnsNewMsg)) {
  120.             if (growMessageTable(hDlgAnswer, msgCount + 1)) {
  121.                 msgTable[msgCount++] = answerLen;
  122.                 setMessageCount();
  123.             }
  124.         } 
  125.         sb->compression = scomp;
  126.         answerLen = ftell(answerFile);
  127.         if (hDlgAnswer != NULL) {
  128.             EnableWindow(GetDlgItem(hDlgAnswer, IDC_RP_NEXT), answerLen > 0);
  129.             EnableWindow(GetDlgItem(hDlgAnswer, IDC_RP_ERASE), answerLen > 0);
  130.         }
  131.     }
  132. }
  133.  
  134. /*  ANSWERSYNC  --  Make sure output data are written to file.  */
  135.  
  136. void answerSync(void)
  137. {
  138.     if (answerFile != NULL) {
  139.         fflush(answerFile);
  140.     }
  141. }
  142.  
  143. /*  ANSWERCLOSE  --  Close the answering machine.  */
  144.  
  145. void answerClose(void)
  146. {
  147.     if (answerFile != NULL) {
  148.         fclose(answerFile);
  149.         answerFile = NULL;
  150.     }
  151. }
  152.  
  153. /*  ANSWERREPLAY  --  Begin replay of answering machine.  */
  154.  
  155. static void answerReplay(void)
  156. {
  157.     answerSync();
  158.     replaying = TRUE;
  159. }
  160.  
  161. /*  ANSWERREAD  --  Read the next buffer from the answering machine.  */
  162.  
  163. static int answerRead(struct in_addr *IPaddr, time_t *rtime,
  164.                       char *hostName, soundbuf *sb)
  165. {
  166.     struct respHeader r;
  167.     
  168.     fseek(answerFile, answerPlayPos, 0);
  169.     if (fread(&r, sizeof r, 1, answerFile) != 1) {
  170.         return FALSE;
  171.     }
  172.     *IPaddr = r.hostIPnumber;
  173.     *rtime = r.itemTime;
  174.     if (fread(hostName, r.hostNameLength, 1, answerFile) != 1) {
  175.         return FALSE;
  176.     }
  177.     if (fread(sb, r.soundBufLength, 1, answerFile) != 1) {
  178.         return FALSE;
  179.     }
  180.     answerPlayPos = ftell(answerFile);
  181.     return TRUE;
  182. }
  183.  
  184. /*  ANSWERREPLAYDONE  --  End replay of answer file.  */
  185.  
  186. static void answerReplayDone(void)
  187. {
  188.     replaying = FALSE;
  189.     answerPlayPos = 0;
  190. }
  191.  
  192. //    SCANMESSAGEFILE  --  Built in-memory message table
  193.  
  194. static void scanMessageFile(HWND hwnd)
  195. {
  196.     struct in_addr IPaddr;
  197.     char hostName[MAX_HOST];
  198.     time_t t;
  199.     long lp;
  200.     
  201.     answerPlayPos = 0;
  202.     msgCount = 0;
  203.     if (answerFile != NULL) {                    
  204.         while (lp = answerPlayPos, answerRead(&IPaddr, &t, hostName, &ebuf)) {
  205.             if (ebuf.compression & fAnsNewMsg) {
  206.                 if (!growMessageTable(hwnd, msgCount + 1)) {
  207.                     return;
  208.                 }
  209.                 msgTable[msgCount++] = lp;
  210.             }    
  211.         }
  212.         answerPlayPos = 0;
  213.     }
  214. }
  215.  
  216. //    ANSWERDLGPROC  --  Answering machine dialogue procedure
  217.  
  218. BOOL CALLBACK answerDlgProc(HWND hwnd, UINT nMessage,
  219.                             WPARAM wParam, LPARAM lParam)
  220. {
  221.     static int replaying;
  222.     static int firstPacket, hostShown, hostPrelim;
  223.     static int buttonPushed;
  224.  
  225.     switch (nMessage) {
  226.         case WM_INITDIALOG:
  227.             replaying = FALSE;
  228.             hDlgAnswer = hwnd;
  229.             msgMax = 50;
  230.             msgTable = (long FAR *) GlobalAllocPtr(GPTR, msgMax * sizeof(long));
  231.             if (msgTable == NULL) {
  232.                 MessageBox(hwnd, rstring(IDS_T_ALLOC_MSG_TABLE_ERR),
  233.                        NULL, MB_OK | MB_ICONEXCLAMATION);
  234.                    DestroyWindow(hwnd);
  235.             }
  236.             scanMessageFile(hwnd);
  237. setIdle:    EnableWindow(GetDlgItem(hwnd, IDC_RP_PREV), FALSE);
  238.             EnableWindow(GetDlgItem(hwnd, IDC_RP_REPLAY), FALSE);
  239.             EnableWindow(GetDlgItem(hwnd, IDC_RP_REWIND), FALSE);
  240.             EnableWindow(GetDlgItem(hwnd, IDC_RP_NEXT), answerFile && msgCount > 0);
  241.             EnableWindow(GetDlgItem(hwnd, IDC_RP_ERASE), answerFile && answerLen > 0);
  242.             EnableWindow(GetDlgItem(hwnd, IDC_RP_RECORD), answerFile != NULL); 
  243.             CheckDlgButton(hwnd, IDC_RP_RECORD, answerFile && answerRecord);
  244.             if (answerFileName != NULL) {
  245.                 SetDlgItemText(hwnd, IDC_RP_MSGFILE, answerFileName);
  246.             } 
  247.             SetDlgItemText(hwnd, IDC_RP_SITE, "");
  248.             SetDlgItemText(hwnd, IDC_RP_TIME, "");
  249.             currentMessage = -1;            // Nothing played yet
  250.             buttonPushed = 0;
  251.             setMessageCount();
  252.             return TRUE;
  253.             
  254.         case WM_CLOSE:
  255.             DestroyWindow(hwnd);
  256.             return TRUE;
  257.  
  258.         case WM_COMMAND:
  259.             switch ((int) wParam) {
  260.             
  261.                 case IDC_RP_PREV:
  262.                     currentMessage--;
  263.                     goto playCurrent;
  264.             
  265.                 case IDC_RP_NEXT:
  266.                     currentMessage++;
  267.                             
  268.                 case IDC_RP_REPLAY:
  269. playCurrent:        setMessageCount();
  270.                     buttonPushed = wParam; 
  271.                     if (obtainOutput(hwndMDIFrame)) {
  272.                         answerReplay();
  273.                         answerPlayPos = msgTable[currentMessage];
  274.                         //    Disable controls to prevent mischief while we're playing
  275.                         EnableWindow(GetDlgItem(hwnd, IDC_RP_PREV), FALSE);
  276.                         EnableWindow(GetDlgItem(hwnd, IDC_RP_NEXT), FALSE);
  277.                         EnableWindow(GetDlgItem(hwnd, IDC_RP_REPLAY), FALSE);
  278.                         EnableWindow(GetDlgItem(hwnd, IDC_RP_ERASE), FALSE);
  279.                         EnableWindow(GetDlgItem(hwnd, IDC_RP_REWIND), FALSE);
  280.                         EnableWindow(GetDlgItem(hwnd, IDC_RP_BROWSE), FALSE);
  281.                         replaying = TRUE;
  282.                         firstPacket = TRUE;
  283.                         hostShown = hostPrelim = FALSE;
  284.                         SetTimer(hwnd, 5, 1, NULL);
  285.                     }
  286.                     break;
  287.             
  288.                 case IDC_RP_ERASE:
  289.                     fclose(answerFile);
  290.                     answerFile = fopen(answerFileName, "w+b");
  291.                     msgCount = 0;
  292.                     answerLen = 0;
  293.                     //    Note fall-through
  294.             
  295.                 case IDC_RP_REWIND: 
  296.                     goto setIdle;
  297.                     
  298.                 case IDC_RP_BROWSE:
  299.                      {
  300.                          OPENFILENAME ofn;
  301.                          char szString[MAX_PATH];
  302.             
  303.                         memset(&ofn, 0, sizeof(ofn));
  304.                         ofn.lStructSize = sizeof(OPENFILENAME);
  305.                         ofn.hwndOwner = hwnd;
  306.                         ofn.lpstrFilter = rfilter(IDS_T_ANSWER_MESSAGE_FILTER);
  307.                         ofn.lpstrCustomFilter = NULL;
  308.                         strcpy(szString, answerFileName);
  309.                         ofn.lpstrFile = (LPSTR) szString;
  310.                         ofn.nMaxFile = sizeof(szString);
  311.                         ofn.lpstrInitialDir = NULL;
  312.                         ofn.lpstrTitle = rstring(IDS_T_ANSWER_OPEN_TITLE);
  313.                         ofn.Flags = OFN_NOREADONLYRETURN | OFN_HIDEREADONLY | OFN_SHOWHELP;
  314.                         fileHelpKey = rstring(IDS_HELP_ANSWER);
  315.                         if (GetOpenFileName((LPOPENFILENAME) &ofn)) {
  316.                             SetDlgItemText(hwnd, IDC_RP_MSGFILE, szString);
  317.                             _fstrcpy(answerFileName, szString);
  318.                             answerClose();
  319.                             answerOpen();
  320.                             currentMessage = -1;
  321.                             scanMessageFile(hwnd);
  322.                             EnableWindow(GetDlgItem(hwnd, IDC_RP_PREV), FALSE);
  323.                             EnableWindow(GetDlgItem(hwnd, IDC_RP_REWIND), FALSE);
  324.                             EnableWindow(GetDlgItem(hwnd, IDC_RP_REPLAY), FALSE);
  325.                             EnableWindow(GetDlgItem(hwnd, IDC_RP_NEXT), answerFile && msgCount > 0);
  326.                             EnableWindow(GetDlgItem(hwnd, IDC_RP_ERASE), answerFile && answerLen > 0);
  327.                             EnableWindow(GetDlgItem(hwnd, IDC_RP_RECORD), answerFile != NULL); 
  328.                             SetDlgItemText(hwnd, IDC_RP_SITE, "");
  329.                             SetDlgItemText(hwnd, IDC_RP_TIME, "");
  330.                             setMessageCount();
  331.                         }
  332.                     }
  333.                     break;
  334.                     
  335.                 case IDC_RP_RECORD:
  336.                     answerRecord = IsDlgButtonChecked(hwnd, IDC_RP_RECORD);
  337.                     break;
  338.             
  339.                 case IDOK:
  340.                     answerRecord = IsDlgButtonChecked(hwnd, IDC_RP_RECORD);
  341.                     PostMessage(hwnd, WM_CLOSE, 0, 0L);
  342.                     break;
  343.                     
  344.                 case ID_HELP:
  345.                     WinHelp(hwndMDIFrame, rstring(IDS_HELPFILE), HELP_KEY,
  346.                                 ((DWORD) (Lrstring(IDS_HELP_ANSWER))));
  347.                     holped = TRUE;
  348.                     break;
  349.             }
  350.             return FALSE;
  351.             
  352.         case WM_DESTROY:
  353.             if (replaying) {
  354.                 KillTimer(hwnd, 5);
  355.             }
  356.             if (msgTable != NULL) {
  357.                 GlobalFreePtr(msgTable);
  358.                 msgTable = NULL;
  359.             }
  360.             hDlgAnswer = NULL;
  361.             return 0;
  362.                     
  363.         case WM_TIMER:
  364.             {
  365.                 struct in_addr IPaddr;
  366.                 char hostName[MAX_HOST];
  367.                 time_t t;
  368.                 DWORD startTicks = GetTickCount();
  369.                 long et, sfp;
  370.                 int ateof = FALSE;
  371.                         
  372.                 if (replaying) {
  373.                     sfp = answerPlayPos;
  374.                     if (answerRead(&IPaddr, &t, hostName, &ebuf)) {
  375.                         if (firstPacket || !(ebuf.compression & fAnsNewMsg)) { 
  376.                             firstPacket = FALSE;
  377.                             playSound(hwndMDIFrame, NULL, &ebuf, aboutOutBits, aboutOutSamples);
  378.                             
  379.                             if (!hostShown) {
  380.                                 char ft[24];
  381.                                 struct tm *lt;
  382.                                 
  383.                                 //    Update host when definitive name seen
  384.                                 if (hostName[0] != '(') {
  385.                                     hostShown = TRUE;
  386.                                     hostPrelim = FALSE;
  387.                                 }
  388.                                 
  389.                                 if (!hostPrelim) {
  390.                                     lt = localtime(&t);        
  391.                                     sprintf(ft, Format(49), rstring(IDS_WEEKDAYS + lt->tm_wday),
  392.                                         lt->tm_year, lt->tm_mon + 1, lt->tm_mday,
  393.                                         lt->tm_hour, lt->tm_min, lt->tm_sec); 
  394.                                     SetDlgItemText(hwnd, IDC_RP_TIME, ft);
  395.                                     SetDlgItemText(hwnd, IDC_RP_SITE, hostName);
  396.                                     hostPrelim = TRUE;
  397.                                 }
  398.                             }
  399.                             
  400.                             /* The following code is needed because when we're reading
  401.                                sound from a file, as opposed to receiving it in real
  402.                                time from the CODEC, we must meter out the samples
  403.                                at the rate they will actually be played by the destination
  404.                                machine.  For 8000 samples per second, this amounts
  405.                                to 125 microseconds per sample. */
  406.                 
  407. #define kOverhead 30000L
  408.                             et = ((ebuf.buffer.buffer_len * 125L) - kOverhead) -
  409.                                 ((GetTickCount() - startTicks) * 1000);
  410.                             if (et <= 0) {
  411.                                 et = 1;
  412.                             }
  413.                             SetTimer(hwnd, 5, (UINT) (et / 1000), NULL);
  414.                         } else {
  415.                             answerPlayPos = sfp;
  416.                             replaying = FALSE;
  417.                         }
  418.                     } else {
  419.                         replaying = FALSE;
  420.                         ateof = TRUE;
  421.                     }                            
  422.                 }
  423.                 if (!replaying) {
  424.                     answerReplayDone();
  425.                     KillTimer(hwnd, 5);
  426.                     EnableWindow(GetDlgItem(hwnd, IDC_RP_PREV), currentMessage > 0);
  427.                     EnableWindow(GetDlgItem(hwnd, IDC_RP_NEXT), !ateof);
  428.                     EnableWindow(GetDlgItem(hwnd, IDC_RP_REPLAY), currentMessage >= 0);
  429.                     EnableWindow(GetDlgItem(hwnd, IDC_RP_REWIND), TRUE);
  430.                     EnableWindow(GetDlgItem(hwnd, IDC_RP_ERASE), TRUE);
  431.                     EnableWindow(GetDlgItem(hwnd, IDC_RP_BROWSE), TRUE);
  432.                     
  433.                     /*    Restore focus to the button we pushed, or the logical
  434.                         successor if it isn't enabled any more.  */
  435.                     
  436.                     if (buttonPushed != 0 && !IsWindowEnabled(GetDlgItem(hwnd, buttonPushed))) {
  437.                         if (IsWindowEnabled(GetDlgItem(hwnd, IDC_RP_NEXT))) {
  438.                             buttonPushed = IDC_RP_NEXT; 
  439.                         } else if (IsWindowEnabled(GetDlgItem(hwnd, IDC_RP_PREV))) {
  440.                             buttonPushed = IDC_RP_PREV; 
  441.                         } else if (IsWindowEnabled(GetDlgItem(hwnd, IDC_RP_REPLAY))) {
  442.                             buttonPushed = IDC_RP_REPLAY; 
  443.                         } else {
  444.                             buttonPushed = IDOK;
  445.                         }  
  446.                     }
  447.                     SetFocus(GetDlgItem(hwnd, buttonPushed));
  448.                 }
  449.             }
  450.             break;
  451.             
  452.         default:
  453.             if (nMessage == fileOpenHelpButton && fileHelpKey != NULL) {
  454.                 WinHelp(hwndMDIFrame, rstring(IDS_HELPFILE), HELP_KEY,
  455.                             ((DWORD) (LPSTR) fileHelpKey));
  456.                 holped = TRUE;
  457.             }
  458.             break;            
  459.     }
  460.     return FALSE;
  461. }
  462.  
  463. //    ANSWERDIALOGUE  --  Answering machine dialogue
  464.  
  465. VOID answerDialogue(HWND hwndParent)
  466. {
  467.     hDlgAnswer = CreateDialog(hInst, MAKEINTRESOURCE(IDD_REPONDEUR),
  468.                     hwndParent, (DLGPROC) pfnAnswer);
  469. }
  470.                     
  471.                     
  472.