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
TiGü

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

AW: TAudioVolume Komponente incl. System Mixer

  Alt 9. Mai 2018, 09:24
Delphi-Quellcode:
function TAudioSessionNotification.OnSessionCreated(const NewSession: IAudioSessionControl): HResult;
begin
  PostMessage(MsgHandle, WM_SessionCreate, integer(@NewSession), 0);

  Result := S_OK;
end;
Wie sag ich das jetzt? Es ist etwas suboptimal!
Du möchtest ein Interface per PostMessage weiterversenden. Erster Fehler ist das Casten des Pointers auf Integer.
Außerdem wird dadurch der Referenzzählung durcheinander gebracht. Sobald OnSessionCreated durchlaufen wird, ist die Instanz nicht mehr sicher da.
Das müsste eigentlich für angemeldete FOnSessionCreated-Eventhandler knallen.

Zumindest tut es das bei mir, wenn man einen Eventhandler anmeldet und auf die NewSession-Instanz zugreifen will:
Delphi-Quellcode:
procedure TForm1.AudioVolume1SessionCreated(NewSession: IAudioSessionControl);
var
  pRetVal: uint;
begin
  NewSession.GetState(pRetVal);
end;
Dann knallt es in System.pas
Delphi-Quellcode:
procedure _IntfAddRef(const Dest: IInterface);
begin
  if Dest <> nil then Dest._AddRef;
end;
Die Überlegung mit den PostMessage, um asynchron zu arbeiten und reagieren zu können ist problemlos für ordinale Typen (Byte, Integer, Cardinal...) umsetzbar, aber mit Interface-Instanzen kommst du in Teufelsküche.

Hast du mal überlegt die IAudioSessionEvents, IMMNotificationClient, IAudioSessionNotification und IAudioEndpointVolumeCallback in TAudioVolume zu integrieren?
Das wäre einfacher als so Zwischenklassen, die nichts weiter tun, als die Informationen per PostMessage weiterzuversenden. Weniger Quelltext würde sich dadurch auch ergeben.
Wenn man aus einen anderen Thread-Context als den Mainthread befeuert wird, muss man natürlich synchronisieren.
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#2

AW: TAudioVolume Komponente incl. System Mixer

  Alt 9. Mai 2018, 17:17
function TAudioSessionNotification.OnSessionCreated(const NewSession: IAudioSessionControl): HResult;

Habe hier noch gar keine Fehler bezüglich des Pointers feststellen(debuggen) können weil das Event nie ausgelöst wird.
Zitat:
Die Überlegung mit den PostMessage, um asynchron zu arbeiten und reagieren zu können ist problemlos für ordinale Typen (Byte, Integer, Cardinal...) umsetzbar, aber mit Interface-Instanzen kommst du in Teufelsküche.
Werde dem Nachgehen sobald ich eine Lösung dafür gefunden habe das dieses Event auch ausgelöst wird.
Wie ich schon sagte trotz Registrierung, Initialisierung funktioniert es nicht.

Zitat:
Diese Zeilen bedürfen einen Überarbeitung:
Jo ein

Delphi-Quellcode:
    if not Assigned(MasterImg) then
    begin
      MasterImg := TImage.Create(FMGroupBox);
      MasterImg.AutoSize := true;
      MasterImg.Parent := FMGroupBox;

      FillChar(WinDir, sizeof(WinDir), 0);
      GetWindowsDirectory(WinDir, MAX_PATH);
      MasterImg.Picture.Icon := SetSysItemIcon(PWideChar(WinDir + '\System32\SndVol.exe'));
      if Assigned(MasterImg.Picture.Icon) then
      begin
        MasterImg.Left := (ClientWidth - Icon.Width) div 2;
        MasterImg.Top := 5;
        MasterImg.Show;
      end else
      FreeAndNil(MasterImg);
    end;
sollte reichen.

Zitat:
Das vorige wird aber nie freigegeben -> Speicherleck.
im Destroy.
Delphi-Quellcode:
if Assigned(MasterImg) then
  FreeAndNil(MasterImg);
Zitat:
Zumindest tut es das bei mir, wenn man einen Eventhandler anmeldet und auf die NewSession-Instanz zugreifen will:
procedure TForm1.AudioVolume1SessionCreated(NewSession: IAudioSessionControl);


Sorry das muss knallen.
1. SessionCreated wird nie aufgerufen daran kann es also nicht liegen.
2. Du erstellst ein Event für eine Session was eigentlich nichts mit den\der Session zu tun hat.
AudioVolume1 ist das HauptVolumen (Lautsprecher) und hat nix mit den Session zu tun. Aber du weist ihm ein SessionCreated zu

Deine Zuweisung ist korrekt ein Denkfehler meinerseits.

gruss

Geändert von EWeiss ( 9. Mai 2018 um 18:15 Uhr)
  Mit Zitat antworten Zitat
TiGü

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

AW: TAudioVolume Komponente incl. System Mixer

  Alt 9. Mai 2018, 18:05
Habe den Quelltext jetzt nicht vor mir, aber ich habe in dem Beispielformular den oben genannten Eventhändler definiert und jeder tempSessionDingsbums an OnSessionCreated rangetackert. Bei neuen Programm mit Audioausgabe, z.B. FooBar2000, wurde das Event mehrfach ausgelöst. Also der Teil wo das Postmessage machst.
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#4

AW: TAudioVolume Komponente incl. System Mixer

  Alt 9. Mai 2018, 18:12
Habe den Quelltext jetzt nicht vor mir, aber ich habe in dem Beispielformular den oben genannten Eventhändler definiert und jeder tempSessionDingsbums an OnSessionCreated rangetackert. Bei neuen Programm mit Audioausgabe, z.B. FooBar2000, wurde das Event mehrfach ausgelöst. Also der Teil wo das Postmessage machst.
OK dann habe ich einen Denkfehler.
Muss dann wohl über AudioVolume1 doch das Event initialisieren.
Bin da wohl selbst über den Session und MasterVolumen Kram gestolpert.

Trotzdem bekomme ich kein Event..
Kann es sein das dieses nur von Anwendungen ausgelöst wird die das Interface auch unterstützen?
Denn wenn ich einen meiner Player starte passiert da gar nichts. Der Mixer selbst erkennt ihn aber und addiert ihn als Session.

Delphi-Quellcode:
{ TSessionNotification }

function TAudioSessionNotification.OnSessionCreated(const NewSession: IAudioSessionControl): HResult;
begin
  PostMessage(MsgHandle, WM_SessionCreate, integer(@NewSession), 0);

  Result := S_OK;
end;
Hier passiert nix.

Danke..

Zitat:
Hast du mal überlegt die IAudioSessionEvents, IMMNotificationClient, IAudioSessionNotification und IAudioEndpointVolumeCallback in TAudioVolume zu integrieren?
Mir ist jetzt nicht ganz klar wie du das bewerkstelligen würdest.
Bin mit dem VCL Kram nicht gerade sehr bewandert.
Zitat:

Zitat:
Hm...die anderen Icons von den Anwendungen leaken auch...versuch mal, ob du das schöner hinkriegst.
Mache ich.. Danke

gruss

Geändert von EWeiss ( 9. Mai 2018 um 18:38 Uhr)
  Mit Zitat antworten Zitat
TiGü

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

AW: TAudioVolume Komponente incl. System Mixer

  Alt 9. Mai 2018, 18:56
Vom Smartphone schreiben ist schwierig, aber du kannst das machen:

TAudioVolume = class(TWinControl, IAudioSessionEvents, IMMNotificationClient, IAudioSessionNotification, IAudioEndpointVolumeCallback) Dann halt wie gehabt die notwendigen Methoden hinzufügen.
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#6

AW: TAudioVolume Komponente incl. System Mixer

  Alt 9. Mai 2018, 19:01
Vom Smartphone schreiben ist schwierig, aber du kannst das machen:

TAudioVolume = class(TWinControl, IAudioSessionEvents, IMMNotificationClient, IAudioSessionNotification, IAudioEndpointVolumeCallback) Dann halt wie gehabt die notwendigen Methoden hinzufügen.
OK werde mal versuchen es umzusetzen.
Danke.

EDIT:
Schwierig.
Habe ja schon 2 x TAudioVolume

Delphi-Quellcode:
  TAudioVolume = class; // <<<<<
  TSplitStrArray = array of string;

  // ByMyAction is used to check if this event is triggered by self action, i.e., my application's
  // execution of SetMasterMute, SetMasterVolume, SetSysSoundMute or SetSysSoundVolume.
  TOnMasterVolumeEvent = procedure(ByMyAction: boolean; Volume: single; Mute: boolean) of object;
  TOnSessionVolumeEvent = procedure(ByMyAction: boolean; Volume: single; Mute: boolean) of object;
  TOnSessionStateEvent = procedure(Sender: TAudioVolume; NewState: integer) of object;
  TOnSessionDisconnected = procedure(Sender: TAudioVolume; DisconnectReason: uint) of object;
  TOnDeviceStateChange = procedure(DeviceId: string; NewDeviceState: DWORD) of object;
  TOnDefaultDeviceChange = procedure(NewDefaultDevice: TDeviceInfo) of object;
  TOnSessionCreated = procedure(NewSession: IAudioSessionControl) of object;

  TAudioVolume = class(TWinControl)// <<<<<<
Das
TAudioVolume = class(TWinControl)
zu ändern nach
TAudioVolume = class(TWinControl, IAudioSessionEvents, IMMNotificationClient, IAudioSessionNotification, IAudioEndpointVolumeCallback)
verträgt sich gar nicht.

Ich muss das MasterVolume von TAudioVolume trennen weil beim erstellen einer neuen Instanz von TAudioVolume alle Eigenschaften von MasterVolume nil sind.
Deshalb kann ich auch die Icons nicht freigeben.
Oder aber eine andere Lösung muss her Hmmm...

Glaube das Konzept ist zur zeit noch sehr verworren.

gruss

Geändert von EWeiss ( 9. Mai 2018 um 19:50 Uhr)
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#7

AW: TAudioVolume Komponente incl. System Mixer

  Alt 10. Mai 2018, 04:53
@Tigü

Habe deinen Vorschlag umgesetzt aber sehe im Moment nicht wirklich irgendeinen Vorteil.
Es geht jetzt mal nur um die Events.

Beispiel:
Vorher!

Delphi-Quellcode:
TAudioEndpointEvents = class(TInterfacedObject, IAudioEndpointVolumeCallback)
  private
    MsgHandle: HWND;
    VolMute: TVolMute;
    EventContext: TGUID;
  public
    function OnNotify(pNotify: PAUDIO_VOLUME_NOTIFICATION_DATA): HResult; stdcall;
    procedure SetMsgHandle(WinHandle: HWND);
  end;

function TAudioEndpointEvents.OnNotify(pNotify: PAUDIO_VOLUME_NOTIFICATION_DATA): HResult; stdcall;
var
  VolumeData: AUDIO_VOLUME_NOTIFICATION_DATA;
begin
  VolumeData := pNotify^;
  VolMute.Volume := VolumeData.fMasterVolume;
  VolMute.Muted := VolumeData.bMuted;
  EventContext := VolumeData.guidEventContext;

  PostMessage(MsgHandle, WM_EndpointVolume, integer(@VolMute), integer(@EventContext));

  Result := S_OK;
end;
Nachher!
Delphi-Quellcode:
  TAudioVolume = class(TWinControl, IAudioSessionEvents, IMMNotificationClient,
    IAudioSessionNotification, IAudioEndpointVolumeCallback)
//...
  public
    function OnNotify(pNotify: PAUDIO_VOLUME_NOTIFICATION_DATA): HResult; stdcall;
Delphi-Quellcode:
function TAudioVolume.OnNotify(pNotify: PAUDIO_VOLUME_NOTIFICATION_DATA): HResult;
var
  VolumeData: AUDIO_VOLUME_NOTIFICATION_DATA;
begin
  VolumeData := pNotify^;
  VolMute.Volume := VolumeData.fMasterVolume;
  VolMute.Muted := VolumeData.bMuted;
  EventContext := VolumeData.guidEventContext;

  PostMessage(MsgHandle, WM_EndpointVolume, integer(@VolMute), integer(@EventContext));

  Result := S_OK;

end;
Wo ist jetzt der Vorteil von deiner <> meiner Auslegung?
Das erschließt sich mir nicht. Sorry

PS:
Hab Foobar 2000 mal installiert.
Und nein wie vorher schon gesagt es wird nie ein Event ausgelöst vom System.

Kein OnSessionCreated
Kein OnSessionDisconnected

gruss

Geändert von EWeiss (10. Mai 2018 um 05:32 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort


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 16:55 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