le supprimer oui mais le remplacer par "const" serait plus juste puisqueCordialement,Envoyé par Andnotor
@+
le supprimer oui mais le remplacer par "const" serait plus juste puisqueCordialement,Envoyé par Andnotor
@+
Ok. J'ai essayé: ça marche avec CONST et OUT comme préfixe de la déclaration du paramètre si j'omets le type.
J'ai appris des choses, dans cette discussion ! Merci beaucoup à vous tous. J'en conclus qu'un paramètre passé sans type est interprété comme pointeur non typé et utilisé comme tel par la fonction en iinterne. Bon à savoir.
Je pensais à un paramètre typé (ou simplement de type pointer si ça devait poser problème), plus proche du prototype et plus parlant à la relecture dans quelques mois :
Mais si tu es satisfait, pas de soucis
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 function GetChannelsPeakValues(u32ChannelCount: UINT; afPeakValues: pSingle): HRESULT; stdcall; var ChannelVolumes :array of single; SetLength(ChannelVolumes, nChannels); HR := peak.GetChannelsPeakValues(nChannels, ChannelVolumes);
ps: je ne sais pas quelle est l'influence de const sur une méthode d'interface.
Oui... mais non ! Delphi 6 Personal Edition est têtu ! Voici le résultat de compilation, avec cette déclaration:
et la déclaration!:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 IAudioMeterInformation = interface(IUnknown) ['{C02216F6-8C67-4B5B-9D00-D008E73E0064}'] function GetPeakValue(out pfPeak: Single): HRESULT; stdcall; function GetMeteringChannelCount(out pnChannelCount: UINT): HRESULT; stdcall; // function GetChannelsPeakValues(u32ChannelCount: UINT; out afPeakValues: pSingle): HRESULT; stdcall; // version 1 // function GetChannelsPeakValues(u32ChannelCount: UINT; out afPeakValues): HRESULT; stdcall; //version 2 function GetChannelsPeakValues(u32ChannelCount: UINT; afPeakValues: pSingle): HRESULT; stdcall; //version 3 function QueryHardwareSupport(out pdwHardwareSupportMask: UINT): HRESULT; stdcall; end;
Etrange alors
ChannelVolumes est un pointeur sur un array et non un array et la déclaration est un pointeur sur un single et non un single...
Bref, laisse comme c'était si ça fonctionne ainsi (je ne suis pas au bureau et ne peut pas tester)
Merci, Andnotor. Je vois enfin plus clair.
Voici une version plus "lisible", qui passe à la compilation et qui fonctionne en exécution:
Déclaration de l'interface:
Déclaration des variables globales:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 IAudioMeterInformation = interface(IUnknown) ['{C02216F6-8C67-4B5B-9D00-D008E73E0064}'] function GetPeakValue(out pfPeak: Single): HRESULT; stdcall; function GetMeteringChannelCount(out pnChannelCount: UINT): HRESULT; stdcall; function GetChannelsPeakValues(u32ChannelCount: UINT; afPeakValues: pSingle): HRESULT; stdcall; //version 3 function QueryHardwareSupport(out pdwHardwareSupportMask: UINT): HRESULT; stdcall; end;
Etablissement de la connexion:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10 var peak: IAudioMeterInformation = nil; SpeakerTimer: TTimer; ChannelVolumes: array of Single; // ces variables sont prévues pour recevoir les PeakValues des deux canaux, par la méthode GetChannelsPeakValues pChannelVolumes: pSingle; // pointeur sur ChannelVolumes pVolumeOutputL, pVolumeOutputR, pVolume: pinteger; // <=== utilisé pour retourner dynamiquement les peak values deu volume MaxOutput: Integer; device: IMMDevice; deviceEnumerator: IMMDeviceEnumerator; nChannels: UINT;
Fonction cherchant les PeakVolumes:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 function InitSpeakerControl(time, MaxV: integer; poutL, poutR, pVol: pinteger):integer; stdcall; export; var n: integer; begin SpeakerTimer := TTimer.Create(nil); SpeakerTimer.Enabled := False; SpeakerTimer.OnTimer := TDummyForm.Timer1Timer; SpeakerTimer.Interval:= time; MaxOutput := MaxV; pVolumeOutputL := poutL; pVolumeOutputR := poutR; pVolume := pVol; CoCreateInstance(CLASS_IMMDeviceEnumerator, nil, CLSCTX_ALL, IID_IMMDeviceEnumerator, deviceEnumerator); deviceEnumerator.GetDefaultAudioEndpoint(eRender, eConsole, device); device.Activate(IID_IAudioMeterInformation, CLSCTX_ALL, nil, IUnknown(peak)); peak.GetMeteringChannelCount(nChannels); SetLength(ChannelVolumes,nChannels); pChannelVolumes := @ChannelVolumes[0]; // <========== chargement du pointeur SpeakerTimer.Enabled := true; result := 0; end; exports InitSpeakerControl;
Bon, je vais garder la version comme ça. Elle est claire et lisible, et mieux, elle fonctionne.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 // Ceci est la fonction évènement OnTimer du timer créé lors de la mise en route de la surveillance du volume class procedure TDummyForm.Timer1Timer(Sender: TObject); var Temp: Single; // cette variable reçoit la peak value générale, par la méthode GetPeakValue vL, vR, vV: integer; // ce sont des variables techniques pour ajuster les valeurs reçues vers l'intervalle imposé [0..MaxOutput] HR: HResult; // code retour de la méthode GetChannelsPeakValues begin ttimer(sender).Enabled := false; // arrêter le timer, le temps de traiter l'évènement peak.GetPeakValue(Temp); // prendre la valeur instantané du volume global, résultat dans Temp ==> correct ! HR := peak.GetChannelsPeakValues(nChannels,pChannelVolumes); // version 3 opérationnelle if HR<>S_OK then begin if HR=E_INVALIDARG then showmessage('E_INVALIDARG') else if HR=E_POINTER then showmessage('E_POINTER') else showmessage('Erreur '+inttostr(integer(HR))+' = '+inttohex(integer(HR),8)); end; ...
Merci à vous tous pour votre aide. Avec le recul, je pense que l'idée maîtresse était de changer la définition de la méthode de l'interface. Ensuite, n'ayant pas vraiment compris, j'ai mal adapté les paramètres. Maintenant, les choses sont claires.
Je te propose encore un dernier test pour supprimer pChannelVolumes
pointer() n'est pas la récupération d'une adresse (comme c'est le cas avec pSingle()) mais la conversion d'un pointeur typé en pointeur quelconque, donc compatible avec tout type de pointeur.
Code : Sélectionner tout - Visualiser dans une fenêtre à part HR := peak.GetChannelsPeakValues(nChannels, pointer(ChannelVolumes));
Après je te fiche la paix
Ca marche ! Très bien. Le code en est encore plus simple. Je garde cette version.
Et... je suis bien content que tu ne m'aies pas "fichu la paix" jusqu'à maintenant - c'était utile et productif ! Merci !
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager