ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

mixer.c
Go to the documentation of this file.
00001 /*
00002  * ReactOS Sound Volume Control
00003  * Copyright (C) 2004-2005 Thomas Weidenmueller
00004  *
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Lesser General Public
00007  * License as published by the Free Software Foundation; either
00008  * version 2.1 of the License, or (at your option) any later version.
00009  *
00010  * This library is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Lesser General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Lesser General Public
00016  * License along with this library; if not, write to the Free Software
00017  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00018  */
00019 /* $Id: mixer.c 51274 2011-04-07 21:31:21Z janderwald $
00020  *
00021  * COPYRIGHT:   See COPYING in the top level directory
00022  * PROJECT:     ReactOS Sound Volume Control
00023  * FILE:        subsys/system/sndvol32/mixer.c
00024  * PROGRAMMERS: Thomas Weidenmueller <w3seek@reactos.com>
00025  */
00026 #include "sndvol32.h"
00027 
00028 #define NO_MIXER_SELECTED ((UINT)(~0))
00029 
00030 static VOID
00031 ClearMixerCache(PSND_MIXER Mixer)
00032 {
00033     PSND_MIXER_DESTINATION Line, NextLine;
00034     PSND_MIXER_CONNECTION Con, NextCon;
00035 
00036     for (Line = Mixer->Lines; Line != NULL; Line = NextLine)
00037     {
00038         if (Line->Controls != NULL)
00039         {
00040             HeapFree(GetProcessHeap(),
00041                      0,
00042                      Line->Controls);
00043         }
00044 
00045         for (Con = Line->Connections; Con != NULL; Con = NextCon)
00046         {
00047             if (Con->Controls != NULL)
00048             {
00049                 HeapFree(GetProcessHeap(),
00050                          0,
00051                          Con->Controls);
00052             }
00053 
00054             NextCon = Con->Next;
00055             HeapFree(GetProcessHeap(),
00056                      0,
00057                      Con);
00058         }
00059 
00060         NextLine = Line->Next;
00061         HeapFree(GetProcessHeap(),
00062                  0,
00063                  Line);
00064     }
00065     Mixer->Lines = NULL;
00066 }
00067 
00068 PSND_MIXER
00069 SndMixerCreate(HWND hWndNotification)
00070 {
00071     PSND_MIXER Mixer = (PSND_MIXER) HeapAlloc(GetProcessHeap(),
00072                                  HEAP_ZERO_MEMORY,
00073                                  sizeof(SND_MIXER));
00074     if (Mixer != NULL)
00075     {
00076         Mixer->hWndNotification = hWndNotification;
00077         Mixer->MixersCount = mixerGetNumDevs();
00078         Mixer->MixerId = NO_MIXER_SELECTED;
00079 
00080         if (Mixer->MixersCount > 0)
00081         {
00082             /* select the first mixer by default */
00083             SndMixerSelect(Mixer, 0);
00084         }
00085     }
00086 
00087     return Mixer;
00088 }
00089 
00090 VOID
00091 SndMixerDestroy(PSND_MIXER Mixer)
00092 {
00093     SndMixerClose(Mixer);
00094     HeapFree(GetProcessHeap(),
00095              0,
00096              Mixer);
00097 }
00098 
00099 VOID
00100 SndMixerClose(PSND_MIXER Mixer)
00101 {
00102     if (Mixer->hmx != NULL)
00103     {
00104       mixerClose(Mixer->hmx);
00105       Mixer->hmx = NULL;
00106       Mixer->MixerId = NO_MIXER_SELECTED;
00107     }
00108 }
00109 
00110 BOOL
00111 SndMixerQueryControls(PSND_MIXER Mixer,
00112                       PUINT DisplayControls,
00113                       LPMIXERLINE LineInfo,
00114                       LPMIXERCONTROL *Controls)
00115 {
00116     if (LineInfo->cControls > 0)
00117     {
00118         *Controls = (MIXERCONTROL*) HeapAlloc(GetProcessHeap(),
00119                               HEAP_ZERO_MEMORY,
00120                               LineInfo->cControls * sizeof(MIXERCONTROL));
00121         if (*Controls != NULL)
00122         {
00123             MIXERLINECONTROLS LineControls;
00124             MMRESULT Result;
00125             UINT j;
00126 
00127             LineControls.cbStruct = sizeof(LineControls);
00128             LineControls.dwLineID = LineInfo->dwLineID;
00129             LineControls.cControls = LineInfo->cControls;
00130             LineControls.cbmxctrl = sizeof(MIXERCONTROL);
00131             LineControls.pamxctrl = (MIXERCONTROL*)(*Controls);
00132 
00133             Result = mixerGetLineControls((HMIXEROBJ)Mixer->hmx,
00134                                           &LineControls,
00135                                           MIXER_GETLINECONTROLSF_ALL);
00136             if (Result == MMSYSERR_NOERROR)
00137             {
00138                 for (j = 0; j < LineControls.cControls; j++)
00139                 {
00140                     if (SndMixerIsDisplayControl(Mixer,
00141                                                  &(*Controls)[j]))
00142                     {
00143                         (*DisplayControls)++;
00144                     }
00145 
00146                     DPRINT("Line control: %ws (0x%x, 0x%x)\n", (*Controls)[j].szName, (*Controls)[j].fdwControl, (*Controls)[j].dwControlType);
00147                 }
00148 
00149                 return TRUE;
00150             }
00151             else
00152             {
00153                 HeapFree(GetProcessHeap(),
00154                          0,
00155                          *Controls);
00156                 *Controls = NULL;
00157                 DPRINT("Failed to get line (ID: 0x%x) controls: %d\n", LineInfo->dwLineID, Result);
00158             }
00159         }
00160         else
00161         {
00162             DPRINT("Failed to allocate memory for %d line (ID: 0x%x) controls!\n", LineInfo->dwLineID, LineInfo->cControls);
00163         }
00164 
00165         return FALSE;
00166     }
00167     else
00168     {
00169         return TRUE;
00170     }
00171 }
00172 
00173 static BOOL
00174 SndMixerQueryConnections(PSND_MIXER Mixer,
00175                          PSND_MIXER_DESTINATION Line)
00176 {
00177     UINT i, DispControls;
00178     MIXERLINE LineInfo;
00179     MMRESULT Result;
00180     BOOL Ret = TRUE;
00181 
00182     LineInfo.cbStruct = sizeof(LineInfo);
00183     for (i = Line->Info.cConnections; i > 0; i--)
00184     {
00185         LineInfo.dwDestination = Line->Info.dwDestination;
00186         LineInfo.dwSource = i - 1;
00187         Result = mixerGetLineInfo((HMIXEROBJ)Mixer->hmx,
00188                                   &LineInfo,
00189                                   MIXER_GETLINEINFOF_SOURCE);
00190         if (Result == MMSYSERR_NOERROR)
00191         {
00192             LPMIXERCONTROL Controls = NULL;
00193             PSND_MIXER_CONNECTION Con;
00194 
00195             DPRINT("++ Source: %ws\n", LineInfo.szName);
00196 
00197             DispControls = 0;
00198 
00199             if (!SndMixerQueryControls(Mixer,
00200                                        &DispControls,
00201                                        &LineInfo,
00202                                        &Controls))
00203             {
00204                 DPRINT("Failed to query connection controls\n");
00205                 Ret = FALSE;
00206                 break;
00207             }
00208 
00209             Con = (SND_MIXER_CONNECTION*) HeapAlloc(GetProcessHeap(),
00210                             HEAP_ZERO_MEMORY,
00211                             sizeof(SND_MIXER_CONNECTION));
00212             if (Con != NULL)
00213             {
00214                 Con->Info = LineInfo;
00215                 Con->Controls = Controls;
00216                 Con->DisplayControls = DispControls;
00217                 Con->Next = Line->Connections;
00218                 Line->Connections = Con;
00219             }
00220             else
00221             {
00222                 HeapFree(GetProcessHeap(),
00223                          0,
00224                          Controls);
00225             }
00226         }
00227         else
00228         {
00229             DPRINT("Failed to get connection information: %d\n", Result);
00230             Ret = FALSE;
00231             break;
00232         }
00233     }
00234 
00235     return Ret;
00236 }
00237 
00238 static BOOL
00239 SndMixerQueryDestinations(PSND_MIXER Mixer)
00240 {
00241     UINT i;
00242     BOOL Ret = TRUE;
00243 
00244     for (i = Mixer->Caps.cDestinations; i > 0; i--)
00245     {
00246         PSND_MIXER_DESTINATION Line;
00247 
00248         Line = (SND_MIXER_DESTINATION*) HeapAlloc(GetProcessHeap(),
00249                          HEAP_ZERO_MEMORY,
00250                          sizeof(SND_MIXER_DESTINATION));
00251         if (Line != NULL)
00252         {
00253             Line->Info.cbStruct = sizeof(Line->Info);
00254             Line->Info.dwDestination = i - 1;
00255             if (mixerGetLineInfo((HMIXEROBJ)Mixer->hmx,
00256                                  &Line->Info,
00257                                  MIXER_GETLINEINFOF_DESTINATION) == MMSYSERR_NOERROR)
00258             {
00259                 DPRINT("+ Destination: %ws (0x%x, %d)\n", Line->Info.szName, Line->Info.dwLineID, Line->Info.dwComponentType);
00260 
00261                 if (!SndMixerQueryControls(Mixer,
00262                                            &Line->DisplayControls,
00263                                            &Line->Info,
00264                                            &Line->Controls))
00265                 {
00266                     DPRINT("Failed to query mixer controls!\n");
00267                     Ret = FALSE;
00268                     break;
00269                 }
00270 
00271                 if (!SndMixerQueryConnections(Mixer, Line))
00272                 {
00273                     DPRINT("Failed to query mixer connections!\n");
00274                     Ret = FALSE;
00275                     break;
00276                 }
00277 
00278                 Line->Next = Mixer->Lines;
00279                 Mixer->Lines = Line;
00280             }
00281             else
00282             {
00283                 DPRINT("Failed to get line information for id %d!\n", i);
00284                 HeapFree(GetProcessHeap(),
00285                          0,
00286                          Line);
00287                 Ret = FALSE;
00288                 break;
00289             }
00290         }
00291         else
00292         {
00293             DPRINT("Allocation of SND_MIXER_DEST structure for id %d failed!\n", i);
00294             Ret = FALSE;
00295             break;
00296         }
00297     }
00298 
00299     return Ret;
00300 }
00301 
00302 BOOL
00303 SndMixerSelect(PSND_MIXER Mixer,
00304                UINT MixerId)
00305 {
00306     if (MixerId >= Mixer->MixersCount)
00307     {
00308         return FALSE;
00309     }
00310 
00311     SndMixerClose(Mixer);
00312 
00313     if (mixerOpen(&Mixer->hmx,
00314                   MixerId,
00315                   (DWORD_PTR)Mixer->hWndNotification,
00316                   0,
00317                   CALLBACK_WINDOW | MIXER_OBJECTF_MIXER) == MMSYSERR_NOERROR ||
00318         mixerOpen(&Mixer->hmx,
00319                   MixerId,
00320                   (DWORD_PTR)Mixer->hWndNotification,
00321                   0,
00322                   CALLBACK_WINDOW) == MMSYSERR_NOERROR ||
00323         mixerOpen(&Mixer->hmx,
00324                   MixerId,
00325                   0,
00326                   0,
00327                   0) == MMSYSERR_NOERROR)
00328     {
00329         if (mixerGetDevCaps(MixerId,
00330                             &Mixer->Caps,
00331                             sizeof(Mixer->Caps)) == MMSYSERR_NOERROR)
00332         {
00333             BOOL Ret = FALSE;
00334 
00335             Mixer->MixerId = MixerId;
00336 
00337             ClearMixerCache(Mixer);
00338 
00339             Ret = SndMixerQueryDestinations(Mixer);
00340 
00341             if (!Ret)
00342             {
00343                 ClearMixerCache(Mixer);
00344             }
00345 
00346             return Ret;
00347         }
00348         else
00349         {
00350             mixerClose(Mixer->hmx);
00351         }
00352     }
00353 
00354     Mixer->hmx = NULL;
00355     Mixer->MixerId = NO_MIXER_SELECTED;
00356     return FALSE;
00357 }
00358 
00359 UINT
00360 SndMixerGetSelection(PSND_MIXER Mixer)
00361 {
00362     return Mixer->MixerId;
00363 }
00364 
00365 INT
00366 SndMixerGetProductName(PSND_MIXER Mixer,
00367                        LPTSTR lpBuffer,
00368                        UINT uSize)
00369 {
00370     if (Mixer->hmx)
00371     {
00372         UINT lnsz = (UINT) lstrlen(Mixer->Caps.szPname);
00373         if(lnsz + 1 > uSize)
00374         {
00375             return lnsz + 1;
00376         }
00377         else
00378         {
00379             memcpy(lpBuffer, Mixer->Caps.szPname, lnsz * sizeof(TCHAR));
00380             lpBuffer[lnsz] = _T('\0');
00381             return lnsz;
00382         }
00383     }
00384 
00385     return -1;
00386 }
00387 
00388 INT
00389 SndMixerGetLineName(PSND_MIXER Mixer,
00390                     DWORD LineID,
00391                     LPTSTR lpBuffer,
00392                     UINT uSize,
00393                     BOOL LongName)
00394 {
00395     if (Mixer->hmx)
00396     {
00397         UINT lnsz;
00398         PSND_MIXER_DESTINATION Line;
00399         LPMIXERLINE lpl = NULL;
00400 
00401         for (Line = Mixer->Lines; Line != NULL; Line = Line->Next)
00402         {
00403             if (Line->Info.dwLineID == LineID)
00404             {
00405                 lpl = &Line->Info;
00406                 break;
00407             }
00408         }
00409 
00410         if (lpl != NULL)
00411         {
00412             lnsz = (UINT) lstrlen(LongName ? lpl->szName : lpl->szShortName);
00413             if(lnsz + 1 > uSize)
00414             {
00415                 return lnsz + 1;
00416             }
00417             else
00418             {
00419                 memcpy(lpBuffer, LongName ? lpl->szName : lpl->szShortName, lnsz * sizeof(TCHAR));
00420                 lpBuffer[lnsz] = _T('\0');
00421                 return lnsz;
00422             }
00423         }
00424     }
00425 
00426     return -1;
00427 }
00428 
00429 BOOL
00430 SndMixerEnumProducts(PSND_MIXER Mixer,
00431                      PFNSNDMIXENUMPRODUCTS EnumProc,
00432                      PVOID Context)
00433 {
00434     MIXERCAPS Caps;
00435     HMIXER hMixer;
00436     UINT i;
00437     BOOL Ret = TRUE;
00438 
00439     for (i = 0; i < Mixer->MixersCount; i++)
00440     {
00441         if (mixerOpen(&hMixer,
00442                       i,
00443                       0,
00444                       0,
00445                       0) == MMSYSERR_NOERROR)
00446         {
00447             if (mixerGetDevCaps(i,
00448                                 &Caps,
00449                                 sizeof(Caps)) == MMSYSERR_NOERROR)
00450             {
00451                 if (!EnumProc(Mixer,
00452                               i,
00453                               Caps.szPname,
00454                               Context))
00455                 {
00456                     mixerClose(hMixer);
00457                     Ret = FALSE;
00458                     break;
00459                 }
00460             }
00461             else
00462             {
00463                 DPRINT("Failed to get device capabilities for mixer id %d!\n", i);
00464             }
00465             mixerClose(hMixer);
00466         }
00467     }
00468 
00469     return Ret;
00470 }
00471 
00472 INT
00473 SndMixerSetVolumeControlDetails(PSND_MIXER Mixer, DWORD dwControlID, DWORD cbDetails, LPVOID paDetails)
00474 {
00475     MIXERCONTROLDETAILS MixerDetails;
00476 
00477     if (Mixer->hmx)
00478     {
00479         MixerDetails.cbStruct = sizeof(MIXERCONTROLDETAILS);
00480         MixerDetails.dwControlID = dwControlID;
00481         MixerDetails.cChannels = 1; //FIXME
00482         MixerDetails.cMultipleItems = 0;
00483         MixerDetails.cbDetails = cbDetails;
00484         MixerDetails.paDetails = paDetails;
00485 
00486         if (mixerSetControlDetails((HMIXEROBJ)Mixer->hmx, &MixerDetails, MIXER_GETCONTROLDETAILSF_VALUE | MIXER_OBJECTF_HMIXER) == MMSYSERR_NOERROR)
00487         {
00488             return 1;
00489         }
00490     }
00491 
00492     return -1;
00493 }
00494 
00495 
00496 INT
00497 SndMixerGetVolumeControlDetails(PSND_MIXER Mixer, DWORD dwControlID, DWORD cbDetails, LPVOID paDetails)
00498 {
00499     MIXERCONTROLDETAILS MixerDetails;
00500 
00501     if (Mixer->hmx)
00502     {
00503         MixerDetails.cbStruct = sizeof(MIXERCONTROLDETAILS);
00504         MixerDetails.dwControlID = dwControlID;
00505         MixerDetails.cChannels = 1; //FIXME
00506         MixerDetails.cMultipleItems = 0;
00507         MixerDetails.cbDetails = cbDetails;
00508         MixerDetails.paDetails = paDetails;
00509 
00510         if (mixerGetControlDetails((HMIXEROBJ)Mixer->hmx, &MixerDetails, MIXER_GETCONTROLDETAILSF_VALUE | MIXER_OBJECTF_HMIXER) == MMSYSERR_NOERROR)
00511         {
00512             return 1;
00513         }
00514     }
00515     return -1;
00516 }
00517 
00518 INT
00519 SndMixerGetDestinationCount(PSND_MIXER Mixer)
00520 {
00521     return (Mixer->hmx ? (INT)Mixer->Caps.cDestinations : -1);
00522 }
00523 
00524 BOOL
00525 SndMixerEnumLines(PSND_MIXER Mixer,
00526                   PFNSNDMIXENUMLINES EnumProc,
00527                   PVOID Context)
00528 {
00529     if (Mixer->hmx)
00530     {
00531         PSND_MIXER_DESTINATION Line;
00532 
00533         for (Line = Mixer->Lines; Line != NULL; Line = Line->Next)
00534         {
00535             if (!EnumProc(Mixer,
00536                           &Line->Info,
00537                           Line->DisplayControls,
00538                           Context))
00539             {
00540                 return FALSE;
00541             }
00542         }
00543 
00544         return TRUE;
00545     }
00546 
00547     return FALSE;
00548 }
00549 
00550 BOOL
00551 SndMixerEnumConnections(PSND_MIXER Mixer,
00552                         DWORD LineID,
00553                         PFNSNDMIXENUMCONNECTIONS EnumProc,
00554                         PVOID Context)
00555 {
00556     if (Mixer->hmx)
00557     {
00558         PSND_MIXER_DESTINATION Line;
00559 
00560         for (Line = Mixer->Lines; Line != NULL; Line = Line->Next)
00561         {
00562             if (Line->Info.dwLineID == LineID)
00563             {
00564                 PSND_MIXER_CONNECTION Connection;
00565 
00566                 if (Line->DisplayControls != 0)
00567                 {
00568                     if (!EnumProc(Mixer,
00569                                   LineID,
00570                                   &Line->Info,
00571                                   Context))
00572                     {
00573                         return FALSE;
00574                     }
00575                 }
00576 
00577                 for (Connection = Line->Connections; Connection != NULL; Connection = Connection->Next)
00578                 {
00579                     if (!EnumProc(Mixer,
00580                                   LineID,
00581                                   &Connection->Info,
00582                                   Context))
00583                     {
00584                         return FALSE;
00585                     }
00586                 }
00587 
00588                 return TRUE;
00589             }
00590         }
00591     }
00592 
00593     return FALSE;
00594 }
00595 
00596 BOOL
00597 SndMixerIsDisplayControl(PSND_MIXER Mixer,
00598                          LPMIXERCONTROL Control)
00599 {
00600     if (Mixer->hmx && !(Control->fdwControl & MIXERCONTROL_CONTROLF_DISABLED))
00601     {
00602         switch (Control->dwControlType & MIXERCONTROL_CT_CLASS_MASK)
00603         {
00604             case MIXERCONTROL_CT_CLASS_FADER:
00605             case MIXERCONTROL_CT_CLASS_SWITCH:
00606                 return TRUE;
00607         }
00608     }
00609 
00610     return FALSE;
00611 }
00612 

Generated on Sun May 27 2012 04:17:44 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.