PC SOFT

FORUMS PROFESSIONNELS
WINDEVWEBDEV et WINDEV Mobile

Accueil → WINDEV 2024 → [WD14] Activation interface USB/midi  (utilisation winmm.dll)
[WD14] Activation interface USB/midi (utilisation winmm.dll)
Débuté par Dominique Durand, 13 nov. 2009 01:25 - 33 réponses
Posté le 13 novembre 2009 - 01:25
Bonjour,
Je teste depuis quelques jours l'appel à l'API Winmm.dll, mais je bloque au delà des fonctions MidiOutOpen et MidiInOpen. J'ai récupéré par la fonction USBRecherche(USBPropriétéNomExplicite, "Midi") l'identifiant du port USB sur une zone définie en chaine sur 100. Les fonctions MidioutOpen et MidiInOpen (retourFonction=API("WINMM.DLL","midiOutOpen",Hmo,0,0,0,0) me retourne un code 0.
Les fonctions midiOutShortMsg, MidiOutClose et MidiInClose me retournent eux un code 5 (Access is denied). Le fait de relancer les fonction Midi..Open qui me donne alors un code erreur 4 (The system cannot open the file) me laisse à penser que l'ouverture des ports était correcte au premier passage. Pourquoi alors les opérations de fermeture ne fonctionnent pas?
Toutes les recherches sur les FAQ, forums et autres n'ont pu m'éclairer sur mon PB.
J'ai essayé également d'envoyer des messages par la fonction "midiOutShortMsg" j'ai un code retour 5 également.

Si vous pouvez m'éclairer, je vous en remercie d'avance.



Mon code de test
retourFonction est un entier // Type C :MMRESULT
sNomexplicite est une chaîne
sDescription est une chaîne
sErreur est une chaîne
sListe est une chaîne
SIDmidi1 est une chaîne sur 100
SIDmidi2 est une chaîne sur 100

Hmo est une chaîne sur 100 //*********** TYPE NON RETROUVE ***********
sHmi est une chaîne sur 100 //*********** TYPE NON RETROUVE ***********
nInd est un entier
sPériphériques est une chaîne = USBRecherche(USBPropriétéNomExplicite, "Midi")
SI sPériphériques <> "" ALORS
SPérif est une chaîne
POUR TOUTE CHAINE SPérif DE sPériphériques SEPAREE PAR RC
nInd++
SELON nInd
CAS 1 : SIDmidi1 = SPérif
CAS 2 : SIDmidi2 = SPérif
AUTRES CAS :
FIN
FIN
FIN

hInst est un entier
hInst = ChargeDLL("WinMM.DLL")
SI hInst = 0 ALORS
Erreur(ErreurInfo())
RETOUR
FIN
Hmo = SIDmidi1
retourFonction=API("WINMM.DLL","midiOutOpen",Hmo,0,0,0,0)
Info ("openout/"+retourFonction+"/"+Hmo)

Hmi = sIDmidi1
retourFonction=API("WINMM.DLL","midiInOpen",Hmi,0,0,0,0)
Info ("openIn/"+retourFonction+"/"+Hmi)

retourFonction=API("WINMM.DLL","midiOutClose",Hmo)
Info ("CloseOut/"+retourFonction+"/"+Hmo)

retourFonction=API("WINMM.DLL","midiInClose",Hmi)
Info ("CloseIn/"+retourFonction+"/"+Hmi)
Posté le 21 novembre 2009 - 09:25
Bon coté MidiOut cela va mieux je réussi à adresser les messages voulus sur plusieurs sorties midi en fonction des besoins.
J'utilise avec des variables type stuctures et entiers les lignes suivantes:
nNbredevs =API("WINMM.DLL","midiOutGetNumDevs")
.....
POUR UDeviceID = 0 A nNbredevs-1
retourFonction=API("WINMM.DLL","midiOutGetDevCapsA",UDeviceID,&pmoc,Taille(&pmoc))
FIN
....
// Ouverture Port Clavier
retourFonction=API("WINMM.DLL","midiOutOpen",&nHmo,gnDeviceOut3,0,0,0)


gnCanal = gnCanalOut3
gnCodePgm = TABLE_T_Programme_Det.COL_Cd_PM_Midi
// message = canal bits 1 à 4
// + C(12)*16 bits 5 à 8 C : codification pour action changement de programme
// + cdpgm * 256 bits 9 à 12
nDwMsg = gnCanal + 192 + (gnCodePgm*256)
retourFonction=API("WINMM.DLL","midiOutShortMsg",nHmo,nDwMsg)

// Fermeture Port Clavier
retourFonction=API("WINMM.DLL","midiOutClose",nHmo)


Reste maintenant à regler le problème de la récupération de messages Midi en IN.
Voici le code que j'ai testé jusqu'à présent:
Une procédure
Procedure MessagemidiIn(Hmi1 est un entier,nUMsg est un entier système,nDw1 est un entier système,nDw2 est un entier système)
Trace("messageMidiIn")

appelée via son adresse comme fonction de rappel et code général suivant:
//********************** Déclaration des structures nécessaires à la fonction de l'API <midiInGetDevCapsA> :
MIDIINCAPSA est une structure
wMid est un entier sur 2 octets //Type C : WORD
wPid est un entier sur 2 octets //Type C : WORD
vDriverVersion est un entier //Type MMVERSION non retrouvé (entier est le type le plus fréquent, mais à VERIFIER)
szPname est une chaîne fixe sur 32 //Type C : CHAR
dwSupport est un entier //Type C : DWORD
FIN
//********************** Fin de la déclaration des structures pour <midiInGetDevCapsA>

nNbredevs est un entier =API("WINMM.DLL","midiInGetNumDevs")

POUR UDeviceID = 0 A nNbredevs-1
retourFonction=API("WINMM.DLL","midiInGetDevCapsA",UDeviceID,&pmic,Taille(&pmic))
FIN
gndeviceIn1 est un entier = 0
gnIDProced est un entier = &MessagemidiIn
retourFonction = API("WINMM.DLL","midiInOpen",&nHmi,gnDeviceIn1,gnIDProced,0,0)
Trace("MidiInOpen/" +retourFonction)
retourFonction = API("WINMM.DLL","midiInStart",nHmi)
Trace("MidiInStart/" +retourFonction)

Les codes retour sont à 0 donc à ce niveau cela semble corret.
Mais je n'ai aucune indication (trace dans la procédure MessagemidiIn) de réception des messages midi qui entre sur le port IN concerné.
J'ai un peu avancé mais là je bloque. L'ecoute du port midi necessite l'activation d'un traitement qui récupère le message, le traite et active des traitements complémentaires mais je prends pas le problème dans le boon sens.
Y a t'il sur le forum un spécialiste des API qui pourrait m'éclairer de son savoir?
Posté le 30 mai 2010 - 00:44
Si vous avez des infos , ça m'arrangerai aussi ;)
j'ai le meme probleme. J'ai essayé la fonction MidiInProc , mais , WD me réponds que c'est inconnu dans la DLL
Posté le 30 mai 2010 - 11:49
Salut Laurent,

MidiInProc n'est pas une fonction qu'on peut appeler par la dll.
Par contre j'ai vu une erreur dans le code de Dominique :
retourFonction = API("WINMM.DLL","midiInOpen",&nHmi,gnDeviceIn1,gnIDProced,0,0)

le dernier paramètre est à zéro (dwflags) ce qui fait qu'on appelle la fonction avec un CALLBACK_NULL
il n'y aura pas de mécanisme de callback donc pas d'exécution de la procédure MessagemidiIn.
Il faut appeler la dll avec comme dernier paramètre CALLBACK_FUNCTION qui a pour valeur 0x30000
donc cela donne :
retourFonction =API("WINMM.DLL","midiInOpen",&nHmi,gnDeviceIn1,gnIDProced,0,0x30000)


je te garantis pas que ça va marcher mais tu peux toujours essayer. Moi je n'ai pas d'interface midi donc je peux pas essayer.

Ami calmant, J.P ;-)
Posté le 30 mai 2010 - 21:20
Merci pour l'info , mais le 0x30000 donne une erreur de syntax.
si je le met entre ", j'ai une erreur de flag 'code10).
Grrrr
Posté le 31 mai 2010 - 09:56
et dans le code de Dominique , et nHmi représente quoi comme variable ?
Posté le 31 mai 2010 - 11:05
bonjour,
il manque des infos dans le code publié de Dominique :

par exemple pmic et pmoc (qui ne sont pas dans un bateau) ne sont pas définis.
je soupçonne qu'ils soient des structures midi in et midi out.
Il faudrait avoir le code complet de Dominique.

Ami calmant, J.P ;-)
Posté le 31 mai 2010 - 13:44
a premiere vue , pmic (et pmoc) sont des variables a structure MIDIINCAPSA. D'après les Refs MSDN ça serait logique.
Par contre , le nombre de device récupéré par midiInGetNumDevs et null chez moi, et je ne vois pas comment atteindre un autre résultat. ce qui fait que le reste ne passe pas puisque pas de device pour le programme.
Ce qui est étonnant , c'est qu'un prog style midi-ox le trouve bien et reçoit les infos
Posté le 31 mai 2010 - 17:27
bon, pouwr l'instant, j'ai bien mon périf, il est vu via midiInGetNumDevs, J'ai un retour de midiGetDevCapsA et le midiInopen fonctionne, par contre , j'ai tjrs pas trouvé la valeur de nHmi qui me permettrait de démarrer midiInStart .

J'ai essayé nHmi est un entier système= &sHmi , mais ça ne donne rien
Si Dominique regarde de temps à autre ce Post , ça serait cool qu'il me donne les définitions de ses valeurs :) comme ça , si ça fonctionne , je pourrais l'aiguillé par la suite :)

Laurent
Posté le 31 mai 2010 - 20:00
bon ben moi j'ai finalement trouvé un PC avec une interface midi j'arrive jusqu'à l'ouverture du port midi mais là je coince sur la procedure de callback .
Quand on ouvre le port midi d'entrée la callback est apparemment appelée et ça crashe. Je vais pas insister car apparemment après ça se complique encore plus.
Au fait pourquoi veux-tu utiliser windev pour la gestion Midi ? il existe des librairies dans d'autres langages et qui sont à un stade très avancés. Par exemple j'ai vu un midi toolkit en .net
Ami calmant, J.P ;-)
Posté le 01 juin 2010 - 01:30
J'ai une application audio ou j'aimerai interface un clavier midi type nanoKey de Korg pour controler le Start et stop de chaque player.

l'application de départ est déjà faite et fonctionne correctement.
Je ne sais pas comment savoir si le callback est correctement appelé chez moi.
je n'ai pas de crash , le résultat du midiInOpen est de 0 , donc ok avec un entier callback qui est défini par "0x30000"

comment as tu mis ton ouverture de callback ?

Laurent
Posté le 01 juin 2010 - 08:54
Je vois que ma question initiale a declenché quelques réactions. J'ai crée sous WD une application qui gère, pour un musicien clavier, la gestion complète de ses besoins. Gestion des partitions des morceaux, et via une interface USB/Midi pilotage de la gestion de sons clavier en fonction des morceaux et celle de l'éclairage par déclenchement associé des scènes programmées dans Daslight. Ces actions sont menées par des commandes midi Out en utilisant plusieurs canaux. Là tout était OK pour moi. Seulement je voulais en plus via une pédale du clavier récuperer sur l'appli des données midi en IN pour gerer par exemple les changements de pages des partitions ou les start/stop de l'éclairage. J'ai calé sur la gestion de l'écoute de canaux midi (IN) et j'ai finalement trouvé une solution bien plus simple par l'utilisation d'une pédale USB en l'associant à un raccourci clavier, lui-même associé à un clic bouton.
Premier concert sans lumière déjà fait et avec lumière samedi prochain.
Je pourrais certainement revenir sur l'aspect d'écoute de canaux midi en IN car cela peu s'avérer malgré tout utile, en tenant compte de vos remarques.
Avec Windev j'ai un peu tendance à développer des trucs perso plutôt en marge. Cela permet de phosphorer un peu.
A+
Posté le 01 juin 2010 - 10:11
bonjour,
bon ça y est la procédure de callback ne plante plus. Voici le code qui marche chez moi mais attention j'ai pas un USB Midi mais un port Joystick Midi.
MidiINCapsa est une structure
wMid est un entier sur 2 octets
wPid est un entier sur 2 octets
vDriverVersion est un entier
szPname est une chaîne ASCIIZ de 32
dwSupport est un entier
FIN
MidiOUTCapsa est une structure
wMid est un entier sur 2 octets
wPid est un entier sur 2 octets
vDriverVersion est un entier
szPname est une chaîne ASCIIZ de 32
wTechnology est un entier sur 2 octets
wVoices est un entier sur 2 octets
wNotes est un entier sur 2 octets
wChannelMask est un entier sur 2 octets
dwSupport est un entier
FIN
retourFonction est un entier // Type C :MMRESULT



nInd est un entier
nNbreOutdevs est un entier
nNbreINdevs est un entier
pmoc est un tableau de 5 MidiOUTCapsa // jusqu'a 5 periph
pmic est un tableau de 5 MidiINCapsa // jusqu'a 5 periph
UDeviceID est un entier


hInst est un entier
hInst = ChargeDLL("WinMM.DLL")
SI hInst = 0 ALORS
Erreur(ErreurInfo())
RETOUR
FIN
nNbreOutdevs =API("WINMM.DLL","midiOutGetNumDevs")
nNbreINdevs =API("WINMM.DLL","midiInGetNumDevs")
POUR UDeviceID = 1 A nNbreOutdevs
retourFonction=API("WINMM.DLL","midiOutGetDevCapsA",UDeviceID-1,&pmoc[UDeviceID],Dimension(pmoc[UDeviceID]))
Trace("sortie Midi : " + pmoc[UDeviceID]:wMid + TAB + pmoc[UDeviceID]:wPid + TAB + pmoc[UDeviceID]:szPName)

FIN
POUR UDeviceID = 1 A nNbreINdevs
retourFonction=API("WINMM.DLL","midiInGetDevCapsA",UDeviceID-1,&pmic[UDeviceID],Dimension(pmic[UDeviceID]))
Trace("entrée Midi : " + pmic[UDeviceID]:wMid + TAB + pmic[UDeviceID]:wPid + TAB + pmic[UDeviceID]:szPName)
FIN
gndeviceIn1 est un entier = 0 // première entrée Midi
nHmi est un entier
nGnIDProced est un entier = &MessagemidiIn // pointeur de la fonction de callback

retourFonction = API("WINMM.DLL","midiInOpen",&nHmi,gndeviceIn1,nGnIDProced,0,0x30020)
Trace("MidiInOpen/" +retourFonction)
retourFonction = API("WINMM.DLL","midiInStart",nHmi)
Trace("MidiInStart/" +retourFonction)


et voici le code de ma procédure de callback :
Procedure MessagemidiIn( hMidiIn, wMsg, dwInstance, dwParam1, dwParam2)

Trace("on passe ici : " + dwParam1 + TAB + dwParam2 )

Mais attention dans la procédure de callback le plus dur reste à faire :
filtrer les événements qui nous interressent.
Sinon avec ce code je reçois les évenements envoyés par un clavier Midi.

Ami Calmant, J.P ;-)
Posté le 01 juin 2010 - 11:21
coool , j'y suis aussi depuis ce matin, je cherche la façon de parser les données du callback :)

Laurent
Posté le 01 juin 2010 - 11:22
fo que je trouve la traduction C vers WD de ceci:

md.mTime = dwParam2;
md.mStatus = (UCHAR)(dwParam1 & 0xFF);
md.mParam1 = (UCHAR)((dwParam1>>8) & 0xFF);
md.mParam2 = (UCHAR)((dwParam1>>16) & 0xFF);

ce qui permettra de parser le param1
Posté le 01 juin 2010 - 15:06
voici le parsing que j'ai et qui fonctionne comme un charme lol


qui me donne de quoi faire toutes mes opérations sur mon programme depuis mon clavier :)
Posté le 01 juin 2010 - 16:14
je n'ai pas besoin de gestion des channels donc, il n'y a rien pour parser le channel
Posté le 12 mai 2012 - 15:55
Bonjour, à vous
Je déterre ce post pour la raison suivante

Je suis entrain , tout en me formant à Windev, de réaliser un logiciel de gestion de partitions musicales.
J'attaque la partie communication avec un clavier des ports Midi

J'ai essayé les différents portions de code citées dans ce post

Le souci que j'ai c'est les descriptions manquante (les constantes et les variable)

Sans vouloir plagier : y aurait-il un code "complet" que je pourrais adapter ?
gestion de sysex à recevoir et a envoyer au clavier
entre autre afficher une partition en appuyant sur un bouton du clavier
envoyer des réglages au clavier en fonction d'une partition affichée

Un grand merci d'avance pour votre aide

NB je suis en W15
Posté le 03 novembre 2013 - 09:00
je relance les bonnes volontés sur le sujet USB/midi

quelqu'un aurait aurait il un bout de code en windev permettant d'adresser les ports midi via USB, ouverture, fermeture, lecture et écritures pour piloter des périphériques midi (synthé, boite à rythmes.... Yamaha, Rolannd...)
une sorte de 'open source" par exemple
bien entendu ce que chacun dévelloperait serait mis en commun pour faire progresser le smilblick

chez pcsoft il est impossible d'obtenir des renseignements précis, on reste dans le vague.

je pense que nous sommes nombreux à nous heurter à ce problème

merci aux bonnes volontés
Posté le 03 novembre 2013 - 21:38
Bonjour,
Voici un morceau de code qui fonctionne pour un changement de banque sons sur un clavier.
le code inclus les commandes sur banques à adresses fixes 1 à 127 type KN6000 et à adresses variables x fois 1 à 8 type Tyros4.
Les éléments du code utile se situent dans différentes procédures :

Définition stockage mémoire dans la procédure du projet
nDwMsg est un entier
nHmo est un entier système
nHmi est un entier système
gnDeviceOut3 est un entier
gnCanal est un entier sur 1
gnCodePgm est un entier sur 2
gnCodeBank est un entier sur 2

Init des canaux de communication ( j'ai le clavier et plusieurs canaux pour les lumières)
CAS 3 : gnCanalOut3 = T_CanalMidi.CD_OUT // Controle Synthetiseur
gnCanalIn3 = T_CanalMidi.CD_IN
gnDeviceOut3 = T_CanalMidi.CD_affect_Int
gnDeviceIn3 = T_CanalMidi.CD_affect_Int
gsLIOption3 = T_CanalMidi.LI_Goupe_Piste

en fin commande de changement de banques
// commande Bank et Panel Clavier
// Gestion des bank fixes (KN6000) et des bank variables (TYROS4)
// Banques Fixes On passe seulement un ordre Changement de programme Valeur midi de 0 à 127)
// Banques variables On passe un ordre Controle Change Changement de banque (B) puis un ordre changement de programme valeur midi de (0 à 7)
// Ouverture Port Clavier
retourFonction=API("WINMM.DLL","midiOutOpen",&nHmo,gnDeviceOut3,0,0,0)

gnCanal = gnCanalOut3
gnCodeBank = Val(TABLE_T_Programme_Det.COL_CD_Banque)
gnCodePgm = TABLE_T_Programme_Det.COL_Cd_PM_Midi
// message = canal bits 1 à 4
// + C(12)*16 bits 5 à 8 C : codification pour action changement de programme B : codification pour action control change
// + cdpgm * 256 bits 9 à 12

// passage commande préliminaire changement de banque pour clavier type Tyros4
SI gnCodeGestionMidi = 2 ALORS
nDwMsg = gnCanal + 176 + (32*256) + ((gnCodeBank-1)*256*256)
retourFonction=API("WINMM.DLL","midiOutShortMsg",nHmo,nDwMsg)
FIN

nDwMsg = gnCanal + 192 + (gnCodePgm*256)
retourFonction=API("WINMM.DLL","midiOutShortMsg",nHmo,nDwMsg)

// Fermeture Port Clavier
retourFonction=API("WINMM.DLL","midiOutClose",nHmo)

Quand j'étais dans le flou pour savoir quelles valeurs passer, j'ai utilisé un petit logiciel Miditest.exe bien pratique.
En espérant que cela vous aidera. En tout cas mon appli en épate quelque uns. Car ma femme tout en jouant peinard qui gère lumières de la scène et les lumières de la piste de danse c'est sympa.
Amicalement.
Dominique
Posté le 28 février 2015 - 09:15
Bonjour, Je reviens sur le sujet
j'ai finalisé mon logiciel de gestion de partitions musicales.Il me manque toujours le traitement des données Midi pour un clavier TYROS (3 4 et 5)
Je souhaites en fonction d'une partition donnée enregistrer les registrations créées afin de pouvoir les restituer lors de l'affichage de la partition
En sachant que le Tyros est connecté en USB

J'ai une partition affichée dans le logiciel
Je crée des registrations sur le Tyros que je sauvegarde
Je voudrais que ces informations soient aussi enregistrées dans mon fichier des partitions pour pouvoir réinjecter ça dans le clavier et ainsi récupérer ces registration
et eventuellement l'inverse
une registration sur le TYROS appelle la partition correspondante

Je donnerai mon logiciel à la personne qui me filera un coup de main (avec le source si elle le souhaite)

Merci d'avance
Posté le 28 février 2015 - 17:54
Bonjour,
J'ai crée une application pour épouse qui utilise actuellement un Tyros 4. Avant elle avait un KN6000.
Cette application est unique et complète car non seulement elle gère l'activation des registrations enregistré, selon que la mémoire du clavier soit de type variable (Tyros4) ou fixe (KN6000) mais aussi des paramètres sur une table de mixage numérique, des programmes de lumières en commandant Daslight ouvert sur le même PC et contient un petit développement de type "DJ" avec pilotage de l'éclairage aussi. Les morceaux sont enregistrés avec des partitions éventuellement multi-pages le déroulé des pages étant en paramétrage libre pour chaque morceau et le changement de page étant fait par une touche raccourci, qui peut être associée à une pédale USB (ce qui plus pratique).
Le problème est que je fonctionnement entièrement en midi pour toute ses fonctionnalités avec une interface USB/Midi à 4 entrée et sortie midi Prodipe. Je n'ai pas étudié comment passer les infos par connexion USB directe.
Je vais me pencher aussi sur la question.
Posté le 01 mars 2015 - 14:47
Bonjour Dominique,

Je te remercie de te pencher sur le sujet, En effet mon appli gère surtout des partitions musicales

Je sais faire jouer des notes au clavier mais ce qui serait intéressant pour moi c'est de récupérer les infos MIDI émises par le tyros lors de l'exécution d'un registre car je suppose que dans un fichier RGT ce sont des infos midi qui sont stockées ? Il suffirait donc de les réinjecter dans le tyros pour simuler le choix d'une registration
Ma partition sachant ou est stocké le fichier rgt correspondant sur le disque du tyros

Donc mon souci : Lire le contenu d'un RGT et l'injecter dans le Tyros ou d'un fichier STYLE
Posté le 27 juin 2015 - 18:35
Bonjour Dominique,

Cette application est unique et complète car non seulement
elle gère l'activation des registrations enregistré, selon que la mémoire du clavier soit de type variable (Tyros4) ou fixe (KN6000) -- C'est cette partie que je voudrais intégrer dans mon logiciel ----

je fonctionnement entièrement en midi pour toute ses fonctionnalités avec une interface USB/Midi à 4 entrée et sortie midi Prodipe. --- J'ai vu le prix d'une interface Prodipe , ce n'est pas trop honéreux donc je pourrais intégrer ça comme contrainte si on veux utiliser l'option activation registre depuis partition. ----

Serais-tu d'accord de me passer le code qui gère cette partie, car malgré mes recherches je suis bloqué,

Je peux te passer une version de mon logiciel si tu le souhaites

Merci d'avance
Posté le 29 juin 2015 - 20:34
Bonjour,
Je peux te passer le code sans soucis, mais sur la réponse de 11/2013 j'avais mis l'essentiel, mais il vrai que pour des raisons un peu obscures j'ai géré le IN/OUT de l'interface de manière indirecte, avec 4 ensembles de paramètres (gnDeviceOut3 par exemple) mais qui ne correspondent spécialement au IN/OUT de l'interface. C'est une table (T_Canalmidi) qui donne le N° de IN/Out de l'interface. Si gnDeviceOut3 = 3 les signaux midi seront envoyés via la OUT3 de l'interface.
Avec une seule série de paramètres cela marchera aussi bien.
Si tu mets 1 dans un "gnDeviceOut" tu activeras la sortie OUT1 de l'interface , 2 la sortie OUT2 ... etc.

Sur l'interface midi prodipe 4In/Out il y a un paramétrage qui permet plusieurs mode IN/Out dont 1 standard avec indépendance complète. Je fonctionne dans cette configuration (par exemple pour commander Daslight via un flux mon appli envoi un code via l'USB sur le port 1 il sort donc en OUT1 sur l'interface. Pour activer Daslight qui tourne sur le même PC j'ai simplement branché le cable midi sortant du OUT1 sur le IN1.
Pour le clavier j'utilise la sortie OUT3 donc gnDeviceOut3 = 3
En recopiant le bout de code de mon post du 3/11 tu devrais y arrivé sans problème.
Pour ne pas avoir de problème de saturation de la mémoire de l'interface il faut à chaque ouvrir le port puis le fermer après envoi du message. Dans mon post toutes ces opération sont notées.
Attention aussi pour les canaux, j'ai noté que sur certains appareils il faut "ajuster le canal" on envoie par exemple canal 3 il reçoit la valeur 4. Si on a paramétré sur appareil canal 3 cela ne marche pas. Il faut donc envoyer canal 3-1.
Pour des infos plus détaillées, si nécessaire, il faudrait peut-être passer par un canal plus direct de communication.
Pour ton logiciel ... il peut être intéressant, mais mon épouse ne fonctionne pas vraiment avec des partitions et un rythme pré programmé. Ils sont 3 dont un batteur.
Posté le 30 juin 2015 - 11:59
Bonjour Dominique,

Merci pour tes infos complémentaires,

Je vais essayer ,

Pour le code je veux bien, car sans tout utiliser le code , la lecture du code écrit par un développeur permet toujours de progresser , dans la façon d'écrire et dans les techniques.J'ai constaté ça au cours de mes 40 ans d'informatique !

Je te transmettrai le mien également via dropBox ou équivalent, tu trouveras peut-être quelques trucs intéressants.
Je m'engage bien sûr à ne pas diffuser tes sources.
Pour une communication en plus direct je ne sais pas trop comment faire , je ne sais pas si on peut mettre une adresse mail dans les posts.

En tout cas merci.
Posté le 30 juin 2015 - 19:06
Contactes-te moi sur ma messagerie d.h.durand@orange.fr.
Posté le 11 septembre 2015 - 20:22
Bonjour,

Pour compléter le sujet , j'ai maintenant un code qui fonctionne bien

//**********************************************************************************************************
Procedure ChargeInfosMidiOUT(gnCanalOut,gnBanque,gnBankRGT,gnNumPrg)
//**********************************************************************************************************
// AppelRegistrationTyros(gnDeviceOUT,gnCanalOUT,gnCodeBank,gnCodePgm)
// Récupération des infos MIDI et Banque à charger
// Parametres à passer : BanqueDepart,CanalMidi,Banque,Registre,Programme

// Pour construire les ordres MIDI

//---------------------------------------------------------------------------------------------------------
// 1- CONTROL CHANGE 0:Valeur 0
//---------------------------------------------------------------------------------------------------------
nCONTROL_CHANGE_INIT= CONTROL_CHANGE * 256
SAI_ResCCInit = CONTROL_CHANGE * 256
SAI_HexaCCInit = EntierVersHexa(SAI_ResCCInit,2)
//---------------------------------------------------------------------------------------------------------
// 2- CANAL D'ENVOI OUT : Program Change 32Valeur de 1 à 16
//---------------------------------------------------------------------------------------------------------
nPROGRAM_CHANGE_CANAL = PROGRAM_CHANGE + gnCanalOut*256
SAI_ResCanal = PROGRAM_CHANGE + gnCanalOut*256
SAI_PrgCanal = EntierVersHexa(SAI_ResCanal,2)
//---------------------------------------------------------------------------------------------------------
// 3- CHARGER BANK DE REGISTRES: Control Change + Bank Valeur 0 à 4
//---------------------------------------------------------------------------------------------------------
nPROGRAM_CHANGE_BANQUE= CONTROL_CHANGE + (BANK_CHANGE*256)+ ((gnBanque) * 256*256)
SAI_ResCC_CB = CONTROL_CHANGE + (BANK_CHANGE*256)+ ((gnBanque) * 256*256)
SAI_ControlChange = EntierVersHexa(SAI_ResCC_CB,2)

//---------------------------------------------------------------------------------------------------------
// 4- CHARGER REGISTRATION: Control Change + Change Program + N° de Registration Valeur de 0 à 128
//---------------------------------------------------------------------------------------------------------
// Il faut faire -1 car la table a une numérotation de 1 à 128
nCONTROLCHANGE_CHANGEPROG_RGT= CONTROL_CHANGE + (BANK_CHANGE*256) + ((gnBankRGT) * 256*256)
SAI_ResChBank = CONTROL_CHANGE + (BANK_CHANGE*256) + ((gnBankRGT) * 256*256)
SAI_ChangeBank = EntierVersHexa(SAI_ResChBank,2)
SAI_NumBanque = gnBankRGT
SAI_RGT= gnBankRGT
//----------------------------------------------------------------------------------------------------------
// 5- CHANGER N DE PROGRAMME DANS LA REGISTRATION
//----------------------------------------------------------------------------------------------------------
nPROGRAM_CHANGE_PRG= PROGRAM_CHANGE + (gnNumPrg - 1)*256
SAI_ResChRgt = PROGRAM_CHANGE + (gnNumPrg - 1)*256
SAI_ChangeRgt = EntierVersHexa(SAI_ResChRgt,2)
SAI_NumRgt = gnNumPrg - 1
SAI_RGT_Prg = gnNumPrg - 1

//************************************************************************************************************
Procedure ChargeRegistrationSurClavier()
//************************************************************************************************************
RGT_OuvreMidiOUT()
RGT_ActiveCanalOUT()
Sleep(100)
RGT_ChangeBanque()
Sleep(100)
RGT_ChangeRegistration()
Sleep(100)
RGT_ChangeProgramme()
Sleep(100)
RGT_FermeMidiOut()

//************************************************************************************************************
Procedure RGT_OuvreMidiOUT()
//************************************************************************************************************
sMesAff est une chaîne
sMesAff = "Port MIDI: " + gnDeviceOut + " Canal: " +gnCanalOut
InitCodesRetourFonctionsMIDI()
gnRetmidiOutOpen= API("WINMM.DLL","midiOutOpen",&gnHMidi,gnDeviceOut,0,0,0)// Ouverture Port clavier

//************************************************************************************************************
Procedure RGT_ActiveCanalOUT()
//************************************************************************************************************
// 1- CONTROL CHANGE
//------------------------------------------------------------------------------------------------------------
gnRetCC= API("WINMM.DLL","midiOutShortMsg",gnHMidi,SAI_ResCCInit)
//Trace(Complète(gnCanalOut,8," ") + " = (" + SAI_HexaCCInit + ")" )
SAI_RetCC = gnRetCC
SI SAI_RetCC <> 0 ALORS
SAI_RetCC..Couleur = RougeFoncé
SINON
SAI_RetCC..Couleur = VertFoncé
FIN
//------------------------------------------------------------------------------------------------------
// 2- ACTIVATION DU CANAL MIDI OUT
//------------------------------------------------------------------------------------------------------
gnRetChangeCanal= API("WINMM.DLL","midiOutShortMsg",gnHMidi,SAI_ResCanal)
//Trace(Complète(gnCanalOut,8," ") + " = (" + SAI_PrgCanal + ")")
SAI_RetChoixCanal = gnRetChangeCanal
SI SAI_RetChoixCanal <> 0 ALORS
SAI_RetChoixCanal..Couleur = RougeFoncé
SINON
SAI_RetChoixCanal..Couleur = VertFoncé
FIN

//************************************************************************************************************
Procedure RGT_ChangeBanque()
//************************************************************************************************************
// 3- Envoyer un Control Change + un Bank Change ( Banque 0 à 4 pour 500 registrations)
//--------------------------------------------------------------------------------------------------------------
gnRetChangeBank= API("WINMM.DLL","midiOutShortMsg",gnHMidi,SAI_ResChBank)
SAI_RetControleChange = gnRetChangeBank
SI SAI_RetControleChange <> 0 ALORS
SAI_RetControleChange..Couleur = RougeFoncé
SINON
SAI_RetControleChange..Couleur = VertFoncé
FIN

//************************************************************************************************************
Procedure RGT_ChangeRegistration()
//************************************************************************************************************
gnRetChangeRGT = API("WINMM.DLL","midiOutShortMsg",gnHMidi,SAI_ResChRgt)
//Trace(Complète(gnBankRGT,8," ") + " = (" + SAI_ChangeBank + ")" )
SAI_RetChangeBank= gnRetChangeRGT
SI SAI_RetChangeBank <> 0 ALORS
SAI_RetChangeBank..Couleur = RougeFoncé
SINON
SAI_RetChangeBank..Couleur = VertFoncé
FIN

//************************************************************************************************************
Procedure RGT_ChangeProgramme()
//************************************************************************************************************
// 5- CHOIX DU PROGRAMME DANS LA REGISTRATION : Valeur 0 à 7 (On fait -1 sur le choix 1 à 8)
//-------------------------------------------------------------------------------------------------------------
gnRetChangePrg = API("WINMM.DLL","midiOutShortMsg",gnHMidi,SAI_ResChRgt)
//Trace(Complète(gnNumPrg,8," ") + " = (" + SAI_ChangeRgt + ")" )
SAI_RetChangeRGT = gnRetChangePrg
SI SAI_RetChangeRGT <> 0 ALORS
SAI_RetChangeRGT..Couleur = RougeFoncé
SINON
SAI_RetChangeRGT..Couleur = VertFoncé
FIN

//************************************************************************************************************
Procedure RGT_FermeMidiOut()
//************************************************************************************************************
// FERMETURE DU PORT CLAVIER
//-------------------------------------------------------------------------------------------
gnRetmidiOutClose= API("WINMM.DLL","midiOutClose",gnHMidi)

//Trace("-------------------------------------------------------------- " )
//Trace("FERMETURE DU PORT OUT")
SAI_RetmidiOutClose = gnRetmidiOutClose
SI SAI_RetmidiOutClose <> 0 ALORS
SAI_RetmidiOutClose..Couleur = RougeFoncé
SINON
SAI_RetmidiOutClose..Couleur = VertFoncé
FIN



Maintenant je voudrais traiter la partie Midi IN : Recevoir un code Sysex en provenance du clavier (Un Numero de partition) envoyé lorsque j'apuie sur une touche registration (Qui contient un sysex)

voici les procédures que j'ai : Je ne sais pas comment décoder ce que je reçois, dans toutes ces infos il faudrait que je trouve une info du type
F0 05 01 02 03 04 F7 <-- Numéro d'une partition que je vois bien passer dans MidiOX

//********************************************************************************************
Procedure MidiIN_Start(nDevice est un entier)
//********************************************************************************************
RetFonc est un entier
RetFoncStart est un entier// première entrée Midi
nCbmh est un entier sans signe
nRetFoncBuff est un entier
nGnIDProced est un entier système = &MidiInCalBak // pointeur de la fonction de callback

BTN_CaptureMidi..Visible = Faux// Pour ne pas ouvrir plusieurs à la fois et ne pas planter
ListeMidiIN..Visible = Faux

// On lance l'écoute du driver sélectionné

RetFonc = API("WINMM.DLL","midiInOpen",&ri,nDevice, &MidiInCalBak,0,CALLBACK_FUNCTION)
RetFoncStart = API("WINMM.DLL","midiInStart",ri) // On démarre l'écoute


// nRetFoncBuff=API("WINMM.DLL","midiInAddBuffer",ri,&gPmh,cbmh)

LIB_Message..Libellé = "Sysex -> J'attend le sysex..."

//*************************************************************************************************************************
Procedure MidiInCalBak( nHMidiIn est entier, nWMsg est entier, nDwInstance est entier, dwParam1 est entier système, nDwparam2 est entier)
//*************************************************************************************************************************
ValeurRetour est entier
mimdata est une chaîne
sMsg est une chaîne
sParam2Hexa est une chaîne
sByte0, sByte1, sByte2, sByte3 sont des chaînes

// Infos transmises pour verification
SAI_nHMidiIn = nHMidiIn
SAI_nWMsg = nWMsg

SAI_nDwInstance = nDwInstance

SAI_dwParam1= dwParam1
SAI_dwParam2= nDwparam2

gnInfoCallBack1= dwParam1
gnParam2CallBack= nDwparam2
gnNUMsg= nWMsg
gnInstance= nDwInstance

SELON nWMsg
CAS MM_MIM_OPEN
LIB_Message= "MidiIn Open"

CAS MM_MIM_CLOSE

CAS MM_MIM_DATA // code 963
LIB_Message = "DATA RECEIVED"

// je passe ici
// Décoder quoi ?

IF dwParam1 > 0 ALORS
//sMsg = Gauche("00000000" + DecToHexa(dwParam1), 8)
sMsg = Gauche(Droite("00000000" + DecToHexa(dwParam1), 8), 6)
gnInfoCallBack1= dwParam1
gnInfoCallBackHexa = sMsg
// Pack the data into a Long variable

sByte3 = Milieu(gnInfoCallBackHexa, 7, 2)// Byte 3 = 00
SI sByte3 = "" ALORS
sByte3 = "00"
FIN
sByte2 = Milieu(gnInfoCallBackHexa, 5, 2)// Byte 2 = Volume
sByte1 = Milieu(gnInfoCallBackHexa, 3, 2)// Byte 1 = Note
sByte0 = Milieu(gnInfoCallBackHexa, 1, 2)// Byte 0 (LSB) = Status
mimdata = sByte0 + " - " + sByte1 + " - "+sByte2+ " - "+ sByte3
sMsg = dwParam1
MidiInDemo.Text1= sMsg
MidiInDemo.Text2= mimdata
SAI_Param1Hexa = mimdata
END

sParam2Hexa = Gauche(Droite("00000000" + DecToHexa(nDwparam2),8), 8)
// Pack the data into a Long variable
sByte3 = Milieu(sParam2Hexa, 7, 2)// Byte 3 = 00
SI sByte3 = "" ALORS
sByte3 = "00"
FIN

sByte2 = Milieu(sParam2Hexa, 5, 2)// Byte 2 = Volume
sByte1 = Milieu(sParam2Hexa, 3, 2)// Byte 1 = Note
sByte0 = Milieu(sParam2Hexa, 1, 2)// Byte 0 (LSB) = Status
mimdata = sByte0 + " - " + sByte1 + " - "+sByte2+ " - "+ sByte3
SAI_Param2Hexa = mimdata

CAS MM_MIM_LONGDATA // code 964
LIB_Message = "LONG DATA RECEIVED"
CAS MM_MIM_ERROR
LIB_Message = "ERROR"
CAS MM_MIM_LONGERROR
LIB_Message = "LONGERROR"
AUTRE CAS
FIN

SI dwParam1 > 255 ALORS // Si dw1 > 255 : Pour ne prendre en compte que les touches appuyées et pas le tempo
//sMsg = Gauche("00000000" + DecToHexa(dwParam1), 8)

gnInfoCallBackHexa = Gauche(Droite("00000000" + DecToHexa(dwParam1), 8), 6)
SAI_Param1Hexa = gnInfoCallBackHexa

// Pack the data into a Long variable

sByte3 = Milieu(gnInfoCallBackHexa, 7, 2)// Byte 3 = 00
SI sByte3 = "" ALORS
sByte3 = "00"
FIN

sByte2 = Milieu(gnInfoCallBackHexa, 5, 2)// Byte 2 = Volume
sByte1 = Milieu(gnInfoCallBackHexa, 3, 2)// Byte 1 = Note
sByte0 = Milieu(gnInfoCallBackHexa, 1, 2)// Byte 0 (LSB) = Status
mimdata = sByte0 + " " + sByte1 + " "+sByte2+ " "+ sByte3
sMsg = dwParam1
MidiInDemo.Text1= sMsg
MidiInDemo.Text2= mimdata
//Récupération Note Jouée
gnNoteJouée= Gauche(Val(gnInfoCallBackHexa,"x"), 2)
MidiInDemo.Text4= gnNoteJouée
SINON
gnInfoCallBackHexa = Gauche(Droite("00000000" + DecToHexa(dwParam1), 8), 6)
// Pack the data into a Long variable

sByte3 = Milieu(gnInfoCallBackHexa, 7, 2)// Byte 3 = 00
SI sByte3 = "" ALORS
sByte3 = "00"
FIN

sByte2 = Milieu(gnInfoCallBackHexa, 5, 2)// Byte 2 = Volume
sByte1 = Milieu(gnInfoCallBackHexa, 3, 2)// Byte 1 = Note
sByte0 = Milieu(gnInfoCallBackHexa, 1, 2)// Byte 0 (LSB) = Status
mimdata = sByte0 + " - " + sByte1 + " - "+sByte2+ " - "+ sByte3
MidiInDemo.Text1B = mimdata
FIN

//*********************************************************************************
Procedure StopCapture()
//*********************************************************************************

nRetFonc est un entier

// on veut quitter
nRetFonc = API("WINMM.DLL","midiInReset",ri) // on réinitialise
nRetFonc= API("WINMM.DLL","midiInStop",ri)
nRetFonc= API("WINMM.DLL","midiInClose",ri)


Je vais bien dans la CALLBACK mais ????????????
Il doit y avoir un filtre à mettre 0xF9 , FILTER_ACTIVE_SENSE (0xFE) et FILTER_CLOCK (0xF8)
J'ai vu ça dans des procédures en VB qui urtilisais l'OCX Mabry

Si quelqu'un peut avancer le schmilblic ça serait sympa

Merci d'avance
Posté le 11 septembre 2015 - 20:22
Bonjour,

Pour compléter le sujet , j'ai maintenant un code qui fonctionne bien

//**********************************************************************************************************
Procedure ChargeInfosMidiOUT(gnCanalOut,gnBanque,gnBankRGT,gnNumPrg)
//**********************************************************************************************************
// AppelRegistrationTyros(gnDeviceOUT,gnCanalOUT,gnCodeBank,gnCodePgm)
// Récupération des infos MIDI et Banque à charger
// Parametres à passer : BanqueDepart,CanalMidi,Banque,Registre,Programme

// Pour construire les ordres MIDI

//---------------------------------------------------------------------------------------------------------
// 1- CONTROL CHANGE 0:Valeur 0
//---------------------------------------------------------------------------------------------------------
nCONTROL_CHANGE_INIT= CONTROL_CHANGE * 256
SAI_ResCCInit = CONTROL_CHANGE * 256
SAI_HexaCCInit = EntierVersHexa(SAI_ResCCInit,2)
//---------------------------------------------------------------------------------------------------------
// 2- CANAL D'ENVOI OUT : Program Change 32Valeur de 1 à 16
//---------------------------------------------------------------------------------------------------------
nPROGRAM_CHANGE_CANAL = PROGRAM_CHANGE + gnCanalOut*256
SAI_ResCanal = PROGRAM_CHANGE + gnCanalOut*256
SAI_PrgCanal = EntierVersHexa(SAI_ResCanal,2)
//---------------------------------------------------------------------------------------------------------
// 3- CHARGER BANK DE REGISTRES: Control Change + Bank Valeur 0 à 4
//---------------------------------------------------------------------------------------------------------
nPROGRAM_CHANGE_BANQUE= CONTROL_CHANGE + (BANK_CHANGE*256)+ ((gnBanque) * 256*256)
SAI_ResCC_CB = CONTROL_CHANGE + (BANK_CHANGE*256)+ ((gnBanque) * 256*256)
SAI_ControlChange = EntierVersHexa(SAI_ResCC_CB,2)

//---------------------------------------------------------------------------------------------------------
// 4- CHARGER REGISTRATION: Control Change + Change Program + N° de Registration Valeur de 0 à 128
//---------------------------------------------------------------------------------------------------------
// Il faut faire -1 car la table a une numérotation de 1 à 128
nCONTROLCHANGE_CHANGEPROG_RGT= CONTROL_CHANGE + (BANK_CHANGE*256) + ((gnBankRGT) * 256*256)
SAI_ResChBank = CONTROL_CHANGE + (BANK_CHANGE*256) + ((gnBankRGT) * 256*256)
SAI_ChangeBank = EntierVersHexa(SAI_ResChBank,2)
SAI_NumBanque = gnBankRGT
SAI_RGT= gnBankRGT
//----------------------------------------------------------------------------------------------------------
// 5- CHANGER N DE PROGRAMME DANS LA REGISTRATION
//----------------------------------------------------------------------------------------------------------
nPROGRAM_CHANGE_PRG= PROGRAM_CHANGE + (gnNumPrg - 1)*256
SAI_ResChRgt = PROGRAM_CHANGE + (gnNumPrg - 1)*256
SAI_ChangeRgt = EntierVersHexa(SAI_ResChRgt,2)
SAI_NumRgt = gnNumPrg - 1
SAI_RGT_Prg = gnNumPrg - 1

//************************************************************************************************************
Procedure ChargeRegistrationSurClavier()
//************************************************************************************************************
RGT_OuvreMidiOUT()
RGT_ActiveCanalOUT()
Sleep(100)
RGT_ChangeBanque()
Sleep(100)
RGT_ChangeRegistration()
Sleep(100)
RGT_ChangeProgramme()
Sleep(100)
RGT_FermeMidiOut()

//************************************************************************************************************
Procedure RGT_OuvreMidiOUT()
//************************************************************************************************************
sMesAff est une chaîne
sMesAff = "Port MIDI: " + gnDeviceOut + " Canal: " +gnCanalOut
InitCodesRetourFonctionsMIDI()
gnRetmidiOutOpen= API("WINMM.DLL","midiOutOpen",&gnHMidi,gnDeviceOut,0,0,0)// Ouverture Port clavier

//************************************************************************************************************
Procedure RGT_ActiveCanalOUT()
//************************************************************************************************************
// 1- CONTROL CHANGE
//------------------------------------------------------------------------------------------------------------
gnRetCC= API("WINMM.DLL","midiOutShortMsg",gnHMidi,SAI_ResCCInit)
//Trace(Complète(gnCanalOut,8," ") + " = (" + SAI_HexaCCInit + ")" )
SAI_RetCC = gnRetCC
SI SAI_RetCC <> 0 ALORS
SAI_RetCC..Couleur = RougeFoncé
SINON
SAI_RetCC..Couleur = VertFoncé
FIN
//------------------------------------------------------------------------------------------------------
// 2- ACTIVATION DU CANAL MIDI OUT
//------------------------------------------------------------------------------------------------------
gnRetChangeCanal= API("WINMM.DLL","midiOutShortMsg",gnHMidi,SAI_ResCanal)
//Trace(Complète(gnCanalOut,8," ") + " = (" + SAI_PrgCanal + ")")
SAI_RetChoixCanal = gnRetChangeCanal
SI SAI_RetChoixCanal <> 0 ALORS
SAI_RetChoixCanal..Couleur = RougeFoncé
SINON
SAI_RetChoixCanal..Couleur = VertFoncé
FIN

//************************************************************************************************************
Procedure RGT_ChangeBanque()
//************************************************************************************************************
// 3- Envoyer un Control Change + un Bank Change ( Banque 0 à 4 pour 500 registrations)
//--------------------------------------------------------------------------------------------------------------
gnRetChangeBank= API("WINMM.DLL","midiOutShortMsg",gnHMidi,SAI_ResChBank)
SAI_RetControleChange = gnRetChangeBank
SI SAI_RetControleChange <> 0 ALORS
SAI_RetControleChange..Couleur = RougeFoncé
SINON
SAI_RetControleChange..Couleur = VertFoncé
FIN

//************************************************************************************************************
Procedure RGT_ChangeRegistration()
//************************************************************************************************************
gnRetChangeRGT = API("WINMM.DLL","midiOutShortMsg",gnHMidi,SAI_ResChRgt)
//Trace(Complète(gnBankRGT,8," ") + " = (" + SAI_ChangeBank + ")" )
SAI_RetChangeBank= gnRetChangeRGT
SI SAI_RetChangeBank <> 0 ALORS
SAI_RetChangeBank..Couleur = RougeFoncé
SINON
SAI_RetChangeBank..Couleur = VertFoncé
FIN

//************************************************************************************************************
Procedure RGT_ChangeProgramme()
//************************************************************************************************************
// 5- CHOIX DU PROGRAMME DANS LA REGISTRATION : Valeur 0 à 7 (On fait -1 sur le choix 1 à 8)
//-------------------------------------------------------------------------------------------------------------
gnRetChangePrg = API("WINMM.DLL","midiOutShortMsg",gnHMidi,SAI_ResChRgt)
//Trace(Complète(gnNumPrg,8," ") + " = (" + SAI_ChangeRgt + ")" )
SAI_RetChangeRGT = gnRetChangePrg
SI SAI_RetChangeRGT <> 0 ALORS
SAI_RetChangeRGT..Couleur = RougeFoncé
SINON
SAI_RetChangeRGT..Couleur = VertFoncé
FIN

//************************************************************************************************************
Procedure RGT_FermeMidiOut()
//************************************************************************************************************
// FERMETURE DU PORT CLAVIER
//-------------------------------------------------------------------------------------------
gnRetmidiOutClose= API("WINMM.DLL","midiOutClose",gnHMidi)

//Trace("-------------------------------------------------------------- " )
//Trace("FERMETURE DU PORT OUT")
SAI_RetmidiOutClose = gnRetmidiOutClose
SI SAI_RetmidiOutClose <> 0 ALORS
SAI_RetmidiOutClose..Couleur = RougeFoncé
SINON
SAI_RetmidiOutClose..Couleur = VertFoncé
FIN



Maintenant je voudrais traiter la partie Midi IN : Recevoir un code Sysex en provenance du clavier (Un Numero de partition) envoyé lorsque j'apuie sur une touche registration (Qui contient un sysex)

voici les procédures que j'ai : Je ne sais pas comment décoder ce que je reçois, dans toutes ces infos il faudrait que je trouve une info du type
F0 05 01 02 03 04 F7 <-- Numéro d'une partition que je vois bien passer dans MidiOX

//********************************************************************************************
Procedure MidiIN_Start(nDevice est un entier)
//********************************************************************************************
RetFonc est un entier
RetFoncStart est un entier// première entrée Midi
nCbmh est un entier sans signe
nRetFoncBuff est un entier
nGnIDProced est un entier système = &MidiInCalBak // pointeur de la fonction de callback

BTN_CaptureMidi..Visible = Faux// Pour ne pas ouvrir plusieurs à la fois et ne pas planter
ListeMidiIN..Visible = Faux

// On lance l'écoute du driver sélectionné

RetFonc = API("WINMM.DLL","midiInOpen",&ri,nDevice, &MidiInCalBak,0,CALLBACK_FUNCTION)
RetFoncStart = API("WINMM.DLL","midiInStart",ri) // On démarre l'écoute


// nRetFoncBuff=API("WINMM.DLL","midiInAddBuffer",ri,&gPmh,cbmh)

LIB_Message..Libellé = "Sysex -> J'attend le sysex..."

//*************************************************************************************************************************
Procedure MidiInCalBak( nHMidiIn est entier, nWMsg est entier, nDwInstance est entier, dwParam1 est entier système, nDwparam2 est entier)
//*************************************************************************************************************************
ValeurRetour est entier
mimdata est une chaîne
sMsg est une chaîne
sParam2Hexa est une chaîne
sByte0, sByte1, sByte2, sByte3 sont des chaînes

// Infos transmises pour verification
SAI_nHMidiIn = nHMidiIn
SAI_nWMsg = nWMsg

SAI_nDwInstance = nDwInstance

SAI_dwParam1= dwParam1
SAI_dwParam2= nDwparam2

gnInfoCallBack1= dwParam1
gnParam2CallBack= nDwparam2
gnNUMsg= nWMsg
gnInstance= nDwInstance

SELON nWMsg
CAS MM_MIM_OPEN
LIB_Message= "MidiIn Open"

CAS MM_MIM_CLOSE

CAS MM_MIM_DATA // code 963
LIB_Message = "DATA RECEIVED"

// je passe ici
// Décoder quoi ?

IF dwParam1 > 0 ALORS
//sMsg = Gauche("00000000" + DecToHexa(dwParam1), 8)
sMsg = Gauche(Droite("00000000" + DecToHexa(dwParam1), 8), 6)
gnInfoCallBack1= dwParam1
gnInfoCallBackHexa = sMsg
// Pack the data into a Long variable

sByte3 = Milieu(gnInfoCallBackHexa, 7, 2)// Byte 3 = 00
SI sByte3 = "" ALORS
sByte3 = "00"
FIN
sByte2 = Milieu(gnInfoCallBackHexa, 5, 2)// Byte 2 = Volume
sByte1 = Milieu(gnInfoCallBackHexa, 3, 2)// Byte 1 = Note
sByte0 = Milieu(gnInfoCallBackHexa, 1, 2)// Byte 0 (LSB) = Status
mimdata = sByte0 + " - " + sByte1 + " - "+sByte2+ " - "+ sByte3
sMsg = dwParam1
MidiInDemo.Text1= sMsg
MidiInDemo.Text2= mimdata
SAI_Param1Hexa = mimdata
END

sParam2Hexa = Gauche(Droite("00000000" + DecToHexa(nDwparam2),8), 8)
// Pack the data into a Long variable
sByte3 = Milieu(sParam2Hexa, 7, 2)// Byte 3 = 00
SI sByte3 = "" ALORS
sByte3 = "00"
FIN

sByte2 = Milieu(sParam2Hexa, 5, 2)// Byte 2 = Volume
sByte1 = Milieu(sParam2Hexa, 3, 2)// Byte 1 = Note
sByte0 = Milieu(sParam2Hexa, 1, 2)// Byte 0 (LSB) = Status
mimdata = sByte0 + " - " + sByte1 + " - "+sByte2+ " - "+ sByte3
SAI_Param2Hexa = mimdata

CAS MM_MIM_LONGDATA // code 964
LIB_Message = "LONG DATA RECEIVED"
CAS MM_MIM_ERROR
LIB_Message = "ERROR"
CAS MM_MIM_LONGERROR
LIB_Message = "LONGERROR"
AUTRE CAS
FIN

SI dwParam1 > 255 ALORS // Si dw1 > 255 : Pour ne prendre en compte que les touches appuyées et pas le tempo
//sMsg = Gauche("00000000" + DecToHexa(dwParam1), 8)

gnInfoCallBackHexa = Gauche(Droite("00000000" + DecToHexa(dwParam1), 8), 6)
SAI_Param1Hexa = gnInfoCallBackHexa

// Pack the data into a Long variable

sByte3 = Milieu(gnInfoCallBackHexa, 7, 2)// Byte 3 = 00
SI sByte3 = "" ALORS
sByte3 = "00"
FIN

sByte2 = Milieu(gnInfoCallBackHexa, 5, 2)// Byte 2 = Volume
sByte1 = Milieu(gnInfoCallBackHexa, 3, 2)// Byte 1 = Note
sByte0 = Milieu(gnInfoCallBackHexa, 1, 2)// Byte 0 (LSB) = Status
mimdata = sByte0 + " " + sByte1 + " "+sByte2+ " "+ sByte3
sMsg = dwParam1
MidiInDemo.Text1= sMsg
MidiInDemo.Text2= mimdata
//Récupération Note Jouée
gnNoteJouée= Gauche(Val(gnInfoCallBackHexa,"x"), 2)
MidiInDemo.Text4= gnNoteJouée
SINON
gnInfoCallBackHexa = Gauche(Droite("00000000" + DecToHexa(dwParam1), 8), 6)
// Pack the data into a Long variable

sByte3 = Milieu(gnInfoCallBackHexa, 7, 2)// Byte 3 = 00
SI sByte3 = "" ALORS
sByte3 = "00"
FIN

sByte2 = Milieu(gnInfoCallBackHexa, 5, 2)// Byte 2 = Volume
sByte1 = Milieu(gnInfoCallBackHexa, 3, 2)// Byte 1 = Note
sByte0 = Milieu(gnInfoCallBackHexa, 1, 2)// Byte 0 (LSB) = Status
mimdata = sByte0 + " - " + sByte1 + " - "+sByte2+ " - "+ sByte3
MidiInDemo.Text1B = mimdata
FIN

//*********************************************************************************
Procedure StopCapture()
//*********************************************************************************

nRetFonc est un entier

// on veut quitter
nRetFonc = API("WINMM.DLL","midiInReset",ri) // on réinitialise
nRetFonc= API("WINMM.DLL","midiInStop",ri)
nRetFonc= API("WINMM.DLL","midiInClose",ri)


Je vais bien dans la CALLBACK mais ????????????
Il doit y avoir un filtre à mettre 0xF9 , FILTER_ACTIVE_SENSE (0xFE) et FILTER_CLOCK (0xF8)
J'ai vu ça dans des procédures en VB qui urtilisais l'OCX Mabry

Si quelqu'un peut avancer le schmilblic ça serait sympa

Merci d'avance
Posté le 11 septembre 2015 - 20:22
Bonjour,

Pour compléter le sujet , j'ai maintenant un code qui fonctionne bien

//**********************************************************************************************************
Procedure ChargeInfosMidiOUT(gnCanalOut,gnBanque,gnBankRGT,gnNumPrg)
//**********************************************************************************************************
// AppelRegistrationTyros(gnDeviceOUT,gnCanalOUT,gnCodeBank,gnCodePgm)
// Récupération des infos MIDI et Banque à charger
// Parametres à passer : BanqueDepart,CanalMidi,Banque,Registre,Programme

// Pour construire les ordres MIDI

//---------------------------------------------------------------------------------------------------------
// 1- CONTROL CHANGE 0:Valeur 0
//---------------------------------------------------------------------------------------------------------
nCONTROL_CHANGE_INIT= CONTROL_CHANGE * 256
SAI_ResCCInit = CONTROL_CHANGE * 256
SAI_HexaCCInit = EntierVersHexa(SAI_ResCCInit,2)
//---------------------------------------------------------------------------------------------------------
// 2- CANAL D'ENVOI OUT : Program Change 32Valeur de 1 à 16
//---------------------------------------------------------------------------------------------------------
nPROGRAM_CHANGE_CANAL = PROGRAM_CHANGE + gnCanalOut*256
SAI_ResCanal = PROGRAM_CHANGE + gnCanalOut*256
SAI_PrgCanal = EntierVersHexa(SAI_ResCanal,2)
//---------------------------------------------------------------------------------------------------------
// 3- CHARGER BANK DE REGISTRES: Control Change + Bank Valeur 0 à 4
//---------------------------------------------------------------------------------------------------------
nPROGRAM_CHANGE_BANQUE= CONTROL_CHANGE + (BANK_CHANGE*256)+ ((gnBanque) * 256*256)
SAI_ResCC_CB = CONTROL_CHANGE + (BANK_CHANGE*256)+ ((gnBanque) * 256*256)
SAI_ControlChange = EntierVersHexa(SAI_ResCC_CB,2)

//---------------------------------------------------------------------------------------------------------
// 4- CHARGER REGISTRATION: Control Change + Change Program + N° de Registration Valeur de 0 à 128
//---------------------------------------------------------------------------------------------------------
// Il faut faire -1 car la table a une numérotation de 1 à 128
nCONTROLCHANGE_CHANGEPROG_RGT= CONTROL_CHANGE + (BANK_CHANGE*256) + ((gnBankRGT) * 256*256)
SAI_ResChBank = CONTROL_CHANGE + (BANK_CHANGE*256) + ((gnBankRGT) * 256*256)
SAI_ChangeBank = EntierVersHexa(SAI_ResChBank,2)
SAI_NumBanque = gnBankRGT
SAI_RGT= gnBankRGT
//----------------------------------------------------------------------------------------------------------
// 5- CHANGER N DE PROGRAMME DANS LA REGISTRATION
//----------------------------------------------------------------------------------------------------------
nPROGRAM_CHANGE_PRG= PROGRAM_CHANGE + (gnNumPrg - 1)*256
SAI_ResChRgt = PROGRAM_CHANGE + (gnNumPrg - 1)*256
SAI_ChangeRgt = EntierVersHexa(SAI_ResChRgt,2)
SAI_NumRgt = gnNumPrg - 1
SAI_RGT_Prg = gnNumPrg - 1

//************************************************************************************************************
Procedure ChargeRegistrationSurClavier()
//************************************************************************************************************
RGT_OuvreMidiOUT()
RGT_ActiveCanalOUT()
Sleep(100)
RGT_ChangeBanque()
Sleep(100)
RGT_ChangeRegistration()
Sleep(100)
RGT_ChangeProgramme()
Sleep(100)
RGT_FermeMidiOut()

//************************************************************************************************************
Procedure RGT_OuvreMidiOUT()
//************************************************************************************************************
sMesAff est une chaîne
sMesAff = "Port MIDI: " + gnDeviceOut + " Canal: " +gnCanalOut
InitCodesRetourFonctionsMIDI()
gnRetmidiOutOpen= API("WINMM.DLL","midiOutOpen",&gnHMidi,gnDeviceOut,0,0,0)// Ouverture Port clavier

//************************************************************************************************************
Procedure RGT_ActiveCanalOUT()
//************************************************************************************************************
// 1- CONTROL CHANGE
//------------------------------------------------------------------------------------------------------------
gnRetCC= API("WINMM.DLL","midiOutShortMsg",gnHMidi,SAI_ResCCInit)
//Trace(Complète(gnCanalOut,8," ") + " = (" + SAI_HexaCCInit + ")" )
SAI_RetCC = gnRetCC
SI SAI_RetCC <> 0 ALORS
SAI_RetCC..Couleur = RougeFoncé
SINON
SAI_RetCC..Couleur = VertFoncé
FIN
//------------------------------------------------------------------------------------------------------
// 2- ACTIVATION DU CANAL MIDI OUT
//------------------------------------------------------------------------------------------------------
gnRetChangeCanal= API("WINMM.DLL","midiOutShortMsg",gnHMidi,SAI_ResCanal)
//Trace(Complète(gnCanalOut,8," ") + " = (" + SAI_PrgCanal + ")")
SAI_RetChoixCanal = gnRetChangeCanal
SI SAI_RetChoixCanal <> 0 ALORS
SAI_RetChoixCanal..Couleur = RougeFoncé
SINON
SAI_RetChoixCanal..Couleur = VertFoncé
FIN

//************************************************************************************************************
Procedure RGT_ChangeBanque()
//************************************************************************************************************
// 3- Envoyer un Control Change + un Bank Change ( Banque 0 à 4 pour 500 registrations)
//--------------------------------------------------------------------------------------------------------------
gnRetChangeBank= API("WINMM.DLL","midiOutShortMsg",gnHMidi,SAI_ResChBank)
SAI_RetControleChange = gnRetChangeBank
SI SAI_RetControleChange <> 0 ALORS
SAI_RetControleChange..Couleur = RougeFoncé
SINON
SAI_RetControleChange..Couleur = VertFoncé
FIN

//************************************************************************************************************
Procedure RGT_ChangeRegistration()
//************************************************************************************************************
gnRetChangeRGT = API("WINMM.DLL","midiOutShortMsg",gnHMidi,SAI_ResChRgt)
//Trace(Complète(gnBankRGT,8," ") + " = (" + SAI_ChangeBank + ")" )
SAI_RetChangeBank= gnRetChangeRGT
SI SAI_RetChangeBank <> 0 ALORS
SAI_RetChangeBank..Couleur = RougeFoncé
SINON
SAI_RetChangeBank..Couleur = VertFoncé
FIN

//************************************************************************************************************
Procedure RGT_ChangeProgramme()
//************************************************************************************************************
// 5- CHOIX DU PROGRAMME DANS LA REGISTRATION : Valeur 0 à 7 (On fait -1 sur le choix 1 à 8)
//-------------------------------------------------------------------------------------------------------------
gnRetChangePrg = API("WINMM.DLL","midiOutShortMsg",gnHMidi,SAI_ResChRgt)
//Trace(Complète(gnNumPrg,8," ") + " = (" + SAI_ChangeRgt + ")" )
SAI_RetChangeRGT = gnRetChangePrg
SI SAI_RetChangeRGT <> 0 ALORS
SAI_RetChangeRGT..Couleur = RougeFoncé
SINON
SAI_RetChangeRGT..Couleur = VertFoncé
FIN

//************************************************************************************************************
Procedure RGT_FermeMidiOut()
//************************************************************************************************************
// FERMETURE DU PORT CLAVIER
//-------------------------------------------------------------------------------------------
gnRetmidiOutClose= API("WINMM.DLL","midiOutClose",gnHMidi)

//Trace("-------------------------------------------------------------- " )
//Trace("FERMETURE DU PORT OUT")
SAI_RetmidiOutClose = gnRetmidiOutClose
SI SAI_RetmidiOutClose <> 0 ALORS
SAI_RetmidiOutClose..Couleur = RougeFoncé
SINON
SAI_RetmidiOutClose..Couleur = VertFoncé
FIN



Maintenant je voudrais traiter la partie Midi IN : Recevoir un code Sysex en provenance du clavier (Un Numero de partition) envoyé lorsque j'apuie sur une touche registration (Qui contient un sysex)

voici les procédures que j'ai : Je ne sais pas comment décoder ce que je reçois, dans toutes ces infos il faudrait que je trouve une info du type
F0 05 01 02 03 04 F7 <-- Numéro d'une partition que je vois bien passer dans MidiOX

//********************************************************************************************
Procedure MidiIN_Start(nDevice est un entier)
//********************************************************************************************
RetFonc est un entier
RetFoncStart est un entier// première entrée Midi
nCbmh est un entier sans signe
nRetFoncBuff est un entier
nGnIDProced est un entier système = &MidiInCalBak // pointeur de la fonction de callback

BTN_CaptureMidi..Visible = Faux// Pour ne pas ouvrir plusieurs à la fois et ne pas planter
ListeMidiIN..Visible = Faux

// On lance l'écoute du driver sélectionné

RetFonc = API("WINMM.DLL","midiInOpen",&ri,nDevice, &MidiInCalBak,0,CALLBACK_FUNCTION)
RetFoncStart = API("WINMM.DLL","midiInStart",ri) // On démarre l'écoute


// nRetFoncBuff=API("WINMM.DLL","midiInAddBuffer",ri,&gPmh,cbmh)

LIB_Message..Libellé = "Sysex -> J'attend le sysex..."

//*************************************************************************************************************************
Procedure MidiInCalBak( nHMidiIn est entier, nWMsg est entier, nDwInstance est entier, dwParam1 est entier système, nDwparam2 est entier)
//*************************************************************************************************************************
ValeurRetour est entier
mimdata est une chaîne
sMsg est une chaîne
sParam2Hexa est une chaîne
sByte0, sByte1, sByte2, sByte3 sont des chaînes

// Infos transmises pour verification
SAI_nHMidiIn = nHMidiIn
SAI_nWMsg = nWMsg

SAI_nDwInstance = nDwInstance

SAI_dwParam1= dwParam1
SAI_dwParam2= nDwparam2

gnInfoCallBack1= dwParam1
gnParam2CallBack= nDwparam2
gnNUMsg= nWMsg
gnInstance= nDwInstance

SELON nWMsg
CAS MM_MIM_OPEN
LIB_Message= "MidiIn Open"

CAS MM_MIM_CLOSE

CAS MM_MIM_DATA // code 963
LIB_Message = "DATA RECEIVED"

// je passe ici
// Décoder quoi ?

IF dwParam1 > 0 ALORS
//sMsg = Gauche("00000000" + DecToHexa(dwParam1), 8)
sMsg = Gauche(Droite("00000000" + DecToHexa(dwParam1), 8), 6)
gnInfoCallBack1= dwParam1
gnInfoCallBackHexa = sMsg
// Pack the data into a Long variable

sByte3 = Milieu(gnInfoCallBackHexa, 7, 2)// Byte 3 = 00
SI sByte3 = "" ALORS
sByte3 = "00"
FIN
sByte2 = Milieu(gnInfoCallBackHexa, 5, 2)// Byte 2 = Volume
sByte1 = Milieu(gnInfoCallBackHexa, 3, 2)// Byte 1 = Note
sByte0 = Milieu(gnInfoCallBackHexa, 1, 2)// Byte 0 (LSB) = Status
mimdata = sByte0 + " - " + sByte1 + " - "+sByte2+ " - "+ sByte3
sMsg = dwParam1
MidiInDemo.Text1= sMsg
MidiInDemo.Text2= mimdata
SAI_Param1Hexa = mimdata
END

sParam2Hexa = Gauche(Droite("00000000" + DecToHexa(nDwparam2),8), 8)
// Pack the data into a Long variable
sByte3 = Milieu(sParam2Hexa, 7, 2)// Byte 3 = 00
SI sByte3 = "" ALORS
sByte3 = "00"
FIN

sByte2 = Milieu(sParam2Hexa, 5, 2)// Byte 2 = Volume
sByte1 = Milieu(sParam2Hexa, 3, 2)// Byte 1 = Note
sByte0 = Milieu(sParam2Hexa, 1, 2)// Byte 0 (LSB) = Status
mimdata = sByte0 + " - " + sByte1 + " - "+sByte2+ " - "+ sByte3
SAI_Param2Hexa = mimdata

CAS MM_MIM_LONGDATA // code 964
LIB_Message = "LONG DATA RECEIVED"
CAS MM_MIM_ERROR
LIB_Message = "ERROR"
CAS MM_MIM_LONGERROR
LIB_Message = "LONGERROR"
AUTRE CAS
FIN

SI dwParam1 > 255 ALORS // Si dw1 > 255 : Pour ne prendre en compte que les touches appuyées et pas le tempo
//sMsg = Gauche("00000000" + DecToHexa(dwParam1), 8)

gnInfoCallBackHexa = Gauche(Droite("00000000" + DecToHexa(dwParam1), 8), 6)
SAI_Param1Hexa = gnInfoCallBackHexa

// Pack the data into a Long variable

sByte3 = Milieu(gnInfoCallBackHexa, 7, 2)// Byte 3 = 00
SI sByte3 = "" ALORS
sByte3 = "00"
FIN

sByte2 = Milieu(gnInfoCallBackHexa, 5, 2)// Byte 2 = Volume
sByte1 = Milieu(gnInfoCallBackHexa, 3, 2)// Byte 1 = Note
sByte0 = Milieu(gnInfoCallBackHexa, 1, 2)// Byte 0 (LSB) = Status
mimdata = sByte0 + " " + sByte1 + " "+sByte2+ " "+ sByte3
sMsg = dwParam1
MidiInDemo.Text1= sMsg
MidiInDemo.Text2= mimdata
//Récupération Note Jouée
gnNoteJouée= Gauche(Val(gnInfoCallBackHexa,"x"), 2)
MidiInDemo.Text4= gnNoteJouée
SINON
gnInfoCallBackHexa = Gauche(Droite("00000000" + DecToHexa(dwParam1), 8), 6)
// Pack the data into a Long variable

sByte3 = Milieu(gnInfoCallBackHexa, 7, 2)// Byte 3 = 00
SI sByte3 = "" ALORS
sByte3 = "00"
FIN

sByte2 = Milieu(gnInfoCallBackHexa, 5, 2)// Byte 2 = Volume
sByte1 = Milieu(gnInfoCallBackHexa, 3, 2)// Byte 1 = Note
sByte0 = Milieu(gnInfoCallBackHexa, 1, 2)// Byte 0 (LSB) = Status
mimdata = sByte0 + " - " + sByte1 + " - "+sByte2+ " - "+ sByte3
MidiInDemo.Text1B = mimdata
FIN

//*********************************************************************************
Procedure StopCapture()
//*********************************************************************************

nRetFonc est un entier

// on veut quitter
nRetFonc = API("WINMM.DLL","midiInReset",ri) // on réinitialise
nRetFonc= API("WINMM.DLL","midiInStop",ri)
nRetFonc= API("WINMM.DLL","midiInClose",ri)


Je vais bien dans la CALLBACK mais ????????????
Il doit y avoir un filtre à mettre 0xF9 , FILTER_ACTIVE_SENSE (0xFE) et FILTER_CLOCK (0xF8)
J'ai vu ça dans des procédures en VB qui urtilisais l'OCX Mabry

Si quelqu'un peut avancer le schmilblic ça serait sympa

Merci d'avance
Posté le 11 septembre 2015 - 20:23
Bonjour,

Pour compléter le sujet , j'ai maintenant un code qui fonctionne bien

//**********************************************************************************************************
Procedure ChargeInfosMidiOUT(gnCanalOut,gnBanque,gnBankRGT,gnNumPrg)
//**********************************************************************************************************
// AppelRegistrationTyros(gnDeviceOUT,gnCanalOUT,gnCodeBank,gnCodePgm)
// Récupération des infos MIDI et Banque à charger
// Parametres à passer : BanqueDepart,CanalMidi,Banque,Registre,Programme

// Pour construire les ordres MIDI

//---------------------------------------------------------------------------------------------------------
// 1- CONTROL CHANGE 0:Valeur 0
//---------------------------------------------------------------------------------------------------------
nCONTROL_CHANGE_INIT= CONTROL_CHANGE * 256
SAI_ResCCInit = CONTROL_CHANGE * 256
SAI_HexaCCInit = EntierVersHexa(SAI_ResCCInit,2)
//---------------------------------------------------------------------------------------------------------
// 2- CANAL D'ENVOI OUT : Program Change 32Valeur de 1 à 16
//---------------------------------------------------------------------------------------------------------
nPROGRAM_CHANGE_CANAL = PROGRAM_CHANGE + gnCanalOut*256
SAI_ResCanal = PROGRAM_CHANGE + gnCanalOut*256
SAI_PrgCanal = EntierVersHexa(SAI_ResCanal,2)
//---------------------------------------------------------------------------------------------------------
// 3- CHARGER BANK DE REGISTRES: Control Change + Bank Valeur 0 à 4
//---------------------------------------------------------------------------------------------------------
nPROGRAM_CHANGE_BANQUE= CONTROL_CHANGE + (BANK_CHANGE*256)+ ((gnBanque) * 256*256)
SAI_ResCC_CB = CONTROL_CHANGE + (BANK_CHANGE*256)+ ((gnBanque) * 256*256)
SAI_ControlChange = EntierVersHexa(SAI_ResCC_CB,2)

//---------------------------------------------------------------------------------------------------------
// 4- CHARGER REGISTRATION: Control Change + Change Program + N° de Registration Valeur de 0 à 128
//---------------------------------------------------------------------------------------------------------
// Il faut faire -1 car la table a une numérotation de 1 à 128
nCONTROLCHANGE_CHANGEPROG_RGT= CONTROL_CHANGE + (BANK_CHANGE*256) + ((gnBankRGT) * 256*256)
SAI_ResChBank = CONTROL_CHANGE + (BANK_CHANGE*256) + ((gnBankRGT) * 256*256)
SAI_ChangeBank = EntierVersHexa(SAI_ResChBank,2)
SAI_NumBanque = gnBankRGT
SAI_RGT= gnBankRGT
//----------------------------------------------------------------------------------------------------------
// 5- CHANGER N DE PROGRAMME DANS LA REGISTRATION
//----------------------------------------------------------------------------------------------------------
nPROGRAM_CHANGE_PRG= PROGRAM_CHANGE + (gnNumPrg - 1)*256
SAI_ResChRgt = PROGRAM_CHANGE + (gnNumPrg - 1)*256
SAI_ChangeRgt = EntierVersHexa(SAI_ResChRgt,2)
SAI_NumRgt = gnNumPrg - 1
SAI_RGT_Prg = gnNumPrg - 1

//************************************************************************************************************
Procedure ChargeRegistrationSurClavier()
//************************************************************************************************************
RGT_OuvreMidiOUT()
RGT_ActiveCanalOUT()
Sleep(100)
RGT_ChangeBanque()
Sleep(100)
RGT_ChangeRegistration()
Sleep(100)
RGT_ChangeProgramme()
Sleep(100)
RGT_FermeMidiOut()

//************************************************************************************************************
Procedure RGT_OuvreMidiOUT()
//************************************************************************************************************
sMesAff est une chaîne
sMesAff = "Port MIDI: " + gnDeviceOut + " Canal: " +gnCanalOut
InitCodesRetourFonctionsMIDI()
gnRetmidiOutOpen= API("WINMM.DLL","midiOutOpen",&gnHMidi,gnDeviceOut,0,0,0)// Ouverture Port clavier

//************************************************************************************************************
Procedure RGT_ActiveCanalOUT()
//************************************************************************************************************
// 1- CONTROL CHANGE
//------------------------------------------------------------------------------------------------------------
gnRetCC= API("WINMM.DLL","midiOutShortMsg",gnHMidi,SAI_ResCCInit)
//Trace(Complète(gnCanalOut,8," ") + " = (" + SAI_HexaCCInit + ")" )
SAI_RetCC = gnRetCC
SI SAI_RetCC <> 0 ALORS
SAI_RetCC..Couleur = RougeFoncé
SINON
SAI_RetCC..Couleur = VertFoncé
FIN
//------------------------------------------------------------------------------------------------------
// 2- ACTIVATION DU CANAL MIDI OUT
//------------------------------------------------------------------------------------------------------
gnRetChangeCanal= API("WINMM.DLL","midiOutShortMsg",gnHMidi,SAI_ResCanal)
//Trace(Complète(gnCanalOut,8," ") + " = (" + SAI_PrgCanal + ")")
SAI_RetChoixCanal = gnRetChangeCanal
SI SAI_RetChoixCanal <> 0 ALORS
SAI_RetChoixCanal..Couleur = RougeFoncé
SINON
SAI_RetChoixCanal..Couleur = VertFoncé
FIN

//************************************************************************************************************
Procedure RGT_ChangeBanque()
//************************************************************************************************************
// 3- Envoyer un Control Change + un Bank Change ( Banque 0 à 4 pour 500 registrations)
//--------------------------------------------------------------------------------------------------------------
gnRetChangeBank= API("WINMM.DLL","midiOutShortMsg",gnHMidi,SAI_ResChBank)
SAI_RetControleChange = gnRetChangeBank
SI SAI_RetControleChange <> 0 ALORS
SAI_RetControleChange..Couleur = RougeFoncé
SINON
SAI_RetControleChange..Couleur = VertFoncé
FIN

//************************************************************************************************************
Procedure RGT_ChangeRegistration()
//************************************************************************************************************
gnRetChangeRGT = API("WINMM.DLL","midiOutShortMsg",gnHMidi,SAI_ResChRgt)
//Trace(Complète(gnBankRGT,8," ") + " = (" + SAI_ChangeBank + ")" )
SAI_RetChangeBank= gnRetChangeRGT
SI SAI_RetChangeBank <> 0 ALORS
SAI_RetChangeBank..Couleur = RougeFoncé
SINON
SAI_RetChangeBank..Couleur = VertFoncé
FIN

//************************************************************************************************************
Procedure RGT_ChangeProgramme()
//************************************************************************************************************
// 5- CHOIX DU PROGRAMME DANS LA REGISTRATION : Valeur 0 à 7 (On fait -1 sur le choix 1 à 8)
//-------------------------------------------------------------------------------------------------------------
gnRetChangePrg = API("WINMM.DLL","midiOutShortMsg",gnHMidi,SAI_ResChRgt)
//Trace(Complète(gnNumPrg,8," ") + " = (" + SAI_ChangeRgt + ")" )
SAI_RetChangeRGT = gnRetChangePrg
SI SAI_RetChangeRGT <> 0 ALORS
SAI_RetChangeRGT..Couleur = RougeFoncé
SINON
SAI_RetChangeRGT..Couleur = VertFoncé
FIN

//************************************************************************************************************
Procedure RGT_FermeMidiOut()
//************************************************************************************************************
// FERMETURE DU PORT CLAVIER
//-------------------------------------------------------------------------------------------
gnRetmidiOutClose= API("WINMM.DLL","midiOutClose",gnHMidi)

//Trace("-------------------------------------------------------------- " )
//Trace("FERMETURE DU PORT OUT")
SAI_RetmidiOutClose = gnRetmidiOutClose
SI SAI_RetmidiOutClose <> 0 ALORS
SAI_RetmidiOutClose..Couleur = RougeFoncé
SINON
SAI_RetmidiOutClose..Couleur = VertFoncé
FIN



Maintenant je voudrais traiter la partie Midi IN : Recevoir un code Sysex en provenance du clavier (Un Numero de partition) envoyé lorsque j'apuie sur une touche registration (Qui contient un sysex)

voici les procédures que j'ai : Je ne sais pas comment décoder ce que je reçois, dans toutes ces infos il faudrait que je trouve une info du type
F0 05 01 02 03 04 F7 <-- Numéro d'une partition que je vois bien passer dans MidiOX

//********************************************************************************************
Procedure MidiIN_Start(nDevice est un entier)
//********************************************************************************************
RetFonc est un entier
RetFoncStart est un entier// première entrée Midi
nCbmh est un entier sans signe
nRetFoncBuff est un entier
nGnIDProced est un entier système = &MidiInCalBak // pointeur de la fonction de callback

BTN_CaptureMidi..Visible = Faux// Pour ne pas ouvrir plusieurs à la fois et ne pas planter
ListeMidiIN..Visible = Faux

// On lance l'écoute du driver sélectionné

RetFonc = API("WINMM.DLL","midiInOpen",&ri,nDevice, &MidiInCalBak,0,CALLBACK_FUNCTION)
RetFoncStart = API("WINMM.DLL","midiInStart",ri) // On démarre l'écoute


// nRetFoncBuff=API("WINMM.DLL","midiInAddBuffer",ri,&gPmh,cbmh)

LIB_Message..Libellé = "Sysex -> J'attend le sysex..."

//*************************************************************************************************************************
Procedure MidiInCalBak( nHMidiIn est entier, nWMsg est entier, nDwInstance est entier, dwParam1 est entier système, nDwparam2 est entier)
//*************************************************************************************************************************
ValeurRetour est entier
mimdata est une chaîne
sMsg est une chaîne
sParam2Hexa est une chaîne
sByte0, sByte1, sByte2, sByte3 sont des chaînes

// Infos transmises pour verification
SAI_nHMidiIn = nHMidiIn
SAI_nWMsg = nWMsg

SAI_nDwInstance = nDwInstance

SAI_dwParam1= dwParam1
SAI_dwParam2= nDwparam2

gnInfoCallBack1= dwParam1
gnParam2CallBack= nDwparam2
gnNUMsg= nWMsg
gnInstance= nDwInstance

SELON nWMsg
CAS MM_MIM_OPEN
LIB_Message= "MidiIn Open"

CAS MM_MIM_CLOSE

CAS MM_MIM_DATA // code 963
LIB_Message = "DATA RECEIVED"

// je passe ici
// Décoder quoi ?

IF dwParam1 > 0 ALORS
//sMsg = Gauche("00000000" + DecToHexa(dwParam1), 8)
sMsg = Gauche(Droite("00000000" + DecToHexa(dwParam1), 8), 6)
gnInfoCallBack1= dwParam1
gnInfoCallBackHexa = sMsg
// Pack the data into a Long variable

sByte3 = Milieu(gnInfoCallBackHexa, 7, 2)// Byte 3 = 00
SI sByte3 = "" ALORS
sByte3 = "00"
FIN
sByte2 = Milieu(gnInfoCallBackHexa, 5, 2)// Byte 2 = Volume
sByte1 = Milieu(gnInfoCallBackHexa, 3, 2)// Byte 1 = Note
sByte0 = Milieu(gnInfoCallBackHexa, 1, 2)// Byte 0 (LSB) = Status
mimdata = sByte0 + " - " + sByte1 + " - "+sByte2+ " - "+ sByte3
sMsg = dwParam1
MidiInDemo.Text1= sMsg
MidiInDemo.Text2= mimdata
SAI_Param1Hexa = mimdata
END

sParam2Hexa = Gauche(Droite("00000000" + DecToHexa(nDwparam2),8), 8)
// Pack the data into a Long variable
sByte3 = Milieu(sParam2Hexa, 7, 2)// Byte 3 = 00
SI sByte3 = "" ALORS
sByte3 = "00"
FIN

sByte2 = Milieu(sParam2Hexa, 5, 2)// Byte 2 = Volume
sByte1 = Milieu(sParam2Hexa, 3, 2)// Byte 1 = Note
sByte0 = Milieu(sParam2Hexa, 1, 2)// Byte 0 (LSB) = Status
mimdata = sByte0 + " - " + sByte1 + " - "+sByte2+ " - "+ sByte3
SAI_Param2Hexa = mimdata

CAS MM_MIM_LONGDATA // code 964
LIB_Message = "LONG DATA RECEIVED"
CAS MM_MIM_ERROR
LIB_Message = "ERROR"
CAS MM_MIM_LONGERROR
LIB_Message = "LONGERROR"
AUTRE CAS
FIN

SI dwParam1 > 255 ALORS // Si dw1 > 255 : Pour ne prendre en compte que les touches appuyées et pas le tempo
//sMsg = Gauche("00000000" + DecToHexa(dwParam1), 8)

gnInfoCallBackHexa = Gauche(Droite("00000000" + DecToHexa(dwParam1), 8), 6)
SAI_Param1Hexa = gnInfoCallBackHexa

// Pack the data into a Long variable

sByte3 = Milieu(gnInfoCallBackHexa, 7, 2)// Byte 3 = 00
SI sByte3 = "" ALORS
sByte3 = "00"
FIN

sByte2 = Milieu(gnInfoCallBackHexa, 5, 2)// Byte 2 = Volume
sByte1 = Milieu(gnInfoCallBackHexa, 3, 2)// Byte 1 = Note
sByte0 = Milieu(gnInfoCallBackHexa, 1, 2)// Byte 0 (LSB) = Status
mimdata = sByte0 + " " + sByte1 + " "+sByte2+ " "+ sByte3
sMsg = dwParam1
MidiInDemo.Text1= sMsg
MidiInDemo.Text2= mimdata
//Récupération Note Jouée
gnNoteJouée= Gauche(Val(gnInfoCallBackHexa,"x"), 2)
MidiInDemo.Text4= gnNoteJouée
SINON
gnInfoCallBackHexa = Gauche(Droite("00000000" + DecToHexa(dwParam1), 8), 6)
// Pack the data into a Long variable

sByte3 = Milieu(gnInfoCallBackHexa, 7, 2)// Byte 3 = 00
SI sByte3 = "" ALORS
sByte3 = "00"
FIN

sByte2 = Milieu(gnInfoCallBackHexa, 5, 2)// Byte 2 = Volume
sByte1 = Milieu(gnInfoCallBackHexa, 3, 2)// Byte 1 = Note
sByte0 = Milieu(gnInfoCallBackHexa, 1, 2)// Byte 0 (LSB) = Status
mimdata = sByte0 + " - " + sByte1 + " - "+sByte2+ " - "+ sByte3
MidiInDemo.Text1B = mimdata
FIN

//*********************************************************************************
Procedure StopCapture()
//*********************************************************************************

nRetFonc est un entier

// on veut quitter
nRetFonc = API("WINMM.DLL","midiInReset",ri) // on réinitialise
nRetFonc= API("WINMM.DLL","midiInStop",ri)
nRetFonc= API("WINMM.DLL","midiInClose",ri)


Je vais bien dans la CALLBACK mais ????????????
Il doit y avoir un filtre à mettre 0xF9 , FILTER_ACTIVE_SENSE (0xFE) et FILTER_CLOCK (0xF8)
J'ai vu ça dans des procédures en VB qui urtilisais l'OCX Mabry

Si quelqu'un peut avancer le schmilblic ça serait sympa

Merci d'avance
Posté le 21 novembre 2015 - 07:24
Jurassic Pork a écrit :
Salut Laurent,

MidiInProc n'est pas une fonction qu'on peut appeler par la dll.
Par contre j'ai vu une erreur dans le code de Dominique :
retourFonction = API("WINMM.DLL","midiInOpen",&nHmi,gnDeviceIn1,gnIDProced,0,0)

le dernier paramètre est à zéro (dwflags) ce qui fait qu'on appelle la fonction avec un CALLBACK_NULL
il n'y aura pas de mécanisme de callback donc pas d'exécution de la procédure MessagemidiIn.
Il faut appeler la dll avec comme dernier paramètre CALLBACK_FUNCTION qui a pour valeur 0x30000
donc cela donne :
retourFonction =API("WINMM.DLL","midiInOpen",&nHmi,gnDeviceIn1,gnIDProced,0,0x30000)


je te garantis pas que ça va marcher mais tu peux toujours essayer. Moi je n'ai pas d'interface midi donc je peux pas essayer.

Ami calmant, J.P ;-)
Posté le 23 novembre 2015 - 13:34
Bonjour,
Je reviens sur le sujet MIDIIn : Procédure CallBack

Je suis toujours à la recherche d'un bout de code qui permet de décortiquer les contenus de Param1 et param2

Dans MIDIOx je vois passer l'info que je dois récupérer c'est une infosysex du Type F0 05 01 02 03 04 F7 et je veux récupérer 1234 qui est le n° d'une partition

Merci aux spécialistes MIDI et WINDEV
Posté le 27 juin 2016 - 10:59
Bonjour tout le monde,
Je revient sur le sujet "Envoi de messages sur le Midi OUT

Je cherche a envoyer un sysex vers un clavier Yamaha (Tyros 5) - pour faire monter un style avec le code suivant
sSysexEnvoi est une chaîne = TABLE_StylesTyros5.COL_Sysex[TABLE_StylesTyros5] // Sysex a envoyer contient : F0 43 73 01 51 05 00 03 04 00 00 1C 6F F7
// Il faut transformer la chaine en byte
nLongueur est un int = Dimension(sSysexEnvoi)
tabByteArray est un tableau de nLongueur entier sur 1

K est un int

FOR K = 1 TO nLongueur
tabByteArray[K] = Asc(Milieu(sSysexEnvoi, K, 1))
END

//For i est un entier = 1 To nLongueur
// System.Runtime.InteropServices.Marshal.WriteByte(hdr.lpData, i, CByte(Val("&h" & ss(i)))) //mscorlib
// utiliser transfert(&cible,&source,longueur) pour remplacer cette ligne ?
// Next


nCodeSysex est un entier = TABLE_StylesTyros5.COL_CodeStyle[TABLE_StylesTyros5]
sYMH_MSG est une chaîne // Yamaha SysEx ID
nResultat,nResultat1,nResultat2 est un entier

STMIDIHDR est une structure
DataPtr est une chaîne // Address of MIDI data
BufferLength est un entier sur 8 // Size of the buffer
BytesRecorded est un entier sur 8 // Actual amount of data in the buffer. This value should be less than or equalto the value given in the dwBufferLength member
MhdrID est un entier sur 8 // Custom user data
Flags est un entier sur 8 // Flags giving information about the buffer
lpNext est un entier sur 8 // Reserved - do not use
Reserved2 est un entier sur 8 // Reserved - do not use
CallbackOffset est un entier //Type C : DWORD offset into Buffer WHEN callback is performed
Reserved3a est un entier sur 8 octets //Type C : DWORD
Reserved3b est un entier sur 8 octets //Type C : DWORD
Reserved3c est un entier sur 8 octets //Type C : DWORD
Reserved3d est un entier sur 8 octets //Type C : DWORD
FIN

MidiInHdr est un tableau fixe de NumSysexBuffers STMIDIHDR /// Pour recuperer les messages sur Midi IN

hMidiIn est un entier
stHdr est un STMIDIHDR

nSize est un entier = Taille(sSysexEnvoi)
nCONTROL_CHANGE_INIT = CONTROL_CHANGE * 256
nPROGRAM_CHANGE_CANAL = PROGRAM_CHANGE + gnCanalOut*256

gnRetmidiOutOpen = API("WINMM.DLL","midiOutOpen",&gnHMidi,gnDeviceOut,0,0,0) // Ouverture Port clavier
gnRetCC = API("WINMM.DLL","midiOutShortMsg",gnHMidi,nCONTROL_CHANGE_INIT)
gnRetChangeCanal = API("WINMM.DLL","midiOutShortMsg",gnHMidi,nPROGRAM_CHANGE_CANAL)


stHdr.BufferLength = nSize
stHdr.BytesRecorded = nSize
stHdr.DataPtr = &tabByteArray

nResultat = API("WINMM.DLL","midiOutPrepareHeader",gnHMidi,&stHdr,nSize)
SI nResultat <> 0 ALORS
AfficheErreurMidiOUT(nResultat)
FIN

nResultat1 = API("WINMM.DLL","midiOutLongMsg",gnHMidi,&stHdr,nSize)
Sleep(50)
SI nResultat1 <> 0 ALORS
AfficheErreurMidiOUT(nResultat1) // pour afficher un Info de l'erreur
FIN

nResultat2 = API("WINMM.DLL","midiOutUnprepareHeader",gnHMidi,&stHdr,nSize)
SI nResultat2 <> 0 ALORS
AfficheErreurMidiOUT(nResultat2)
FIN
gnRetmidiOutClose = API("WINMM.DLL","midiOutClose",gnHMidi)


Tous les codes retour donnent bien 0, mais mon sysex n'est pas pris en compte. D'après ce que j'ai pu voir dans certains programmes en VB le sysex doit être transformé en Byte sur 2 octets.

Ce que j'ai trouvé en VB:
'Envoie un message long
Public Sub MidiSendLong(ByVal hMidiOut As Integer, ByVal text_msg As String)

Dim hdr As MIDIHDR
Dim result As Integer
Dim ss() As String = text_msg.Split(" ")
Dim size As Integer = ss.Length

hdr.lpData = System.Runtime.InteropServices.Marshal.AllocHGlobal(size) -de la librairie mscorlib
For i As Integer = 0 To size - 1
System.Runtime.InteropServices.Marshal.WriteByte(hdr.lpData, i, CByte(Val("&h" & ss(i)))) -de la librairie mscorlib
Next
hdr.dwBufferLength = size
hdr.dwBytesRecorded = size

result = midiOutPrepareHeader(hMidiOut, hdr, 48)
result = midiOutLongMsg(hMidiOut, hdr, 48)
result = midiOutUnprepareHeader(hMidiOut, hdr, 48)

System.Runtime.InteropServices.Marshal.FreeHGlobal(hdr.lpData)

End Sub

J'en appelle aux spécialistes MIDI/WINDEV pour des conseils éclairés avec mes chaleureux remerciements