AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Projekte TAudioVolume Komponente incl. System Mixer
Thema durchsuchen
Ansicht
Themen-Optionen

TAudioVolume Komponente incl. System Mixer

Ein Thema von EWeiss · begonnen am 6. Mai 2018 · letzter Beitrag vom 24. Jul 2019
Antwort Antwort
Seite 1 von 2  1 2      
EWeiss
(Gast)

n/a Beiträge
 
#1

AW: TAudioVolume Komponente incl. System Mixer

  Alt 10. Mai 2018, 07:27
Jetzt kannst du das Postmessage weglassen und direkt reagieren.
OK nur mein bestreben ist das gerade keine unnötigen externen Funktionen ausgeführt werden müssen.
Die Komponente soll so einfach wie möglich gehalten werden.

zu dem basiert das komplette Control auf diesen Event.
Delphi-Quellcode:
    if not(csDesigning in ComponentState) then
      FEventHandle := AllocateHWnd(ProcessMsg);
Delphi-Quellcode:
procedure TAudioVolume.ProcessMsg(var Msg: TMessage);
var
  PVolMuteRec: PVolMute;
  Volume: single;
  Muted: boolean;
  Device: IMMDevice;
  DeviceId: WideString;
  DeviceInfo: TDeviceInfo;
  HR: HResult;
  NewState: DWORD;
  MyRegistry: TRegistry;
begin
  case Msg.Msg of

    WM_EndpointVolume:
      begin
        PVolMuteRec := PVolMute(Msg.WPARAM);
        if Assigned(tbMasterVolume) then
        begin
          tbMasterVolume.Position := round((1.0 - PVolMuteRec^.Volume) * tbMasterVolume.Max);
          ckMasterMute.Checked := PVolMuteRec^.Muted;
        end;
        if Assigned(tbMasterBalance) then
          AdjustMasterBalancePos;

        if Assigned(FOnMasterVolumeEvent) then
          FOnMasterVolumeEvent(MyVolSet, PVolMuteRec^.Volume, PVolMuteRec^.Muted);
      end;

    WM_VolumeEvent:
      begin
        PVolMuteRec := PVolMute(Msg.WPARAM);

        if MySessionVolSet or Assigned(FOnSessionVolumeEvent) then
        begin
          if Assigned(tbSessionVolume) or Assigned(FOnSessionVolumeEvent) then
          begin
            tbSessionVolume.Position := round((1.0 - PVolMuteRec^.Volume) * tbSessionVolume.Max);
            ckSessionMute.Checked := PVolMuteRec^.Muted;
          end;

          if (MySessionVolSet and (abs(PVolMuteRec^.Volume - MyVolVal) < 0.0001)) then
            MySessionVolSet := false
          else if (MyMuteSet and (PVolMuteRec^.Muted = MyMuteVal)) then
            MyMuteSet := false;

          if Assigned(tbSessionBalance) then
            AdjustSessionBalancePos;
        end;
      end;

    WM_SessionStateEvent:
      begin
        if Assigned(FOnSessionStateEvent) then
          FOnSessionStateEvent(self, Msg.WPARAM);
      end;

    WM_DeviceStateChange, WM_DeviceAdded, WM_DeviceRemoved:
      begin
        DeviceId := WideString(PWideChar(Msg.WPARAM));
        NewState := Msg.LPARAM;
        // Just refresh device list to simplify the logic.
        RefreshDeviceList(DeviceEnumerator);
        // SetupDefaultAudioEndpoint(DeviceEnumerator);
        if Assigned(FOnDeviceStateChange) then
        begin
          if Msg.Msg = WM_DeviceStateChange then
            FOnDeviceStateChange(DeviceId, NewState)
          else if Msg.Msg = WM_DeviceAdded then
            FOnDeviceStateChange(DeviceId, DEVICE_STATE_ADDED)
          else if Msg.Msg = WM_DeviceRemoved then
            FOnDeviceStateChange(DeviceId, DEVICE_STATE_REMOVED);
        end;
      end;

    WM_SessionDisconnected:
      begin
        FAudioSessionList.SessionDisconnected := cAudioSessionDisconnected
          [TAudioSessionDisconnected(Msg.WPARAM)];

        if Assigned(FOnSessionDisconnected) then
          FOnSessionDisconnected(self, Msg.WPARAM);
      end;

    WM_SessionCreate:
      begin
        if Assigned(FOnSessionCreated) then
          FOnSessionCreated(IAudioSessionControl(@Msg.WPARAM));
      end;

    WM_DefaultDeviceChange:
      begin
        HR := DeviceEnumerator.GetDefaultAudioEndpoint(eRender, eMultimedia, Device);
        if HR <> S_OK then
          raise Exception.Create('Error : Unable to get DefaultAudioEndpoint Device');
        DeviceInfo := GetDeviceInfo(Device);
        if DeviceInfo.DeviceId <> FDefaultDevice.DeviceId then
        begin
          FDefaultDevice := DeviceInfo;
          if Assigned(FOnDefaultDeviceChange) then
            FOnDefaultDeviceChange(DeviceInfo);
        end;
      end;

    MM_MIXM_LINE_CHANGE:
      begin
        // wParam = (WPARAM) hMixer lParam = (LPARAM) dwLineID

      end;

    MM_MIXM_CONTROL_CHANGE:
      begin
        // wParam = (WPARAM) hMixer lParam = (LPARAM) dwControlID
        if (DWORD(Msg.LPARAM) <> MasterMute.dwControlID) and
          (DWORD(Msg.LPARAM) <> MasterVol.dwControlID) then
          exit;

        Muted := IsMasterMuted;
        Volume := GetMasterVolume;
        if (DWORD(Msg.LPARAM) = MasterMute.dwControlID) then
        begin
          if (MyMuteSet and (Muted = MyMuteVal)) then
            MyMuteSet := false;
        end
        else
        // for (Msg.LParam = MasterVol.dwControlID)
          if (MyVolSet and (abs(Volume - MyVolVal) < 0.0001)) then
          MyVolSet := false;

        if Assigned(tbMasterVolume) then
        begin
          tbMasterVolume.Position := round((1.0 - Volume) * tbMasterVolume.Max);
          ckMasterMute.Checked := Muted;
        end;

        if Assigned(tbMasterBalance) then
          AdjustMasterBalancePos;
      end;
  else
    if Msg.Msg = WINMM_DEVICECHANGE then
    begin
      MyRegistry := TRegistry.Create;
      MyRegistry.RootKey := HKEY_CURRENT_USER;
      if MyRegistry.KeyExists('Software\Microsoft\Multimedia\Sound Mapper') then
        if MyRegistry.OpenKey('Software\Microsoft\Multimedia\Sound Mapper', true) then
          FDefaultDevice.DeviceName := MyRegistry.ReadString('Playback');
      MyRegistry.free;
    end
    else
      Msg.Result := DefWindowProc(FEventHandle, Msg.Msg, Msg.WPARAM, Msg.LPARAM);
  end;
end;
Kannst du dir vorstellen was ich dann alles ändern müsste?
Das ist nicht mal eben, mache die Events Public in TAudioVolume da hängt noch viel mehr von ab.

gruss

Geändert von EWeiss (10. Mai 2018 um 07:35 Uhr)
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.079 Beiträge
 
Delphi 10.4 Sydney
 
#2

AW: TAudioVolume Komponente incl. System Mixer

  Alt 10. Mai 2018, 19:24
Der Aufwand wäre nur, die ganze processmsg-Methode wegzumachen und die einzelnen Teile rauszukopieren und anstatt den jeweiligen PostMessage-Aufrufen hinzukopieren. Dazu noch prüfen if Mainthread <> GetCurrentThreadId then Sync.
Alles in allen keine 10 min Arbeit und auch nur wenn man sich sehr viel Zeit lässt beim Drücken von Strg+C und Strg+V.
Am Ende haste viel weniger Quelltext gesamt gesehen. Außerdem gehen dann die Sachen, wo du Referenzgezählte Sachen weiterreichst.
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#3

AW: TAudioVolume Komponente incl. System Mixer

  Alt 11. Mai 2018, 00:39
Zitat:
Alles in allen keine 10 min Arbeit und auch nur wenn man sich sehr viel Zeit lässt beim Drücken von Strg+C und Strg+V.
Ich verwende die Maus lieber als Tasten.

Wenn es bei dir < wie 10 Min dauert sollte es doch für dich kein Problem sein das eben mal umzubauen.
Wäre zumindest produktiver als sich hier noch > 10 Min darüber zu unterhalten welche nun die bessere Lösung ist PostMessage oder deine Methode.
Letztendlich haben alle was davon und es wäre ein leichtes für dich.

Habe jetzt keinen Bock das alles wieder umzuschreiben zumal mein Aufwand dafür > wie 10 Min dauert geschätzt ne halbe Stunde.
In der zeit wo ich hier Editiert habe hätte es schon fertig sein können sei's drum.

gruss

Geändert von EWeiss (11. Mai 2018 um 04:27 Uhr)
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#4

AW: TAudioVolume Komponente incl. System Mixer

  Alt 12. Mai 2018, 00:15
Ich erstelle eine neue Anwendung ohne den VCL Kram das nervt nur.
Ist fertig wenn fertig!

Werde die Bilder später wieder löschen.

gruss

Geändert von EWeiss (13. Mai 2018 um 15:49 Uhr)
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#5

AW: TAudioVolume Komponente incl. System Mixer

  Alt 13. Mai 2018, 13:25
Nur zur Info.
So wird das komplette Control erstellt.
Allerdings kann sich das während der Entwicklung noch leicht ändern.

Eine Kombination aus verschiedenen Bitmaps, Text und Fonts die zur Laufzeit registriert werden.
Die ID's werden inkrementiert abhängig vom Index.

ID_BVOLUME = Background-Volumen Picture. Der Rahmen der sich um die Controls legt!
ID := ID_BVOLUME + Index;

Durch das inkrementieren der ID's kann ich auf einfache weise mehrere Controls hintereinander erstellen.
Die Bedienung ist dann abhängig von der jeweiligen ID.
So kann man die Tollsten Fenster und Controls basteln das einzige Hindernis ist die eigene Kreativität.

Delphi-Quellcode:
procedure CreateVolumeCtrl(Index: Integer; UseFont: string; x1, y1, w, h: Integer; FontSize: Integer;
  Color: COLORREF; UseText: PWideChar);
var
  x, y: Integer;
  nX, nY: Integer;
  hBmp, hThumb: HBitmap;
  bmW, bmH: cardinal;
  IbmW, IbmH: Integer;
  ID: Integer;
begin

  // Hintergrund
  hBmp := gSprCtrl.GI_CreateBitmapFromFile(PWideChar(SpriteResPath + 'LBottom.png'), bmW, bmH);
  if (hBmp <> 0) then
  begin
    ParentWidth := bmW;
    ParentHeight := bmH;

    ID := ID_BVOLUME + Index;
    gSprCtrl.GD_DrawBitmapToCtrl(HSprCtrl, x1, y1, hBmp, gSprCtrl.GD_ColorARGB(255, 0), ID, GS_VISIBLE);
    gSprCtrl.GD_SetObjectLinked(ID, ID);
    gSprCtrl.GD_SetObjectLocked(ID, true);

    // Vordergrund
    hBmp := gSprCtrl.GI_CreateBitmapFromFile(PWideChar(SpriteResPath + 'LTop.png'), bmW, bmH);
    if (hBmp <> 0) then
    begin
      ID := ID_TVOLUME + Index;
      gSprCtrl.GD_DrawBitmapToCtrl(HSprCtrl, x1, y1, hBmp, gSprCtrl.GD_ColorARGB(255, 0),
        ID, GS_VISIBLE);
      gSprCtrl.GD_SetObjectLinked(ID, (ID_BVOLUME + Index));
      gSprCtrl.GD_SetObjectLocked(ID, true);

      // LCD vertikaler Slider Value
      x := x1 + 30;
      y := y1 + 74;

      if not Assigned(TTFLcd) then
        GDIP_LoadPrivateFontCollection(UseFont, TTFLcd, LcdFontName);

      ID := ID_SLIDER_LED + Index;
      gSprCtrl.GD_DrawTextToCtrlEx(HSprCtrl, UseText, x, y + 1, w, h, Color, PWideChar(LcdFontName)
          , TTFLcd, FontSize, ID, GS_VISIBLE, 0, Ord(StringAlignmentFar));

      gSprCtrl.GD_SetObjectLinked(ID, (ID_BVOLUME + Index));
      gSprCtrl.GD_SetObjectLocked(ID, true);

      GDIP_GetTextBound(MainClass.DeviceName, FontName, 13, bw, bh, nil, GD_TextHorzUp);

      // DeviceName
      x := x1 + ((ParentWidth - bw) div 2);
      y := 208;
      // Keinen privaten Font verwenden weil text sich zur Laufzeit ändern kann.
      ID := ID_DEVICENAME + Index;
      gSprCtrl.GD_DrawTextToCtrl(HSprCtrl, PWideChar(MainClass.DeviceName), x, y, gSprCtrl.GD_ARGB
          (255, 255, 255, 255), PWideChar(FontName), nil, 13, ID, GS_VISIBLE, 1, Ord
          (StringAlignmentNear));

      gSprCtrl.GD_SetObjectLinked(ID, (ID_BVOLUME + Index));
      gSprCtrl.GD_SetObjectLocked(ID, true);

      // vertikaler slider
      nX := x1 + 36;
      nY := y1 + 112;

      hBmp := gSprCtrl.GI_CreateBitmapFromFile(PWideChar(SpriteResPath + 'slideV.png'), bmW, bmH);
      if (hBmp <> 0) then
      begin
        hThumb := gSprCtrl.GI_CreateBitmapFromFile
          (PWideChar(SpriteResPath + 'thumbV.png'), bmW, bmH);
        if (hThumb <> 0) then
        begin
          gSprCtrl.GI_GetBitmapSize(hBmp, IbmW, IbmH);
          x := nX;
          y := nY;

          ID := ID_SLIDER_VERT + Index;
          gSprCtrl.GD_DrawBitmapToCtrl(HSprCtrl, x, y, hBmp, OPAQUEIMAGE, ID, GS_VISIBLE);
          gSprCtrl.GD_SetObjectLinked(ID, (ID_BVOLUME + Index));
          gSprCtrl.GD_SetObjectLocked(ID, true);

          y := nY + (IbmH div 2);
          gSprCtrl.GI_GetBitmapSize(hThumb, IbmW, IbmH);
          x := nX;
          y := y - (IbmH div 2 - 1);

          ID := ID_THUMB_VERT + Index;
          gSprCtrl.GD_DrawBitmapToCtrl(HSprCtrl, x, y, hThumb, OPAQUEIMAGE, ID, GS_VISIBLE);
          gSprCtrl.GD_SetObjectLinked(ID, (ID_BVOLUME + Index));
          gSprCtrl.GD_SetObjectLocked(ID, true);

          // Mute
          hBmp := gSprCtrl.GI_CreateBitmapFromFile(PWideChar(SpriteResPath + 'vSwitch.png'), bmW,
            bmH);
          x := x1 + (ParentWidth - Integer(bmW) div 2) - 23;
          y := y1 + ParentHeight - Integer(bmH);

          ID := ID_SWITCH + Index;
          gSprCtrl.GI_GetBitmapSize(hBmp, IbmW, IbmH);
          gSprCtrl.GD_DrawBitmapToCtrl(HSprCtrl, x, y, hBmp, $FFFFFFFF, ID, GS_VISIBLE);

          gSprCtrl.GD_SetObjectLinked(ID, (ID_BVOLUME + Index));
          gSprCtrl.GD_SetObjectFrameCount(ID, 2);
          gSprCtrl.GD_SetObjectFrameToUse(ID, 1);
          gSprCtrl.GD_SetObjectLocked(ID, true);

          // Anchor
          gSprCtrl.GD_SetObjectAnchorMode((ID_SLIDER_LED + Index), ANCHOR_CENTER);
          gSprCtrl.GD_SetObjectAnchorMode((ID_SLIDER_VERT + Index), ANCHOR_CENTER);
          gSprCtrl.GD_SetObjectAnchorMode((ID_THUMB_VERT + Index), ANCHOR_CENTER);
          gSprCtrl.GD_SetObjectAnchorMode((ID_SWITCH + Index), ANCHOR_CENTER);
          gSprCtrl.GD_SetObjectAnchorMode((ID_DEVICENAME + Index), ANCHOR_CENTER);
        end;
      end;
    end;
  end;
end;
Keine sorge Bilder werden später wieder gelöscht möchte nur den fortschritt dokumentieren.
Wie man sehen kann gibt es noch Probleme mit den Texten die überlagern sich.


gruss

Geändert von EWeiss (13. Mai 2018 um 15:49 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von KodeZwerg
KodeZwerg

Registriert seit: 1. Feb 2018
3.691 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: TAudioVolume Komponente incl. System Mixer

  Alt 13. Mai 2018, 14:24
Und das Grafikgenie liefert wieder eine Mona-Lisa, man bist Du gut! Auch wenn ich pers. es nicht gebrauchen kann freue ich mich darauf

Interessens-Frage nebenbei, kann man das ganze auch per Code steuern, also ohne Grafik?
Gruß vom KodeZwerg
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#7

AW: TAudioVolume Komponente incl. System Mixer

  Alt 13. Mai 2018, 14:30
Und das Grafikgenie liefert wieder eine Mona-Lisa, man bist Du gut! Auch wenn ich pers. es nicht gebrauchen kann freue ich mich darauf

Interessens-Frage nebenbei, kann man das ganze auch per Code steuern, also ohne Grafik?
Gegenfrage welchen sinn macht das ohne Graphik ?
bzw.. welchen sinn hat eine VCL Form ohne Komponente ?

gruss
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.079 Beiträge
 
Delphi 10.4 Sydney
 
#8

AW: TAudioVolume Komponente incl. System Mixer

  Alt 14. Mai 2018, 08:11
Wenn es bei dir < wie 10 Min dauert sollte es doch für dich kein Problem sein das eben mal umzubauen.
Wäre zumindest produktiver als sich hier noch > 10 Min darüber zu unterhalten welche nun die bessere Lösung ist PostMessage oder deine Methode.
Letztendlich haben alle was davon und es wäre ein leichtes für dich.

Habe jetzt keinen Bock das alles wieder umzuschreiben zumal mein Aufwand dafür > wie 10 Min dauert geschätzt ne halbe Stunde.
In der zeit wo ich hier Editiert habe hätte es schon fertig sein können sei's drum.
Ist das noch aktuell, soll ich dir das mal zeigen was ich meine oder ist jetzt eh schon egal?
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#9

AW: TAudioVolume Komponente incl. System Mixer

  Alt 14. Mai 2018, 08:20
Wenn es bei dir < wie 10 Min dauert sollte es doch für dich kein Problem sein das eben mal umzubauen.
Wäre zumindest produktiver als sich hier noch > 10 Min darüber zu unterhalten welche nun die bessere Lösung ist PostMessage oder deine Methode.
Letztendlich haben alle was davon und es wäre ein leichtes für dich.

Habe jetzt keinen Bock das alles wieder umzuschreiben zumal mein Aufwand dafür > wie 10 Min dauert geschätzt ne halbe Stunde.
In der zeit wo ich hier Editiert habe hätte es schon fertig sein können sei's drum.
Ist das noch aktuell, soll ich dir das mal zeigen was ich meine oder ist jetzt eh schon egal?
PostMessage ist immer noch aktuell.
Wäre schön wenn du mir das zeigen würdest.

Auch wenn ich keine Controls mehr in TAudioVolume verwende sende ich die Messagen immer noch mit PostMessage.
Werde mein neues Projekt hochladen wenn vollständig.
Falls du die neue TAudioVolum.pas dafür brauchst sag bescheid.

gruss

Geändert von EWeiss (14. Mai 2018 um 08:26 Uhr)
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.079 Beiträge
 
Delphi 10.4 Sydney
 
#10

AW: TAudioVolume Komponente incl. System Mixer

  Alt 14. Mai 2018, 08:37
Also wenn überhaupt, zeige ich dir das anhand der Ableitung von TWinControl.
Bei den ewig langen und komplizierten NonVCL-Quelltexten kriege ich Pickel auf den Augen.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:35 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz