Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Interface 'IAudioEndpointVolume' läuft unter TurboDelphi aber nicht unter Delphi10.1? (https://www.delphipraxis.net/190972-interface-iaudioendpointvolume-laeuft-unter-turbodelphi-aber-nicht-unter-delphi10-1-a.html)

r29d43 24. Nov 2016 15:44

Interface 'IAudioEndpointVolume' läuft unter TurboDelphi aber nicht unter Delphi10.1?
 
Hallo,

es geht um ein kleines etwas älteres Turbo-Delphi Programm, das ich jetzt auch mal mit Delphi10.1 compliliert habe. Leider läuft es danach nämlich nicht mehr.

Nach dem ProgStart taucht jedesmal eine Zugriffsverletzung auf (eine Exception der Klasse $C0000005 mit der Meldung 'access violation at...). Und zwar immer dann, wenn ich versuche auf die erste private deklarierte Feld-Variable von TForm (nach den eigentlichen Interface-Variablen) zuzugreifen. Mache ich aus dieser Variable anschließend eine globale Variable, dann entsteht die gleiche Exception beim Zugriff auf die dann nächste oberste private deklarierte Variable. Mache ich diese dann auch noch zur globalen Variablen, dann entsteht die gleiche Exception beim Lesezugriff auf die Caption eines Buttons des Progs.

Im Debugger wird mir für diese Variablen jeweils ein "nicht verfügbarer Wert" angezeigt.

Kommentiere ich die eigentliche das endpointVolume-Objekt erzeugende Zeile aber aus, dann entsteht keine Exception mehr (allerdings hat das Prog dann natürlich auch seine eigentliche Funktion verloren). Von daher sollte der eigentliche Prob-Verursacher also schon dieses Interface sein.

Hier event. nochmal ein kleiner Code-Auszug bzgl. dieses Interfaces:

Code:
  TMuterForm = class(TForm)
    . . .
  private
    { Private-Deklarationen }
    deviceEnumerator: IMMDeviceEnumerator; // Interface-Pointer, Interface ist in MMDevApi definiert; ..wird im Prog als erster ermittelt
    defaultDevice: IMMDevice;              // Interface-Pointer, Interface ist in MMDevApi definiert; ..wird im Prog als zweites ermittelt
    endpointVolume: IAudioEndpointVolume;  // Interface-Pointer, Interface ist in MMDevApi definiert; ..wird im Prog dann als drittes ermittelt

    MuteIsOnStream, MuteIsOffStream : TMemoryStream;   <---------- beim Zugriff auf diese Vars entstehen die ersten Exceptions
    MuteStatus : boolean;                              <---------- danach beim Zugriff auf diese hier, anschließend (wenn ich die jeweils zu globalen Var mache) beim Zugriff auf Button1.Caption

    HookHandle : Cardinal;
    StartXY : TPoint;

    Seconds : integer;
    EndTickCount : DWord;
    procedure manageButtonCaptions;
  public
. . .


procedure TMuterForm.FormCreate(Sender: TObject);
var
  aTop, aLeft : integer;
begin

  // Die drei ersten Anweisungen haben einen Pointer auf ein IAudioEndpointVolume-Interface zu ermitteln, über dessen Methoden dann alle Volume-Aktionen auszuführen sind

  // kreiert ein "IMMDeviceEnumerator"-Objekt (siehe MMDevApi-Unit unten), "deviceEnumerator" zeigt dann anschließend darauf (wird nur für die nächste Codezeile benötigt)
  CoCreateInstance(CLASS_IMMDeviceEnumerator, nil, CLSCTX_INPROC_SERVER, IID_IMMDeviceEnumerator, deviceEnumerator);

  // diese "GetDefaultAudioEndpoint"-Methode des "IMMDeviceEnumerator"-Objektes besorgt dann ein "IMMDevice"-Objekt (siehe MMDevApi-Unit etwa mitte), "defaultDevice" zeigt dann anschließend darauf (wird ebenfalls wiederum nur für die nächste Codezeile benötigt)
  deviceEnumerator.GetDefaultAudioEndpoint(eRender, eConsole, defaultDevice);

  // diese "Activate"-Methode des "IMMDevice"-Objektes besorgt dann ein "IAudioEndpointVolume"-Objekt (siehe MMDevApi-Unit etwa Anfang der Interface-Deklarationen), "endpointValume" zeigt dann anschließend darauf
  //_und mit den Methoden dieses "IAudioEndpointVolume"-Objektes, gepointet durch "endpointVolume", werden dann die jeweiligen Volume-Aktionen ausgeführt
  defaultDevice.Activate(IID_IAudioEndpointVolume, CLSCTX_INPROC_SERVER, nil, endpointVolume);

  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

. . .


DIE INTERFACE-UNIT:

unit MMDevApi;


interface
uses
  Windows, ActiveX, ComObj;
const
  CLASS_IMMDeviceEnumerator            : TGUID = '{BCDE0395-E52F-467C-8E3D-C4579291692E}';
  IID_IMMDeviceEnumerator              : TGUID = '{A95664D2-9614-4F35-A746-DE8DB63617E6}';
  IID_IMMDevice                        : TGUID = '{D666063F-1587-4E43-81F1-B948E807363F}';
  IID_IMMDeviceCollection              : TGUID = '{0BD7A1BE-7A1A-44DB-8397-CC5392387B5E}';
  IID_IAudioEndpointVolume             : TGUID = '{5CDF2C82-841E-4546-9722-0CF74078229A}';
  IID_IAudioMeterInformation           : TGUID = '{C02216F6-8C67-4B5B-9D00-D008E73E0064}';
  IID_IAudioEndpointVolumeCallback     : TGUID = '{657804FA-D6AD-4496-8A60-352752AF4F89}';
  DEVICE_STATE_ACTIVE                  = $00000001;
  DEVICE_STATE_UNPLUGGED               = $00000002;
  DEVICE_STATE_NOTPRESENT              = $00000004;
  DEVICE_STATEMASK_ALL                 = $00000007;
type
  EDataFlow = TOleEnum;
const
  eRender                              = $00000000;
  eCapture                             = $00000001;
  eAll                                 = $00000002;
  EDataFlow_enum_count                 = $00000003;
type
  ERole = TOleEnum;
const
  eConsole                             = $00000000;
  eMultimedia                          = $00000001;
  eCommunications                      = $00000002;
  ERole_enum_count                     = $00000003;
type
  IAudioEndpointVolumeCallback = interface(IUnknown)
  ['{657804FA-D6AD-4496-8A60-352752AF4F89}']
  end;
  IAudioEndpointVolume = interface(IUnknown)
  ['{5CDF2C82-841E-4546-9722-0CF74078229A}']
    function RegisterControlChangeNotify(AudioEndPtVol: IAudioEndpointVolumeCallback): Integer; stdcall;
    function UnregisterControlChangeNotify(AudioEndPtVol: IAudioEndpointVolumeCallback): Integer; stdcall;
    function GetChannelCount(out PInteger): Integer; stdcall;
    function SetMasterVolumeLevel(fLevelDB: single; pguidEventContext: PGUID): Integer; stdcall;
    function SetMasterVolumeLevelScalar(fLevelDB: single; pguidEventContext: PGUID): Integer; stdcall;
    function GetMasterVolumeLevel(out fLevelDB: single): Integer; stdcall;
    function GetMasterVolumeLevelScaler(out fLevelDB: single): Integer; stdcall;
    function SetChannelVolumeLevel(nChannel: Integer; fLevelDB: double; pguidEventContext: PGUID): Integer; stdcall;
    function SetChannelVolumeLevelScalar(nChannel: Integer; fLevelDB: double; pguidEventContext: PGUID): Integer; stdcall;
    function GetChannelVolumeLevel(nChannel: Integer; out fLevelDB: double): Integer; stdcall;
    function GetChannelVolumeLevelScalar(nChannel: Integer; out fLevel: double): Integer; stdcall;
    function SetMute(bMute: Boolean; pguidEventContext: PGUID): Integer; stdcall;
    function GetMute(out bMute: Boolean): Integer; stdcall;
    function GetVolumeStepInfo(pnStep: Integer; out pnStepCount: Integer): Integer; stdcall;
    function VolumeStepUp(pguidEventContext: PGUID): Integer; stdcall;
    function VolumeStepDown(pguidEventContext: PGUID): Integer; stdcall;
    function QueryHardwareSupport(out pdwHardwareSupportMask): Integer; stdcall;
    function GetVolumeRange(out pflVolumeMindB: double; out pflVolumeMaxdB: double; out pflVolumeIncrementdB: double): Integer; stdcall;
  end;
  IAudioMeterInformation = interface(IUnknown)
  ['{C02216F6-8C67-4B5B-9D00-D008E73E0064}']
  end;
  IPropertyStore = interface(IUnknown)
  end;
  IMMDevice = interface(IUnknown)
  ['{D666063F-1587-4E43-81F1-B948E807363F}']
    function Activate(const refId: TGUID;
                      dwClsCtx: DWORD;
                      pActivationParams: PInteger;
                      out pEndpointVolume: IAudioEndpointVolume): Hresult; stdCall;
    function OpenPropertyStore(stgmAccess: DWORD; out ppProperties: IPropertyStore): Hresult; stdcall;
    function GetId(out ppstrId: PLPWSTR): Hresult; stdcall;
    function GetState(out State: Integer): Hresult; stdcall;
  end;

  IMMDeviceCollection = interface(IUnknown)
  ['{0BD7A1BE-7A1A-44DB-8397-CC5392387B5E}']
  end;
  IMMNotificationClient = interface(IUnknown)
  ['{7991EEC9-7E89-4D85-8390-6C703CEC60C0}']
  end;
  IMMDeviceEnumerator = interface(IUnknown)
  ['{A95664D2-9614-4F35-A746-DE8DB63617E6}']
    function EnumAudioEndpoints(dataFlow: EDataFlow; deviceState: SYSUINT; DevCollection: IMMDeviceCollection): Hresult; stdcall;
    function GetDefaultAudioEndpoint(EDF: SYSUINT; ER: SYSUINT; out Dev :IMMDevice ): Hresult; stdcall;
    function GetDevice(pwstrId: pointer; out Dev: IMMDevice): HResult; stdcall;
    function RegisterEndpointNotificationCallback(pClient: IMMNotificationClient): Hresult; stdcall;
  end;
implementation
end.

Kennt event. jemand dieses merkwürdige Phänomen? Was läuft da schief?

Event. noch etwas zum Hintergrund: Die simple Hauptaufgabe des Progs ist es, mittels eines IAudioEndpointVolume-Interfaces schon beim ProgStart den Ton abzustellen ...um sich den ewigen Werbevorspann vor irgendwelchen kleinen Internet-Videos im IExplorer so zumindest akustisch etwas vom Leib halten zu können. Beim Programmende schaltet es den Ton dann wieder an.

Gruß

t.roller 24. Nov 2016 17:40

AW: Interface 'IAudioEndpointVolume' läuft unter TurboDelphi aber nicht unter Delphi1
 
Alternative:
Delphi-Quellcode:
const
  VK_VOLUME_MUTE = $AD;
  VK_VOLUME_DOWN = $AE;
  VK_VOLUME_UP = $AF;

procedure Press(Key: Byte);
begin
 keybd_event(Key, 0, 0, 0);
 keybd_event(Key, 0, KEYEVENTF_KEYUP, 0);
end;

procedure VolumeUP;
begin
  Press(VK_VOLUME_UP);
end;

procedure VolumeDOWN;
begin
  Press(VK_VOLUME_DOWN);
end;

procedure Mute;
begin
  Press(VK_VOLUME_MUTE);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Mute;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  VolumeUP;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  VolumeDOWN;
end;

r29d43 24. Nov 2016 22:55

AW: Interface 'IAudioEndpointVolume' läuft unter TurboDelphi aber nicht unter Delphi1
 
Danke, klappt (und das obgleich ich kein Keyboard habe, das solche Keys überhaupt besitzt)!

@all
..was allerdings nicht heißt, dass mich die Lösung für mein endpointVolume-Prob oben nicht mehr interessiert ...weil auch mittels dieses keybd_event -Verfahrens hat man dann nämlich immer noch die Schwierigkeit rauszukriegen, ob der Ton aktuell überhaupt an ist oder aus.

t.roller 24. Nov 2016 23:14

AW: Interface 'IAudioEndpointVolume' läuft unter TurboDelphi aber nicht unter Delphi1
 
Oder so mit CheckBox:
Delphi-Quellcode:
procedure TForm1.cbMUTEClick(Sender: TObject);
var b: LongBool;
begin                //Mute on/off
 if endpointVolume = nil then Exit;
 b := cbMUTE.Checked;
 endpointVolume.SetMute(b, nil);
end;

r29d43 24. Nov 2016 23:41

AW: Interface 'IAudioEndpointVolume' läuft unter TurboDelphi aber nicht unter Delphi1
 
Thx, aber es geht nicht darum, endpointVolume nicht richtig anwenden zu könnnen. Wenn endpointVolume sich normal kreieren ließe, mein Programm damit also nicht irgendwie kaputt gehen würde, sprich es dann auch diese oben erwähnten Zugriffsverletzungen nicht mehr gäbe, dann hätte ich keine Schwierigkeiten diesen Status mittels endpointVolume auszulesen. Hatte ja auch mittels eines Turbo-Delphi-compilierten Progs ohne Probleme geklappt. Nur halt jetzt nicht mehr wenn ich dieses Programm mittels Delphi10.1 compiliere.

samso 25. Nov 2016 05:25

AW: Interface 'IAudioEndpointVolume' läuft unter TurboDelphi aber nicht unter Delphi1
 
Ich glaube nicht das der Fehler durch den gezeigten Code hervorgerufen wird, sondern an einer anderen Stelle. Ich würde denken, dass an irgend einer Stelle Speicher überschrieben wird. Verdächtige Kandidaten sind move-Befehle insbesondere im Zusammenhang mit Strings (die nun Unicode sind). Zusätzlich wäre es ganz gut die Rückgabewerte der Funktionsaufrufe auszuwerten (und bei einem Fehler eine Exception auszulösen o.ä).

t.roller 25. Nov 2016 07:20

AW: Interface 'IAudioEndpointVolume' läuft unter TurboDelphi aber nicht unter Delphi1
 
Woher bekommt MuteStatus : boolean; seinen Wert?
Getmute liefert einen INTEGER-Wert zurück.

Ersetze MMDevAPI:
Delphi-Quellcode:
unit MMDevAPI; //20161125

interface

uses
//  Windows, ActiveX, ComObj;
  Winapi.Windows, Winapi.ActiveX, System.Win.ComObj;

const
  CLASS_IMMDeviceEnumerator            : TGUID = '{BCDE0395-E52F-467C-8E3D-C4579291692E}';
  IID_IMMDeviceEnumerator              : TGUID = '{A95664D2-9614-4F35-A746-DE8DB63617E6}';
  IID_IMMDevice                        : TGUID = '{D666063F-1587-4E43-81F1-B948E807363F}';
  IID_IMMDeviceCollection              : TGUID = '{0BD7A1BE-7A1A-44DB-8397-CC5392387B5E}';
  IID_IAudioEndpointVolume             : TGUID = '{5CDF2C82-841E-4546-9722-0CF74078229A}';
  IID_IAudioMeterInformation           : TGUID = '{C02216F6-8C67-4B5B-9D00-D008E73E0064}';
  IID_IAudioEndpointVolumeCallback     : TGUID = '{657804FA-D6AD-4496-8A60-352752AF4F89}';

  DEVICE_STATE_ACTIVE                  = $00000001;
  DEVICE_STATE_UNPLUGGED               = $00000002;
  DEVICE_STATE_NOTPRESENT              = $00000004;
  DEVICE_STATEMASK_ALL                 = $00000007;

type
  EDataFlow = TOleEnum;

const
  eRender                              = $00000000;
  eCapture                             = $00000001;
  eAll                                 = $00000002;
  EDataFlow_enum_count                 = $00000003;
               
type
  ERole = TOleEnum;

const
  eConsole                             = $00000000;
  eMultimedia                          = $00000001;
  eCommunications                      = $00000002;
  ERole_enum_count                     = $00000003;

type
  IAudioEndpointVolumeCallback = interface(IUnknown)
  ['{657804FA-D6AD-4496-8A60-352752AF4F89}']
  end;

  IAudioEndpointVolume = interface(IUnknown)
  ['{5CDF2C82-841E-4546-9722-0CF74078229A}']
    function RegisterControlChangeNotify(AudioEndPtVol: IAudioEndpointVolumeCallback): Integer; stdcall;
    function UnregisterControlChangeNotify(AudioEndPtVol: IAudioEndpointVolumeCallback): Integer; stdcall;
    function GetChannelCount(out PInteger): Integer; stdcall;
    function SetMasterVolumeLevel(fLevelDB: single; pguidEventContext: PGUID): Integer; stdcall;
    function SetMasterVolumeLevelScalar(fLevelDB: single; pguidEventContext: PGUID): Integer; stdcall;
    function GetMasterVolumeLevel(out fLevelDB: single): Integer; stdcall;
    function GetMasterVolumeLevelScaler(out fLevelDB: single): Integer; stdcall;
    function SetChannelVolumeLevel(nChannel: Integer; fLevelDB: double; pguidEventContext: PGUID): Integer; stdcall;
    function SetChannelVolumeLevelScalar(nChannel: Integer; fLevelDB: double; pguidEventContext: PGUID): Integer; stdcall;
    function GetChannelVolumeLevel(nChannel: Integer; out fLevelDB: double): Integer; stdcall;
    function GetChannelVolumeLevelScalar(nChannel: Integer; out fLevel: double): Integer; stdcall;
    function SetMute(bMute: Boolean; pguidEventContext: PGUID): Integer; stdcall;
    function GetMute(out bMute: Boolean): Integer; stdcall;
    function GetVolumeStepInfo(pnStep: Integer; out pnStepCount: Integer): Integer; stdcall;
    function VolumeStepUp(pguidEventContext: PGUID): Integer; stdcall;
    function VolumeStepDown(pguidEventContext: PGUID): Integer; stdcall;
    function QueryHardwareSupport(out pdwHardwareSupportMask): Integer; stdcall;
    function GetVolumeRange(out pflVolumeMindB: double; out pflVolumeMaxdB: double; out pflVolumeIncrementdB: double): Integer; stdcall;
  end;

  IAudioMeterInformation = interface(IUnknown)
  ['{C02216F6-8C67-4B5B-9D00-D008E73E0064}']
  end;

  IPropertyStore = interface(IUnknown)
  end;

  IMMDevice = interface(IUnknown)
  ['{D666063F-1587-4E43-81F1-B948E807363F}']
    function Activate(const refId: TGUID;
                      dwClsCtx: DWORD;
                      pActivationParams: PInteger;
                      out pEndpointVolume: IAudioEndpointVolume): Hresult; stdCall;
    function OpenPropertyStore(stgmAccess: DWORD; out ppProperties: IPropertyStore): Hresult; stdcall;
    function GetId(out ppstrId: PLPWSTR): Hresult; stdcall;
    function GetState(out State: Integer): Hresult; stdcall;
  end;


  IMMDeviceCollection = interface(IUnknown)
  ['{0BD7A1BE-7A1A-44DB-8397-CC5392387B5E}']
  end;

  IMMNotificationClient = interface(IUnknown)
  ['{7991EEC9-7E89-4D85-8390-6C703CEC60C0}']
  end;

  IMMDeviceEnumerator = interface(IUnknown)
  ['{A95664D2-9614-4F35-A746-DE8DB63617E6}']
    function EnumAudioEndpoints(dataFlow: EDataFlow; deviceState: SYSUINT; DevCollection: IMMDeviceCollection): Hresult; stdcall;
    function GetDefaultAudioEndpoint(EDF: SYSUINT; ER: SYSUINT; out Dev :IMMDevice ): Hresult; stdcall;
    function GetDevice(pwstrId: pointer; out Dev: IMMDevice): HResult; stdcall;
    function RegisterEndpointNotificationCallback(pClient: IMMNotificationClient): Hresult; stdcall;
  end;

implementation

end.

himitsu 25. Nov 2016 09:22

AW: Interface 'IAudioEndpointVolume' läuft unter TurboDelphi aber nicht unter Delphi1
 
"Boolean" (1 Byte) ist auch falsch, da BOOL dem LongBool (4 Byte) entspricht.
Und bei GetChannelCount hat sich auch ein Fehler eingeschlichen.
Delphi-Quellcode:
GetChannelCount(out pnChannelCount: Integer)

Aber ist grundsätzlich erstmal egal, da solche Fehler sowohl in DX10, also auch in D2006 einen Fehler darstellen.

Ansonsten sehen die gezeigeten paar wenigen Codezeilen eigentlich OK aus.

Zacherl 25. Nov 2016 09:26

AW: Interface 'IAudioEndpointVolume' läuft unter TurboDelphi aber nicht unter Delphi1
 
Tippe auch auf einen Buffer-Overflow an anderer Stelle. Funktioniert das Interface in einem komplett neuen Projekt oder kracht es da auch?

r29d43 25. Nov 2016 16:09

AW: Interface 'IAudioEndpointVolume' läuft unter TurboDelphi aber nicht unter Delphi1
 
Thx @all erstmal.

Ich habe mal Zacherls Rat umgesetzt und ein neues Prog mit diesem Interface aufgesetzt. Erstes Ergebnis: Es kam zu keinen dieser besagten Exceptions mehr. Auch als ich anschließend mein Prob-Prog Stück für Stück in dieses neue integriert habe, lief erstmal noch alles glatt.

...Was also immerhin schonmal zeigt, dass Delphie 10.1 durchaus auch mit diesem Interface kann.

Erst als ich ganz zum Schluss auch noch die beiden Timer einbaute, stellten sich diese besagten Exceptions wieder ein. Und zwar dann, wenn ich in dieser TimerProc auf eine Feld-Variable der Hauptform zugreife, so wie ich das schon in Post 1 geschildert habe.

Vermutungen?

Zacherl 26. Nov 2016 11:32

AW: Interface 'IAudioEndpointVolume' läuft unter TurboDelphi aber nicht unter Delphi1
 
Zitat:

Zitat von r29d43 (Beitrag 1354699)
Vermutungen?

Ist leider ohne den kompletten Source ein reines Ratespiel. Irgendwo wirst du über (Array/String/etc.)Bereichsgrenzen hinaus schreiben oder durch manuelle Pointer-Spielchen den Speicher korrumpieren.

r29d43 26. Nov 2016 14:55

AW: Interface 'IAudioEndpointVolume' läuft unter TurboDelphi aber nicht unter Delphi1
 
Ich habe das Prog jetzt nochmal neu aufgebaut - nur jetzt aus der anderen Richtung her aufgezogen. Nach der Installation des endpointVolume-Interfaces dann zuerst den Timer auf die Form gesetzt (bei dem ja im Versuch davor die Exceptions angefangen haben). Dann die Timer-Proc erstellt, von der aus, nach einer kleine Anweisung, dann eine weitere kleine Proc aufrufen wird. Und schon ab da tritt der Fehler auch hier immer wieder auf, also ohne ein weiteres Control auf der Form und mit nur einer weiteren Feld-Variablen (jenseits der drei, die ich für die Installation des Interfaces brauche).

Ich liste das Mini-Prog, das so natürlich keinerlei Sinn mehr ergibt, trotzdem noch mal auf. Eventuell will das ja mal jemand kurz gegenchecken. Aktuelles System auf dem ich das gerade ausprobiere ist Win7. Die Exception

---------------------------
Benachrichtigung über Debugger-Exception
---------------------------
Im Projekt Project1.exe ist eine Exception der Klasse $C0000005 mit der Meldung 'access violation at 0x005c9d80: read of address 0x00000001' aufgetreten.
---------------------------
Anhalten Fortsetzen Hilfe
---------------------------

taucht bei mir jedesmal in dieser Proc "BlablaSub" auf.

Delphi-Quellcode:
unit unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, ActiveX, MMDevApi, Vcl.ExtCtrls;

type
  TForm1 = class(TForm)
    Timer1: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
  private
    { Private-Deklarationen }
    endpointVolume: IAudioEndpointVolume;    // Interface-Pointer, Interface ist in MMDevApi definiert; ..wird im Prog dann als drittes ermittelt
    deviceEnumerator: IMMDeviceEnumerator;   // Interface-Pointer, Interface ist in MMDevApi definiert; ..wird im Prog als erster ermittelt
    defaultDevice: IMMDevice;                // Interface-Pointer, Interface ist in MMDevApi definiert; ..wird im Prog als zweites ermittelt

    MuteStatus : boolean;
    procedure BlablaSub;
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}


procedure TForm1.FormCreate(Sender: TObject);
begin
  // Die drei ersten Anweisungen haben einen Pointer auf ein IAudioEndpointVolume-Interface zu ermitteln, über dessen Methoden dann alles geht

  // kreiert ein "IMMDeviceEnumerator"-Objekt (siehe MMDevApi-Unit unten), "deviceEnumerator" zeigt dann anschließend darauf
  CoCreateInstance(CLASS_IMMDeviceEnumerator, nil, CLSCTX_INPROC_SERVER, IID_IMMDeviceEnumerator, deviceEnumerator);
  // diese "GetDefaultAudioEndpoint"-Methode des "IMMDeviceEnumerator"-Objektes besorgt dann ein "IMMDevice"-Objekt (siehe MMDevApi-Unit etwa mitte), "defaultDevice" zeigt dann anschließend darauf
  deviceEnumerator.GetDefaultAudioEndpoint(eRender, eConsole, defaultDevice);
  // diese "Activate"-Methode des "IMMDevice"-Objektes besorgt dann ein "IAudioEndpointVolume"-Objekt (siehe MMDevApi-Unit etwa Anfang der Interface-Deklarationen), "endpointValume" zeigt dann anschließend darauf
  //_und mit den Methoden dieses "IAudioEndpointVolume"-Objektes, gepointet durch "endpointVolume", wird dann alles geschaltet
  defaultDevice.Activate(IID_IAudioEndpointVolume, CLSCTX_INPROC_SERVER, nil, endpointVolume);

  // die nächsten 2 Zeilen weisen dem Timer zwar nur Defaulteinstellungen zu, sollen also genau das auch nur aussagen
  Timer1.Enabled := true;
  Timer1.Interval := 1000;
end;


procedure TForm1.Timer1Timer(Sender: TObject);
var momMuteStatus : boolean;
begin
  endpointVolume.GetMute(momMuteStatus);

  if momMuteStatus <> MuteStatus then
    BlablaSub;
end;

procedure TForm1.BlablaSub;
var aResult : integer;
begin
  aResult := endpointVolume.GetMute(MuteStatus);

end;

end.

EWeiss 26. Nov 2016 15:21

AW: Interface 'IAudioEndpointVolume' läuft unter TurboDelphi aber nicht unter Delphi1
 
Keine Ahnung was du da machst.
Aber warum glaubst du wohl gibt es für IAudioEndpointVolume eine dazugehörige IAudioEndpointVolumeCallback ?
Schlechte Idee dafür einen Timer zu verwenden.

Zudem ist die Übergabe BOOL und nicht Boolean..
MuteStatus : BOOL;

gruss

t.roller 26. Nov 2016 15:23

AW: Interface 'IAudioEndpointVolume' läuft unter TurboDelphi aber nicht unter Delphi1
 
"if momMuteStatus <> MuteStatus then..."

Das habe ich aber weiter oben schon mal gefragt:
Was hat MuteStatus für einen Wert?

Ausserdem würde ich GetMute nicht im Timer aufrufen - ist unsinnig, weil es global wirkt und nicht nur für das aufrufende Programm.

r29d43 26. Nov 2016 15:45

AW: Interface 'IAudioEndpointVolume' läuft unter TurboDelphi aber nicht unter Delphi1
 
Ok, nachdem ich in der Interface-Unit bzgl. dieser GetMute-Funktion nun das Boolean durchs Bool ersetzt habe (und das auch noch in meinem Prog getan habe), sind die Exceptions verschwunden. Thx all. Müssten demnach dann nicht eigentlich auch noch alle übrigen Boolean-Typen in dieser Interface-Unit durch ein Bool ausgewechselt werden? Nehme mal an, ja. Hatte diese Unit irgendwann mal aus dem Netz gedownloaded. Und wie gesagt: Mit TurboDelphi hatte es immer problemlos geklappt.

r29d43 26. Nov 2016 15:51

AW: Interface 'IAudioEndpointVolume' läuft unter TurboDelphi aber nicht unter Delphi1
 
Zitat:

Zitat von t.roller (Beitrag 1354753)
Ausserdem würde ich GetMute nicht im Timer aufrufen - ist unsinnig, weil es global wirkt und nicht nur für das aufrufende Programm.

Warum? GetMute ist doch nur eine Status-Abfrage. Da ist es imo doch unrelevant ob es eine quasi globale Abfrage ist oder nicht, oder?

Zacherl 26. Nov 2016 16:24

AW: Interface 'IAudioEndpointVolume' läuft unter TurboDelphi aber nicht unter Delphi1
 
Zitat:

Zitat von r29d43 (Beitrag 1354754)
Ok, nachdem ich in der Interface-Unit bzgl. dieser GetMute-Funktion nun das Boolean durchs Bool ersetzt habe (und das auch noch in meinem Prog getan habe), sind die Exceptions verschwunden. Thx all. Müssten demnach dann nicht eigentlich auch noch alle übrigen Boolean-Typen in dieser Interface-Unit durch ein Bool ausgewechselt werden? Nehme mal an, ja. Hatte diese Unit irgendwann mal aus dem Netz gedownloaded. Und wie gesagt: Mit TurboDelphi hatte es immer problemlos geklappt.

Jap mit ziemlicher Sicherheit. Microsoft Schnittstellen bzw. C im allgemeinen verwendet in der Regel 4-Byte Booleans (= BOOL). Dass es vorher geklappt hat war reiner Zufall, da du dir mit den falschen Parametern auf jeden Fall den Stack kaputt machst. Die Integer Results sind btw. auch falsch, das müsste HRESULT sein und
Delphi-Quellcode:
stdcall
kannst du mit
Delphi-Quellcode:
safecall
ersetzen, wenn du lieber Exceptions statt Error-Codes hast. Generell solltest du auf jeden Fall die Fehlercodes von MSDN-Library durchsuchenCoCreateInstance und den Interface Methoden prüfen.

t.roller 26. Nov 2016 16:38

AW: Interface 'IAudioEndpointVolume' läuft unter TurboDelphi aber nicht unter Delphi1
 
Liste der Anhänge anzeigen (Anzahl: 1)
DELPHI wird bis zum bitteren Ende herumzicken - siehe Anhang.

Zitat:
"Einen Test auf Gleichheit mit Hilfe des Operators "ungleich" zu formulieren, kann jedoch als fragwürdiger Programmierstil aufgefaßt werden ... "
Datentyp bool in C/C++ (In C++ hat AUDIO_VOLUME_NOTIFICATION_DATA seinen Ursprung)

EWeiss 26. Nov 2016 17:15

AW: Interface 'IAudioEndpointVolume' läuft unter TurboDelphi aber nicht unter Delphi1
 
Zitat:

DELPHI wird bis zum bitteren Ende herumzicken - siehe Anhang.
Nicht wenn man es richtig macht..

Delphi-Quellcode:
  HR := AudioEndpointVolume.GetMute(b);
  if HR = S_OK then
    if Value <> b then
    begin
      // ** We should use very tricky code as follows.
      // ** If we use normal sentence like "AudioEndpointVolume.SetMute(Value, nil);"
      // ** it does not operate.
      if b then
        i := 0
      else
        i := 1;
      AudioEndpointVolume.SetMute(BOOL(i), @GUID_TAudioVolume);
    end;
Davon ab da ist einiges im argen, aber sei's drum.
Wenn du Boolean definierst solltest du es explicit casten.. siehe dieses Beispiel.

gruss

r29d43 26. Nov 2016 18:37

AW: Interface 'IAudioEndpointVolume' läuft unter TurboDelphi aber nicht unter Delphi1
 
Zitat:

Zitat von t.roller (Beitrag 1354753)
"if momMuteStatus <> MuteStatus then..."

Das habe ich aber weiter oben schon mal gefragt:
Was hat MuteStatus für einen Wert?

Du hattest das in Post7 mit dem Boolean-Wert auf der einen Seite und dem Integer-Wert auf der anderen Seite etwas falsch interpretiert, weil ja der Funktionswert nur für die Kontrolle, ob die Funktion überhaupt richtig arbeiten konnte, zurückgegeben wird. Der hat mit diesem abzufragenden MuteStatus ansonsten nämlich garnichts zu tun, weil dieser MuteStatus-Wert eben über den von dir angegebenen Parameter in der Klammer der Funktion übergeben wird. Von daher war das für mich also der nicht richtige Ansatz und weshalb ich diese Boolean-Antwort dann im Weiteren natürlich blöderweise insgesamt ignoriert. Zumal das von himitsu sicher keine Fehlinterpretation sein konnte. Aber deine Fehlinterpretation dieser Situation hatte mich einfach zu sehr davon abgebracht ..so dass ich tatsächlich nochmal einen dritten Anstoß von EWeiss in diese Richtung brauchte. :stupid:

EWeiss 26. Nov 2016 18:47

AW: Interface 'IAudioEndpointVolume' läuft unter TurboDelphi aber nicht unter Delphi1
 
Zitat:

Du hattest das in Post7 mit dem Boolean-Wert auf der einen Seite und dem Integer-Wert auf der anderen Seite etwas falsch interpretiert
Zitat:

Woher bekommt MuteStatus : boolean; seinen Wert?
Getmute liefert einen INTEGER-Wert zurück.

Ersetze MMDevAPI:
Ok das war alles falsch basierend auf dein Schnipsel.
BOOL und HRESULT wäre richtig gewesen, aber gut.

Zitat:

so dass ich tatsächlich nochmal einen dritten Anstoß von EWeiss in diese Richtung brauchte.
Na ja himitsu hat da im Beitrag 8 schon drauf hingewiesen.
Zitat:

"Boolean" (1 Byte) ist auch falsch, da BOOL dem LongBool (4 Byte) entspricht.
Das wäre alles nicht passiert wenn du die Interface selbst übersetzt hättest.
Wie schon gesagt da ist noch einiges im argen.

Einfaches Beispiel..
Die richtige Code-Zeile für GetMute sieht aus wie folgt.

Delphi-Quellcode:
function GetMute(var pbMute: BOOL): HRESULT; stdcall;
Durch den var Parameter pbMute hättest du Boolean gar nicht erst übergeben können (Der Fehler wäre also niemals aufgetreten)
Dann wie Zacherl schon sagte ist die Rückgabe HRESULT nicht Integer.. wenn schon dann "LongInt"
usw..

gruss

r29d43 26. Nov 2016 20:59

AW: Interface 'IAudioEndpointVolume' läuft unter TurboDelphi aber nicht unter Delphi1
 
na, jetzt mach aber bitte mal ein bisschen halblang. :-D

Zitat:

Zitat:

Woher bekommt MuteStatus : boolean; seinen Wert?
Getmute liefert einen INTEGER-Wert zurück.

Ersetze MMDevAPI:
Ok das war alles falsch basierend auf dein Schnipsel.
BOOL und HRESULT wäre richtig gewesen, aber gut.
Wieso basierend auf meinem Schnipsel? Das sehe ich minimal anders. Für mich liest sich das schlicht so, dass er diese Art der Ergebnisübergabe noch garnicht so richtig kannte und hier einfach einen angeblichen Vergleich zwischen Boolean- und INTEGER-Wert beanstanden wollte. 8-)


Zitat:

Zitat:

so dass ich tatsächlich nochmal einen dritten Anstoß von EWeiss in diese Richtung brauchte.
Na ja himitsu hat da im Beitrag 8 schon drauf hingewiesen.
Zitat:

"Boolean" (1 Byte) ist auch falsch, da BOOL dem LongBool (4 Byte) entspricht.

habe ich doch selbst schon so anklingen lassen, oder? :)

Zitat:

Das wäre alles nicht passiert wenn du die Interface selbst übersetzt hättest.
Da gebe ich dir allerdings recht. Obschon wage ich es mal festzustellen, dass sich der ganz große Tross des Programmierervolkes ebenfalls auf diese etwas schnellere Art und Weise fortzubewegen versucht. Es reicht imo, wenn man den im Internet irgendwo erspähten Code grundsätzlich begriffen hat, diesen vllt. noch da o. da etwas sinnvoll auskommentiert hat, und wenn der anschließend auch noch (jahrelang) fehlerlose Ergebnisse bringt, dann ist der eben gebongt. Erst wenn ich mal irgendein etwas größeres Projekt bzgl. dieses Themas machen möchte, und nicht nur ein kleines Mini-Progrämmchen, werde ich mir die Sache nochmal etwas gründlicher und eingehender zu Gemüte führen. Das wird auch bei sehr vielen anderen so die Regel sein, und ist durchaus auch sinnvoll bzw. notwendig, wenn überhaupt eine irgendwie nennenswerte Masse an interessantem Code, den man mal wenigstens so zur Kenntnis genommen haben sollte, herauskommen soll. :!:



Zitat:

Wie schon gesagt da ist noch einiges im argen.
Danke, danke, danke, es sprach wohl der ganz ganz große Meister himself! :shock:

Zitat:

Einfaches Beispiel..
Die richtige Code-Zeile für GetMute sieht aus wie folgt.
Geschenkt, für solche extra schöngeschriebenen Sandmännchengeschichtchen bin ich schon zu alt.

usw.. :arrow:



Schönen Abend,
trotzdem noch.
:cheers:

EWeiss 26. Nov 2016 21:15

AW: Interface 'IAudioEndpointVolume' läuft unter TurboDelphi aber nicht unter Delphi1
 
Zitat:

Geschenkt, für solche extra schöngeschriebenen Sandmännchengeschichtchen bin ich schon zu alt.
Nun gut war mir eine Lehre bzgl. deiner Threads und Fragen für die Zukunft werde ich mich zurückhalten.
Nachher wenn alles behoben durch die Hilfestellung diverser User hier markierst du den großen Mann..

Aber du hast natürlich in einem recht. Geschenkt! So soll es dann sein.

gruss

Daniel 27. Nov 2016 09:23

AW: Interface 'IAudioEndpointVolume' läuft unter TurboDelphi aber nicht unter Delphi1
 
Zitat:

Zitat von r29d43 (Beitrag 1354767)
Geschenkt, für solche extra schöngeschriebenen Sandmännchengeschichtchen bin ich schon zu alt.

Aber zum lernen ist man nie zu alt. Erinnern wir uns kurz an den Anfang dieser Diskussion: Du hattest gefragt, warum Dein Programm nicht läuft. Der Austausch von Wissen ist Sinn & Zweck dieses Forums. Jeder von uns lernt dabei neue Sachen, die er bisher nicht kannte - das ist doch gerade der Witz und kein Grund für verletzten Stolz.

r29d43 27. Nov 2016 12:52

AW: Interface 'IAudioEndpointVolume' läuft unter TurboDelphi aber nicht unter Delphi1
 
Zitat:

Zitat von Daniel (Beitrag 1354770)
Zitat:

Zitat von r29d43 (Beitrag 1354767)
Geschenkt, für solche extra schöngeschriebenen Sandmännchengeschichtchen bin ich schon zu alt.

Aber zum lernen ist man nie zu alt. Erinnern wir uns kurz an den Anfang dieser Diskussion: Du hattest gefragt, warum Dein Programm nicht läuft. Der Austausch von Wissen ist Sinn & Zweck dieses Forums. Jeder von uns lernt dabei neue Sachen, die er bisher nicht kannte - das ist doch gerade der Witz und kein Grund für verletzten Stolz.

Natürlich, da gebe ich dir ja durchaus recht. Allerdings gebe ich auch zu bedenken, dass man diesen von dir zitierten Satz nicht von der Diskussionssituation an dieser Stelle im Thread unabhängig betrachten darf. Denn EWeiss hatte in seinem Post davor ja auch nur in einer reichlich absurden, sehr aufgeblähten Weise versucht, sich mittels großteils eher unangemessener Kritik (nach meiner ja schon durchaus kleinen Selbstkritik im Post davor) auf mir aufzubahren. Und sowas gehört doch mindestens ebensowenig in ein Forum (wenn nicht noch weniger). Meine Antwort war dann eher nur eine durch diesen Stil herausgenötigte dazu dann wiederum ganz passende lustige Erwiderung. So nach dem Motto: Wer sich seine kleine Hilfe weit überzogen hochrechnen möchte, um sich damit dann dermaßen künstlich auf dem Fragenden aufbahren zu können, dessen kleine Hilfe braucht doch niemand wirklich (also "geschenkt").

P.S.
"DragonsLear" ähnliche Helferfiguren (sicher allen bekannt aus dem DelphiTreff-Forum) sind in keinem Forum wirklich eine echte Hilfe. Man sollte sich also ggf. schonmal minimal gegen sie wehren dürfen. Ansonsten treiben die nämlich die Leute nur aus einem Forum raus und zu anderen Foren hin. Dieses Forum ist ja selbst nur ein ziemlich Nutznießer besagter Person gewesen, seinerzeit.

EWeiss 27. Nov 2016 15:52

AW: Interface 'IAudioEndpointVolume' läuft unter TurboDelphi aber nicht unter Delphi1
 
Zitat:

nur in einer reichlich absurden, sehr aufgeblähten Weise versucht, sich mittels großteils eher unangemessener Kritik
Ich habe seinerzeit die TAudioVolume (CoreAudio) mit Silhwan zusammen entwickelt bzw. für Delphi zur verfügung gestellt.
Deshalb maße ich mir an davon einiges zu verstehen.
Wenn ich also auf die korrekte Function, Schreibweise hinweise hat das meines Erachtens nichts mit Überheblichkeit oder dergleichen zu tun
sondern mit wissen.

Wenn du dich nun nach der Behebung deines Problems (kein wissen deinerseits) nun so hervorheben willst, kann ich damit leben.
Nur wie gesagt von meiner Seite her noch mal Hilfe zu erwarten bei diversen anderen Problemen kannst du dir wie von dir gewünscht schenken.

Zitat:

auf mir aufzubahren
Dir fehlte einfach das Wissen nicht mehr und nicht weniger.
Selbst nach dem Neuaufbau hast du die selben Fehler wieder eingebaut.

Damit das hier nicht ausartet ist das Thema für mich erledigt.

gruss

r29d43 27. Nov 2016 16:51

AW: Interface 'IAudioEndpointVolume' läuft unter TurboDelphi aber nicht unter Delphi1
 
Zitat:

Wenn ich also auf die korrekte Function, Schreibweise hinweise...
Wenn es nur das alleine gewesen wäre..., aber das ging ja wohl ein ordentliches Stück darüber hinaus. Und jeder kann ja auch in Post#21 sehen, wie weit du das auszureizen versucht hast. Es ist schon verblüffend, wie stark du daran immer vorbeizureden versuchst.

Zitat:

Selbst nach dem Neuaufbau hast du die selben Fehler wieder eingebaut.
Weil dieser Fehler nicht nur in meinem persönlichen Code lag, sondern grundlegend in erster Linie in dieser jahrelang korrekt funktioniert habenden Interface-Unit, die ich vor sehr langem mal irgendwo aus dem Netz gedownloadet hatte. Außerdem diente dieser Neuaufbau auch überhaupt erstmal nur der primären Lokalisierung des Errors. Und alles restliche diesbezüglich hatte ich ja auch schon in Post #20 erklärt. Wie man dann in Post #21 nochmal so eine Show abzuziehen versucht, erklärt sich jedenfalls sicher nicht mit Wissen – und wenn doch, wärs umso trauriger, weil nämlich dann umso mehr genau das, was ich an deinem fraglichen Stil schon anzudeuten versucht habe.

EWeiss 27. Nov 2016 17:05

AW: Interface 'IAudioEndpointVolume' läuft unter TurboDelphi aber nicht unter Delphi1
 
Zitat:

dieser jahrelang korrekt funktioniert habenden Interface-Unit,
Nur weil etwas funktioniert muss es noch lange nicht richtig sein.

Der Rest.. Geschenkt!

gruss

Daniel 27. Nov 2016 17:16

AW: Interface 'IAudioEndpointVolume' läuft unter TurboDelphi aber nicht unter Delphi1
 
Lüüüüd - das Thema ist doch eigentlich erledigt. Die technischen Probleme offenbar klar identifiziert und behoben. Kann es sein, dass Ihr Euch gerade lediglich auf dem "falschen Fuß" erwischt habt?
Den Rest klärt bitte per PN.

EWeiss 27. Nov 2016 17:19

AW: Interface 'IAudioEndpointVolume' läuft unter TurboDelphi aber nicht unter Delphi1
 
Zitat:

Zitat von Daniel (Beitrag 1354785)
Den Rest klärt bitte per PN.

Bestimmt nicht.
Aber sagte ja schon ist für mich erledigt.
Und das mein letzter Beitrag dazu.

gruss

Zacherl 27. Nov 2016 23:47

AW: Interface 'IAudioEndpointVolume' läuft unter TurboDelphi aber nicht unter Delphi1
 
Zitat:

Zitat von t.roller (Beitrag 1354759)
DELPHI wird bis zum bitteren Ende herumzicken - siehe Anhang

Mhh :gruebel: bei mir ist BOOL in der Windows.pas korrekt als
Delphi-Quellcode:
BOOL = LongBool
definiert.


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:15 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz