home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / xwphescr.zip / XWPH0208.ZIP / src / helpers / syssound.c < prev    next >
C/C++ Source or Header  |  2002-07-05  |  28KB  |  780 lines

  1.  
  2. /*
  3.  *@@sourcefile syssound.c:
  4.  *      this has code for querying and manipulating the
  5.  *      system sounds, which are stored in MMPM.INI in
  6.  *      the MMOS2 directory. Also, we have support for
  7.  *      manipulating Warp 4 sound schemes in here too.
  8.  *      This code works on Warp 3 also.
  9.  *
  10.  *      Usage: All OS/2 programs.
  11.  *
  12.  *      Some of this code used to be in XWorkplace's main\common.c,
  13.  *      as far as the regular system sounds were concerned.
  14.  *      However, all this code has been greatly reworked
  15.  *      and extended with V0.9.0.
  16.  *
  17.  *      <B>About system sound configuration data</B>
  18.  *
  19.  *      The current system sounds are stored in ?:\MMOS2\MMPM.INI.
  20.  *
  21.  *      These are the general flags in the "MMPM2_AlarmSoundsData"
  22.  *      application:
  23.  *
  24.  *      --  If "EnableSounds" is FALSE, all system sounds are disabled.
  25.  *          This defaults to TRUE (tested).
  26.  *
  27.  *      --  If "ApplyVolumeToAll" is TRUE, the same volume is used for
  28.  *          all sounds. This defaults to FALSE (tested).
  29.  *
  30.  *      --  If ApplyVolumeToAll is TRUE, "Volume" is used for the
  31.  *          global volume. Otherwise, the individual sound volumes
  32.  *          (below) will be used.
  33.  *
  34.  *      "MMPM2_AlarmSounds" then has all the system sounds. The keys
  35.  *      in that application are numerical indices, which are listed
  36.  *      in syssound.h.
  37.  *
  38.  *      Each sound data block in there consists of three elements:
  39.  *
  40.  +          soundfile#description#volume
  41.  *
  42.  *      where "description" is what is listed in the "Sound" object.
  43.  *      "volume" is only used when "ApplyVolumeToAll" (above) is FALSE.
  44.  *
  45.  *      We have functions in this code file for decoding/setting this
  46.  *      (sndParseSoundData, sndQuerySystemSound, sndWriteSoundData,
  47.  *      sndSetSystemSound).
  48.  *
  49.  *      By contrast (and for no real reason), Warp 4 stores the
  50.  *      "sound schemes" in OS2SYS.INI. I stuck with that for compatibility,
  51.  *      although this prevents several users from having different
  52.  *      sound schemes. What the heck.
  53.  *
  54.  *      Anyways, the "PM_SOUND_SCHEMES_LIST" application is a directory of
  55.  *      schemes, which in turn point to other applications in OS2SYS.INI
  56.  *      which have the actual sound scheme data. All these applications
  57.  *      appear to start with "PM_SOUND_xxx" by convention.
  58.  *
  59.  *      Note that as opposed to the sound data in MMPM.INI, only the
  60.  *      sound file name is stored here (not the three elements as
  61.  *      described above). We slightly extend that mechanism to add an
  62.  *      additional volume data field after the first null byte. This
  63.  *      allows the default WPSound object to still be able to read
  64.  *      the sound scheme data (it apparently uses PrfQueryProfileString)
  65.  *      while the XWorkplace sound object replacement (XWPSound) can
  66.  *      still store volume data as well.
  67.  *
  68.  *      I have created more functions in this code file to easily load and
  69.  *      store sound schemes (sndDoesSchemeExist, sndCreateSoundScheme,
  70.  *      sndLoadSoundScheme, sndDestroySoundScheme).
  71.  *
  72.  *      Note: Version numbering in this file relates to XWorkplace version
  73.  *            numbering.
  74.  *
  75.  *@@header "helpers\syssound.h"
  76.  *@@added V0.9.0 [umoeller]
  77.  */
  78.  
  79. #define OS2EMX_PLAIN_CHAR
  80.     // this is needed for "os2emx.h"; if this is defined,
  81.     // emx will define PSZ as _signed_ char, otherwise
  82.     // as unsigned char
  83.  
  84. #define INCL_DOSERRORS
  85. #define INCL_WINSHELLDATA
  86. #include <os2.h>
  87.  
  88. #include <stdlib.h>
  89. #include <stdio.h>
  90. #include <string.h>
  91.  
  92. #include "setup.h"                      // code generation and debugging options
  93.  
  94. #include "helpers\dosh.h"
  95. #include "helpers\prfh.h"
  96.  
  97. #include "helpers\syssound.h"
  98.  
  99. #pragma hdrstop
  100.  
  101. /*
  102.  *@@category: Helpers\Profile (INI) helpers\System sounds
  103.  *      see syssound.c.
  104.  */
  105.  
  106. /*
  107.  *@@ sndParseSoundData:
  108.  *      this helper func splits the system sound data
  109.  *      passed to it into three buffers.
  110.  *      Each key data in there has the following format:
  111.  +          soundfile#description#volume.
  112.  *
  113.  *      This is copied into the three specified buffers.
  114.  *      You can set any buffer pointer to NULL if you're
  115.  *      not interested in that data.
  116.  *
  117.  *      Returns the number of items successfully parsed,
  118.  *      which should be 3.
  119.  *
  120.  *@@added V0.9.0 [umoeller]
  121.  *@@changed V0.9.20 (2002-07-03) [umoeller]: optimized
  122.  */
  123.  
  124. ULONG sndParseSoundData(PCSZ pszSoundData,  // in: INI data from MMPM.INI
  125.                         PSZ pszDescr,    // out: sound description, as displayed
  126.                                // in the "Sound" object (ptr may be NULL)
  127.                         PSZ pszFile,     // out: sound file to (ptr may be NULL)
  128.                         PULONG pulVolume)  // out: sound volume (0-100). Note:
  129.                                // this always returns the individual sound volume,
  130.                                // even if "Global volume" is set in MMPM.INI.
  131. {
  132.     PCSZ        p1 = pszSoundData, p2;
  133.     ULONG       ulrc = 0;
  134.     // get sound file
  135.     if (p2 = strchr(p1, '#'))
  136.     {
  137.         ulrc++;
  138.         if (pszFile)
  139.         {
  140.             strncpy(pszFile, p1, p2 - p1);
  141.             pszFile[p2-p1] = '\0';
  142.         }
  143.         p1 = p2+1;
  144.  
  145.         // get sound description
  146.         if (p2 = strchr(p1, '#'))
  147.         {
  148.             ulrc++;
  149.             if (pszDescr)
  150.             {
  151.                 strncpy(pszDescr, p1, p2-p1);
  152.                 pszDescr[p2-p1] = '\0';
  153.             }
  154.             p1 = p2+1;
  155.  
  156.             // get volume (0-100)
  157.             if (pulVolume)
  158.             {
  159.                 // individual volume settings per sound
  160.                 *pulVolume = atoi(p1);      // V0.9.20 (2002-07-03) [umoeller]
  161.                 // sscanf(p1, "%lu", pulVolume);
  162.                 ulrc++;
  163.             }
  164.         }
  165.     }
  166.  
  167.     return ulrc;
  168. }
  169.  
  170. /*
  171.  *@@ sndQueryMmpmIniPath:
  172.  *      writes the full path of MMPM.INI into
  173.  *      the specified buffer (e.g. C:\MMOS2\MMPM.INI).
  174.  *
  175.  *@@added V0.9.10 (2001-04-16) [umoeller]
  176.  */
  177.  
  178. VOID sndQueryMmpmIniPath(PSZ pszMMPM)       // out: fully q'fied MMPM.INI
  179. {
  180.     PSZ pszMMPMPath;
  181.     if (pszMMPMPath = getenv("MMBASE"))  // V0.9.6 (2000-10-16) [umoeller]
  182.     {
  183.         // variable set:
  184.         PSZ p;
  185.  
  186.         strcpy(pszMMPM, pszMMPMPath); // V0.9.7 (2000-12-17) [umoeller]
  187.  
  188.         // kill semicolon if present
  189.         if (p = strchr(pszMMPM, ';'))
  190.            *p = 0;
  191.  
  192.         strcat(pszMMPM, "\\MMPM.INI");
  193.     }
  194.     else
  195.         // variable not set (shouldn't happen): try boot drive
  196.         sprintf(pszMMPM, "%c:\\MMOS2\\MMPM.INI", doshQueryBootDrive());
  197. }
  198.  
  199. /*
  200.  *@@ sndOpenMmpmIni:
  201.  *      this opens \MMOS2\MMPM.INI on the
  202.  *      boot drive and returns the profile
  203.  *      handle (or NULLHANDLE upon errors).
  204.  *      Use PrfCloseProfile to close the
  205.  *      profile again.
  206.  *
  207.  *@@added V0.9.1 (99-12-19) [umoeller]
  208.  *@@changed V0.9.6 (2000-10-16) [umoeller]: now using MMBASE environment variable
  209.  *@@changed V0.9.6 (2000-10-16) [umoeller]: added proper HAB param
  210.  *@@changed V0.9.7 (2000-12-17) [umoeller]: fixed broken MMBASE handling
  211.  */
  212.  
  213. HINI sndOpenMmpmIni(HAB hab)
  214. {
  215.     HAB     habDesktop = WinQueryAnchorBlock(HWND_DESKTOP);
  216.     CHAR    szMMPM[CCHMAXPATH];
  217.  
  218.     sndQueryMmpmIniPath(szMMPM);
  219.  
  220.     return PrfOpenProfile(habDesktop, szMMPM);
  221. }
  222.  
  223. /*
  224.  *@@ sndQuerySystemSound:
  225.  *      this gets a system sound from the MMPM.INI file.
  226.  *      usIndex must be the sound to query. The following
  227.  *      MMSOUND_* IDs are declared in syssound.h:
  228.  *
  229.  *      Default system sounds (syssound.h):
  230.  *      --  MMSOUND_WARNING         0
  231.  *      --  MMSOUND_INFORMATION     1
  232.  *      --  MMSOUND_ERROR           2
  233.  *      --  MMSOUND_ANIMATEOPEN     3
  234.  *      --  MMSOUND_ANIMATECLOSE    4
  235.  *      --  MMSOUND_DRAG            5
  236.  *      --  MMSOUND_DROP            6
  237.  *      --  MMSOUND_SYSTEMSTARTUP   7
  238.  *      --  MMSOUND_SHUTDOWN        8
  239.  *      --  MMSOUND_SHREDDER        9
  240.  *      --  MMSOUND_LOCKUP          10
  241.  *      --  MMSOUND_ALARMCLOCK      11
  242.  *      --  MMSOUND_PRINTERROR      12
  243.  *
  244.  *      BTW, these values match those of the WinAlarm call
  245.  *      (WA_* values), but only the first three are documented
  246.  *      in PMREF and pmwin.h (WA_WARNING, WA_NOTE, WA_ERROR).
  247.  *
  248.  *      New XWorkplace system sounds:
  249.  *      --  MMSOUND_XFLD_SHUTDOWN   555
  250.  *      --  MMSOUND_XFLD_RESTARTWPS 556
  251.  *      --  MMSOUND_XFLD_CTXTOPEN   558
  252.  *      --  MMSOUND_XFLD_CTXTSELECT 559
  253.  *      --  MMSOUND_XFLD_CNRDBLCLK  560
  254.  *
  255.  *      The string buffers are recommended to be at least
  256.  *      CCHMAXPATH in size.
  257.  *
  258.  *@@changed V0.9.0 [umoeller]: this used to be cmnQuerySystemSound
  259.  *@@changed V0.9.0 [umoeller]: exported stuff to sndParseSoundData
  260.  *@@changed V0.9.6 (2000-10-16) [umoeller]: added proper HAB param
  261.  */
  262.  
  263. BOOL sndQuerySystemSound(HAB hab,           // in: caller's anchor block
  264.                          USHORT usIndex,    // in: sound index to query
  265.                          PSZ pszDescr,      // out: sound description, as displayed
  266.                                 // in the "Sound" object (ptr may be NULL)
  267.                          PSZ pszFile,       // out: sound file to (ptr may be NULL)
  268.                          PULONG pulVolume)  // out: sound volume (0-100).
  269.                                 // If the "Global volume" flag is
  270.                                 // set in MMPM.INI, this will return the global
  271.                                 // volume instead. Ptr may be NULL also.
  272. {
  273.     BOOL    rc = FALSE;
  274.     HINI    hiniMMPM = sndOpenMmpmIni(hab);
  275.  
  276.     #ifdef DEBUG_SOUNDS
  277.         _Pmpf((__FUNCTION__ ": entering, hiniMMPM is 0x%lX", hiniMMPM));
  278.     #endif
  279.  
  280.     if (hiniMMPM)
  281.     {
  282.         CHAR szData[1000];
  283.         CHAR szData2[100];
  284.         CHAR szKey[10];
  285.         sprintf(szKey, "%d", usIndex);
  286.         PrfQueryProfileString(hiniMMPM,
  287.                               MMINIKEY_SOUNDSETTINGS, "EnableSounds",
  288.                               "TRUE",    // default string
  289.                               szData2, sizeof(szData2));
  290.         #ifdef DEBUG_SOUNDS
  291.             _Pmpf(("  sounds enabled: %s", szData2));
  292.         #endif
  293.         if (strcmp(szData2, "TRUE") == 0)
  294.             // sounds enabled at all?
  295.             if (PrfQueryProfileString(hiniMMPM,
  296.                                       MMINIKEY_SYSSOUNDS, szKey,
  297.                                       ".",
  298.                                       szData, sizeof(szData)-1) > 3)
  299.             {
  300.                 sndParseSoundData(szData,
  301.                                   pszDescr,
  302.                                   pszFile,
  303.                                   pulVolume);
  304.  
  305.                 // if "global volume" has been enabled,
  306.                 // we do not return the value specified
  307.                 // here, but the global value
  308.                 PrfQueryProfileString(hiniMMPM,
  309.                                       MMINIKEY_SOUNDSETTINGS, "ApplyVolumeToAll",
  310.                                       "FALSE",
  311.                                       szData2, sizeof(szData2));
  312.                 if (strcmp(szData2, "FALSE") != 0)
  313.                 {
  314.                     // global volume setting for all sounds
  315.                     PrfQueryProfileString(hiniMMPM,
  316.                                           MMINIKEY_SOUNDSETTINGS, "Volume",
  317.                                           "100",
  318.                                           szData2, sizeof(szData2));
  319.                     sscanf(szData2, "%lu", pulVolume);
  320.                 }
  321.  
  322.                 rc = TRUE;
  323.             }
  324.  
  325.         PrfCloseProfile(hiniMMPM);
  326.     }
  327.  
  328.     return rc;
  329. }
  330.  
  331. /*
  332.  *@@ sndWriteSoundData:
  333.  *      this sets a system sound in MMPM.INI.
  334.  *      Gets called by sndSetSystemSound. As opposed
  335.  *      to that function, this needs the profile handle
  336.  *      of MMPM.INI.
  337.  *
  338.  *      If (pszDescr == NULL), that sound entry is removed.
  339.  *
  340.  *      Returns the return value of PrfWriteProfileString.
  341.  *
  342.  *@@added V0.9.0 [umoeller]
  343.  *@@changed V0.9.1 (99-12-30) [umoeller]: added delete support
  344.  *@@changed V0.9.6 (2000-10-16) [umoeller]: added MMPM/2 notify
  345.  */
  346.  
  347. BOOL sndWriteSoundData(HINI hiniMMPM,       // in: MMPM.INI handle (from sndOpenMmpmIni)
  348.                        USHORT usIndex,      // in: sound index
  349.                        PCSZ pszDescr,       // in: sound name or NULL for removal
  350.                        PCSZ pszFile,        // in: sound file
  351.                        ULONG ulVolume)      // in: sound volume
  352. {
  353.     BOOL    brc = FALSE;
  354.     CHAR    szKey[10];
  355.  
  356.     sprintf(szKey, "%d", usIndex);
  357.     if (pszDescr)
  358.     {
  359.         CHAR szData[1000];
  360.         // format: soundfile#description#volume
  361.         sprintf(szData, "%s#%s#%lu", pszFile, pszDescr, ulVolume);
  362.         brc = PrfWriteProfileString(hiniMMPM,
  363.                                     MMINIKEY_SYSSOUNDS,
  364.                                     szKey,
  365.                                     szData);
  366.     }
  367.     else
  368.         // pszDescr == NULL:
  369.         // delete entry
  370.         brc = PrfWriteProfileString(hiniMMPM,
  371.                                     MMINIKEY_SYSSOUNDS,
  372.                                     szKey,
  373.                                     NULL);
  374.  
  375.     if (brc)
  376.         // success:
  377.         if (usIndex < 100)
  378.             // one of the default OS/2 sounds has changed:
  379.             // we then need to notify MMPM/2...
  380.             // this is done by calling WinAlarm with 1000+index!
  381.             // sick stuff..
  382.             WinAlarm(HWND_DESKTOP, usIndex+1000); // V0.9.6 (2000-10-16) [umoeller]
  383.  
  384.     return brc;
  385. }
  386.  
  387. /*
  388.  *@@ sndSetSystemSound:
  389.  *      this sets a system sound in MMPM.INI by
  390.  *      calling sndWriteSoundData.
  391.  *      Returns FALSE if an error occured.
  392.  *
  393.  *      See sndQuerySystemSound for the parameters.
  394.  *
  395.  *@@changed V0.9.0 [umoeller]: this used to be cmnSetSystemSound
  396.  *@@changed V0.9.0 [umoeller]: exported stuff to sndWriteSoundData
  397.  *@@changed V0.9.6 (2000-10-16) [umoeller]: added proper HAB param
  398.  */
  399.  
  400. BOOL sndSetSystemSound(HAB hab,
  401.                        USHORT usIndex,
  402.                        PCSZ pszDescr,
  403.                        PCSZ pszFile,
  404.                        ULONG ulVolume)
  405. {
  406.     BOOL    brc = FALSE;
  407.     HINI    hiniMMPM;
  408.     if (hiniMMPM = sndOpenMmpmIni(hab))
  409.     {
  410.         brc = sndWriteSoundData(hiniMMPM, usIndex, pszDescr, pszFile, ulVolume);
  411.         PrfCloseProfile(hiniMMPM);
  412.     }
  413.  
  414.     return brc;
  415. }
  416.  
  417. /*
  418.  *@@ sndDoesSchemeExist:
  419.  *      returns TRUE if pszScheme already exists
  420.  *      in OS2SYS.INI.
  421.  *
  422.  *      If so, and *ppszRealScheme is != NULL, it
  423.  *      is set to the key name found. Since the
  424.  *      scheme names are case-insensitive, this
  425.  *      check is necessary to delete the original
  426.  *      scheme for overwrites. The caller is
  427.  *      responsible for free()ing *ppszRealScheme
  428.  *      then.
  429.  *
  430.  *@@added V0.9.0 [umoeller]
  431.  *@@changed V0.9.20 (2002-07-03) [umoeller]: check has to be case-insensitive, fixed; changed prototype
  432.  */
  433.  
  434. BOOL sndDoesSchemeExist(PCSZ pcszScheme,
  435.                         PSZ *ppszRealScheme)    // out: actual key name (ptr can be NULL)
  436. {
  437.     BOOL fExists = FALSE;
  438.     PSZ pszKeysList;
  439.     if (!prfhQueryKeysForApp(HINI_SYSTEM,
  440.                              MMINIKEY_SOUNDSCHEMES,  // "PM_SOUND_SCHEMES_LIST"
  441.                              &pszKeysList))
  442.     {
  443.         PSZ pKey2 = pszKeysList;
  444.         while (*pKey2)
  445.         {
  446.             if (!stricmp(pKey2, pcszScheme))
  447.             {
  448.                 fExists = TRUE;
  449.  
  450.                 if (ppszRealScheme)
  451.                     *ppszRealScheme = strdup(pKey2);
  452.  
  453.                 break;
  454.             }
  455.  
  456.             pKey2 += strlen(pKey2)+1; // next key
  457.         }
  458.  
  459.         free(pszKeysList);
  460.     }
  461.  
  462.     return fExists;
  463.  
  464.     /* old code V0.9.20 (2002-07-03) [umoeller]
  465.     // check in OS2SYS.INI's scheme list whether that
  466.     // scheme exists already
  467.     PSZ pszExisting = prfhQueryProfileData(HINI_SYSTEM,
  468.                                            MMINIKEY_SOUNDSCHEMES,  // "PM_SOUND_SCHEMES_LIST"
  469.                                            pszScheme,
  470.                                            NULL);
  471.     if (pszExisting)
  472.     {
  473.         free(pszExisting);
  474.         return (TRUE);
  475.     }
  476.  
  477.     return (FALSE);
  478.     */
  479.  
  480. }
  481.  
  482. /*
  483.  *@@ sndCreateSoundScheme:
  484.  *      this creates a new sound scheme and copies
  485.  *      the current data in MMPM.INI into it.
  486.  *      No check is made for whether that sound
  487.  *      scheme exists already (use sndDoesSchemeExist
  488.  *      for that). Data is overwritten without further
  489.  *      discussion.
  490.  *
  491.  *      Returns:
  492.  *      --  NO_ERROR
  493.  *      --  ERROR_INVALID_HANDLE: hiniMMPM invalid
  494.  *      --  ERROR_NO_DATA: scheme not found.
  495.  *
  496.  *@@added V0.9.0 [umoeller]
  497.  */
  498.  
  499. APIRET sndCreateSoundScheme(HINI hiniMMPM,      // in: MMPM.INI handle (from sndOpenMmpmIni)
  500.                             PCSZ pszNewScheme)  // in: name of new scheme
  501. {
  502.     APIRET  arc = NO_ERROR;
  503.     CHAR    szNewAppName[200] = "PM_SOUNDS_";
  504.  
  505.     // create a unique new application name for
  506.     // this scheme in OS2SYS.INI (this is how
  507.     // Warp 4 apparently does it)
  508.     strcat(szNewAppName, pszNewScheme);  // PM_SOUNDS_blahblah
  509.     strupr(szNewAppName);               // PM_SOUNDS_BLAHBLAH
  510.  
  511.     if (hiniMMPM)
  512.     {
  513.         // get applications list for sounds list in MMPM.INI
  514.         PSZ pszKeysList = NULL;
  515.         if (!(arc = prfhQueryKeysForApp(hiniMMPM,
  516.                                         MMINIKEY_SYSSOUNDS, // "MMPM2_AlarmSounds"
  517.                                         &pszKeysList)))
  518.         {
  519.             PSZ     pKey2 = pszKeysList;
  520.  
  521.             CHAR    szFile[CCHMAXPATH+50];
  522.             ULONG   ulVolume,
  523.                     ulKeyLen;
  524.  
  525.             while (*pKey2 != 0)
  526.             {
  527.                 // now copy this key to the new sound scheme;
  528.                 // however, we can't just copy the whole key,
  529.                 // but need to extract the file name and
  530.                 // volume first.
  531.                 // Warp 4 normally _only_ stores the file name
  532.                 // in the sound schemes. Since we want the
  533.                 // volume also, we add a null char after the
  534.                 // file name and append the volume...
  535.  
  536.                 PSZ pSoundData;
  537.                 if (pSoundData = prfhQueryProfileData(hiniMMPM,
  538.                                                       MMINIKEY_SYSSOUNDS, // "MMPM2_AlarmSounds"
  539.                                                       pKey2,
  540.                                                       NULL))
  541.                 {
  542.                     sndParseSoundData(pSoundData,
  543.                                       NULL,     // we don't need the description
  544.                                       szFile,
  545.                                       &ulVolume);
  546.                     ulKeyLen = strlen(szFile)+1;    // go beyond null byte
  547.                     ulKeyLen += sprintf(szFile+ulKeyLen,
  548.                                 "%lu",
  549.                                 ulVolume) + 1;
  550.                     // and write to OS2SYS.INI
  551.                     PrfWriteProfileData(HINI_SYSTEM,
  552.                                         szNewAppName,
  553.                                         pKey2,
  554.                                         szFile,
  555.                                         ulKeyLen);
  556.  
  557.                     free(pSoundData);
  558.                 } // end if (pSoundData)
  559.  
  560.                 pKey2 += strlen(pKey2)+1;
  561.             } // end while (*pKey2 != 0)
  562.  
  563.             free (pszKeysList);
  564.  
  565.             // finally, store new scheme in schemes list
  566.             PrfWriteProfileString(HINI_SYSTEM,
  567.                                   MMINIKEY_SOUNDSCHEMES,  // "PM_SOUND_SCHEMES_LIST"
  568.                                   (PSZ)pszNewScheme,      // key is scheme name
  569.                                   szNewAppName);    // data is new OS2SYS.INI application
  570.         }
  571.         else
  572.             arc = ERROR_NO_DATA;
  573.     }
  574.     else
  575.         arc = ERROR_INVALID_HANDLE;
  576.  
  577.     return arc;
  578. }
  579.  
  580. /*
  581.  *@@ sndLoadSoundScheme:
  582.  *      this loads the data in pszScheme (OS2SYS.INI)
  583.  *      into MMPM.INI. Existing sound data
  584.  *      in that profile will be overwritten.
  585.  *
  586.  *      Note: Only those sounds in MMPM.INI will be
  587.  *      overwritten for which a corresponding entry
  588.  *      in the sound scheme exists. If it doesn't,
  589.  *      the data in MMPM.INI for _that_ sound only
  590.  *      will _not_ be changed. In other words, existing
  591.  *      sound data will be merged with the scheme data.
  592.  *
  593.  *      If you don't like this, delete the whole
  594.  *      "MMPM2_AlarmSounds" application in MMPM.INI
  595.  *      before calling this function.
  596.  *
  597.  *      Returns:
  598.  *      --  NO_ERROR
  599.  *      --  ERROR_INVALID_HANDLE: hiniMMPM invalid
  600.  *      --  ERROR_NO_DATA: scheme not found.
  601.  *      --  ERROR_BAD_FORMAT: error in MMPM.INI data.
  602.  *
  603.  *@@added V0.9.0 [umoeller]
  604.  *@@changed V0.9.1 (99-12-20) [umoeller]: fixed memory leak
  605.  *@@changed V0.9.6 (2000-10-16) [umoeller]: added MMPM/2 notify
  606.  */
  607.  
  608. APIRET sndLoadSoundScheme(HINI hiniMMPM,      // in: HINI of ?:\MMOS2\MMPM.INI (PrfOpenProfile)
  609.                           PCSZ pszScheme)     // in: scheme name
  610. {
  611.     APIRET arc = NO_ERROR;
  612.  
  613.     #ifdef DEBUG_SOUNDS
  614.         _Pmpf(("Entering sndLoadSoundScheme"));
  615.     #endif
  616.  
  617.     if (hiniMMPM)
  618.     {
  619.         // check in OS2SYS.INI's scheme list whether that
  620.         // scheme exists already
  621.         PSZ pszSchemeAppName = prfhQueryProfileData(HINI_SYSTEM,
  622.                                     MMINIKEY_SOUNDSCHEMES,  // "PM_SOUND_SCHEMES_LIST"
  623.                                     pszScheme,
  624.                                     NULL);
  625.         #ifdef DEBUG_SOUNDS
  626.             _Pmpf(("    pszSchemeAppName: %s", pszSchemeAppName));
  627.         #endif
  628.  
  629.         if (pszSchemeAppName)
  630.         {
  631.             // now copy keys from OS2SYS.INI to MMPM.INI;
  632.             // since OS2SYS.INI _only_ has the file name
  633.             // (and _maybe_ the individual volume, if it
  634.             // was us who created the sound scheme --
  635.             // see sndCreateSoundScheme above), we need
  636.             // to go thru the MMPM.INI (!) sounds lists
  637.             // and merge the data in there with the
  638.             // corresponding sound data for the current
  639.             // scheme...
  640.  
  641.             // get applications list for sounds list in MMPM.INI
  642.             PSZ pszMMPMKeysList = NULL;
  643.             if (!(arc = prfhQueryKeysForApp(hiniMMPM,
  644.                                             MMINIKEY_SYSSOUNDS,// "MMPM2_AlarmSounds"
  645.                                             &pszMMPMKeysList)))
  646.             {
  647.                 PSZ     pMMPMKey2 = pszMMPMKeysList,
  648.                         pMMPMSoundData,
  649.                         pSchemeSoundData;
  650.  
  651.                 CHAR    szDescription[300];         // from MMPM.INI
  652.                 CHAR    szFile[CCHMAXPATH+50];      // from OS2SYS.INI
  653.                 ULONG   ulVolume;                   // from MMPM.INI _or_ OS2SYS.INI
  654.                 CHAR    szData[1000];
  655.  
  656.                 // go thru keys (numbers)
  657.                 while (*pMMPMKey2 != 0)
  658.                 {
  659.                     ULONG   cbSchemeSoundData = 0,
  660.                             cbSchemeSoundFile = 0;
  661.  
  662.                     pMMPMSoundData = prfhQueryProfileData(hiniMMPM,
  663.                                                           MMINIKEY_SYSSOUNDS, // "MMPM2_AlarmSounds"
  664.                                                           pMMPMKey2,
  665.                                                           NULL);
  666.                     pSchemeSoundData = prfhQueryProfileData(HINI_SYSTEM,
  667.                                                             pszSchemeAppName,
  668.                                                             pMMPMKey2,
  669.                                                             &cbSchemeSoundData);
  670.  
  671.                     if ((pMMPMSoundData) && (pSchemeSoundData))
  672.                     {
  673.                         sndParseSoundData(pMMPMSoundData,
  674.                                           szDescription,
  675.                                           NULL,                // we don't need the file
  676.                                           &ulVolume);
  677.                         // now overwrite this data with scheme data
  678.                         strcpy(szFile,
  679.                                pSchemeSoundData);       // up to first null byte
  680.                         cbSchemeSoundFile = strlen(pSchemeSoundData)+1;
  681.                         if (cbSchemeSoundData > cbSchemeSoundFile)
  682.                             // this means we have an additional volume string
  683.                             // after the null byte (sndCreateSoundScheme);
  684.                             // copy it
  685.                             sscanf(pSchemeSoundData + cbSchemeSoundFile,
  686.                                    "%lu",
  687.                                    &ulVolume);
  688.  
  689.                         // and write data to MMPM.INI
  690.                         // format: soundfile#description#volume
  691.                         sprintf(szData, "%s#%s#%lu", szFile, szDescription, ulVolume);
  692.                         if (PrfWriteProfileString(hiniMMPM,
  693.                                                   MMINIKEY_SYSSOUNDS, // "MMPM2_AlarmSounds"
  694.                                                   pMMPMKey2,    // key (decimal number)
  695.                                                   szData))
  696.                         {
  697.                             // success:
  698.                             USHORT usIndex = atoi(pMMPMKey2);
  699.                             if (usIndex < 100)
  700.                                 // this was one of the default OS/2 sounds:
  701.                                 // notify MMPM/2 of the change... see sndWriteSoundData
  702.                                 // V0.9.6 (2000-10-16) [umoeller]
  703.                                 WinAlarm(HWND_DESKTOP, usIndex+1000);
  704.                         }
  705.                     }
  706.  
  707.                     if (pMMPMSoundData)
  708.                         free(pMMPMSoundData);
  709.                     if (pSchemeSoundData)
  710.                         free(pSchemeSoundData);
  711.  
  712.                     pMMPMKey2 += strlen(pMMPMKey2)+1;
  713.                 } // end while (*pMMPMKey2 != 0)
  714.  
  715.                 free (pszMMPMKeysList);
  716.             }
  717.             else
  718.                 arc = ERROR_BAD_FORMAT;
  719.  
  720.             free(pszSchemeAppName);
  721.         } // end if (pszSchemeAppName)
  722.         else
  723.             arc = ERROR_NO_DATA;
  724.     }
  725.     else
  726.         arc = ERROR_INVALID_HANDLE;
  727.  
  728.     #ifdef DEBUG_SOUNDS
  729.         _Pmpf(("End of sndLoadSoundScheme, arc: %d", arc));
  730.     #endif
  731.     return arc;
  732. }
  733.  
  734. /*
  735.  *@@ sndDestroySoundScheme:
  736.  *      destroys pszScheme in OS2SYS.INI;
  737.  *      returns TRUE is pszScheme was found
  738.  *      and deleted.
  739.  *
  740.  *      See xsound.c for explanations.
  741.  *
  742.  *      Returns:
  743.  *      --  NO_ERROR
  744.  *      --  ERROR_NO_DATA: scheme not found.
  745.  *
  746.  *@@added V0.9.0 [umoeller]
  747.  */
  748.  
  749. APIRET sndDestroySoundScheme(PCSZ pszScheme)
  750. {
  751.     APIRET arc = NO_ERROR;
  752.  
  753.     // check in OS2SYS.INI's scheme list whether that
  754.     // scheme exists
  755.     PSZ pszExisting;
  756.     if (pszExisting = prfhQueryProfileData(HINI_SYSTEM,
  757.                                            MMINIKEY_SOUNDSCHEMES,  // "PM_SOUND_SCHEMES_LIST"
  758.                                            pszScheme,
  759.                                            NULL))
  760.     {
  761.         // delete whole existing PM_SOUNDS_BLAHBLAH application
  762.         PrfWriteProfileString(HINI_SYSTEM,
  763.                               pszExisting,      // application
  764.                               NULL,
  765.                               NULL);
  766.         // and delete entry in sound schemes list
  767.         PrfWriteProfileString(HINI_SYSTEM,
  768.                               MMINIKEY_SOUNDSCHEMES,  // "PM_SOUND_SCHEMES_LIST"
  769.                               (PSZ)pszScheme,
  770.                               NULL);
  771.         free(pszExisting);
  772.     }
  773.     else
  774.         arc = ERROR_NO_DATA;
  775.  
  776.     return arc;
  777. }
  778.  
  779.  
  780.