Questo sito utilizza cookies, anche di terze parti, per mostrare pubblicità e servizi in linea con il tuo account. Leggi l'informativa sui cookies.
Username: Password: oppure
C# / VB.NET - [VB.NET] MIDI , errore con callback di funzione .
Forum - C# / VB.NET - [VB.NET] MIDI , errore con callback di funzione .

Avatar
masterz (Normal User)
Newbie


Messaggi: 8
Iscritto: 28/02/2011

Segnala al moderatore
Postato alle 19:26
Lunedì, 28/02/2011
(copio e incollo da un altro forum in cui ho postato la domanda )
spero di non aver scritto cavolate nel titolo ,
purtroppo mi ritrovo con un problema di concetto , essendo passato io da poco a vb.net non ho capito ancora bene come funziona il concetto di delegate ed in generale il concetto di programmazione ad oggetti ( essendo io passato da programmazione ad eventi! ).

Iniziero' a leggere una guida avanzata ( sto leggendo quella di questo sito)

Pero' ... ho poco tempo , prima di rimettermi a studiare per l'universita' dovrei finire il programma, alla svelta ,quindi vi spiego il problema .

Ho trovato del codice in vb6 per utilizzare il mio controller midi per i miei soft .
aiutandomi con degli esempi presi su internet sono riuscito a farlo girare benone su vb.net utilizzando il metodo delegate ... da completo profano . Pero' c'e' un problema , la funzione richiamata dai delegate funziona solo se richiama a sua volta delle sub che caricano poco la cpu , quindi , a volte mi da' l'errore a volte no , sull 'help ho trovato esposta la causa e la soluzione , pero' essendo io alquanto profano in materia , in realta' non ho capito bene ne la causa ne la soluzione , il link e' questo : LINK

ora vi incollo il codice che fa funzionare il mio controller midi come joystick

in un modulo ho messo :
Codice sorgente - presumibilmente VB.NET

  1. Module Module1
  2.  
  3.     Declare Function midiInGetNumDevs Lib "winmm.dll" () As Long
  4.     Declare Function midiInGetDevCaps Lib "winmm.dll" Alias "midiInGetDevCapsA" (ByVal uDeviceID As Integer, ByRef lpCaps As MIDIINCAPS, ByVal uSize As Integer) As Integer
  5.  
  6.     'Api:
  7.     Public Delegate Function Memorize_EventCallback(ByVal MidiInHandle As Integer, _
  8.                                                ByVal Message As Integer, _
  9.                                                ByVal Instance As Integer, _
  10.                                                ByVal dw1 As Integer, _
  11.                                                ByVal dw2 As Integer) As Integer
  12.  
  13.     Declare Function midiInOpen Lib "winmm.dll" (ByRef lphMidiIn As Integer, ByVal uDeviceID As Integer, ByVal dwCallback As Memorize_EventCallback, ByVal dwInstance As Integer, ByVal dwFlags As Integer) As Integer
  14.  
  15.     Declare Function midiInClose Lib "winmm.dll" (ByVal hMidiIn As Integer) As Integer
  16.     Declare Function midiInStart Lib "winmm.dll" (ByVal hMidiIn As Integer) As Integer
  17.     Declare Function midiInStop Lib "winmm.dll" (ByVal hMidiIn As Integer) As Integer
  18.     Declare Function midiInReset Lib "winmm.dll" (ByVal hMidiIn As Integer) As Integer
  19.  
  20.     'la reference
  21.     Public ri As Long
  22.  
  23.     Public Structure MIDIINCAPS
  24.         Dim wMid As Short ' Manufacturer ID
  25.         Dim wPid As Short ' Product ID
  26.         Dim vDriverVersion As Integer ' Driver version
  27.         Dim szPname As String ' Product Name
  28.         Dim dwSupport As Integer ' Supported extras
  29.     End Structure
  30.  
  31.     Public Const CALLBACK_FUNCTION = &H30000    'riferimento alla funzione
  32.  
  33. End Module


nella form principale invece ho piazzato all'evento LOAD
Codice sorgente - presumibilmente VB.NET

  1. Dim a As Integer
  2.         a = midiInGetNumDevs
  3.             ListBox1.Items.Add("controller midi :" & a)
  4.         If a = 1 Then
  5.             midiInOpen(ri, 0, AddressOf MidiIn_Event, 0, CALLBACK_FUNCTION)
  6.             midiInStart(ri)
  7.             ListBox1.BackColor = Color.GreenYellow
  8.         ElseIf a = 0 Then
  9.             MsgBox("controller midi non connesso oppure piu di un controller connesso!")
  10.             ListBox1.BackColor = Color.LightCoral
  11.         End If


ok ... e' poco preciso , ma per il mio uso va molto bene
e poi la funzione richiamata :
Codice sorgente - presumibilmente VB.NET

  1. #Region "regione RICEVIMIDI"
  2.  
  3.     Public Function MidiIn_Event(ByVal MidiInHandle As Integer, ByVal Message As Integer, ByVal Instance As Integer, ByVal dw1 As Integer, ByVal dw2 As Integer) As Integer
  4.         Dim a As String, b As String, c As String
  5.         Dim out As Short
  6.         If dw1 > 255 Then
  7.             Call RiceviMidi(dw1)
  8.         End If
  9.     End Function
  10.  
  11.  
  12.     Private Delegate Sub midiDelegate(ByVal code As Integer)
  13.  
  14.     Public Sub RiceviMidi(ByVal code As Integer)
  15.         If Me.InvokeRequired Then
  16.             Me.Invoke(New midiDelegate(AddressOf RiceviMidi), New Object() {code})
  17.             Return
  18.         End If
  19.         Dim b As String, a As String, c As String
  20.         a = code.ToString
  21.         b = Strings.Left(Strings.Right("00000000" + Hex(a), 6), 4)
  22.         c = Int("&H" + Strings.Right(b, 2))
  23.                 Call Joystick(c)
  24.         End If
  25.     End Sub
  26.  
  27. #End Region


la funzione joystick rileva quale tasto e' stato premuto e richiama una funzione del programma

allora il problema e' che dopo aver eseguito una serie di funzioni molto lunghe , richiamate in joystick , alla prima pressione del tasto tutto ok
, esegue le funzioni senza errori ,

quando pero' fatto questo vado a premere un tasto qualsiasi della tastiera midi ( uno qualsiasi , non per forza quello assegnato per eseguire altre funzioni ) , che richiama la funzione delegate di callback ( e0 giusto? ) , questa e' stata chiusa (? non so' perche') e mi appare l'errore CallbackOnCollectedDelegate .

potreste darmi una mano a risolvere il problema ??

grazie 1000

Ultima modifica effettuata da Il Totem il 01/03/2011 alle 11:11


programmatore solitario
PM
Avatar
Il Totem (Admin)
Guru^2


Messaggi: 3635
Iscritto: 24/01/2006

Up
0
Down
V
Segnala al moderatore
Postato alle 11:10
Martedì, 01/03/2011
Se il tuo problema è un delegato che viene distrutto prima del necessario, potresti dichiararlo come variabile globale: questo gli assicurerebbe la vita eterna!!! muhahaha!! Almeno finché lo distruggi logicamente.
Codice sorgente - presumibilmente C# / VB.NET

  1. Private midiOpenDelegate As New Memorize_EventCallback(AddressOf MidiIn_Event)


grazie 1000^1000 ... la soluzione era cosi semplice ! intanto mi finisco la tua guida al vb.net - masterz - 01/03/11 15:19


"Infelici sono quelli che hanno tanto cervello da vedere la loro stupidità."
(Fligende Blatter)

"Dubitare di se stessi è il primo segno d'intelligenza."
(Ugo Ojetti)
PM
Avatar
pablormago (Normal User)
Newbie


Messaggi: 2
Iscritto: 22/02/2012

Up
0
Down
V
Segnala al moderatore
Postato alle 17:01
Mercoledì, 22/02/2012
i have the same problem, but i cant resolve, here is my project: https://docs.google.com/viewer?a=v&pid=explorer&chrome=true ...

Any help would be great, thanx

PM
Avatar
pablormago (Normal User)
Newbie


Messaggi: 2
Iscritto: 22/02/2012

Up
0
Down
V
Segnala al moderatore
Postato alle 17:04
Mercoledì, 22/02/2012
Hi, i have the same problem but i cant resolved,could you help me??

here is my project https://docs.google.com/viewer?a=v&pid=explorer&chrome=true ...

and here are my codes:

Form1
Codice sorgente - presumibilmente VB.NET

  1. Delegate Sub DelegateForSomeSub(ByVal arg0 As String)
  2. Public Class Form1
  3.    
  4.  
  5.     Public Sub SomeSub(ByVal arg0 As String)
  6.         If Me.InvokeRequired Then
  7.             Debug.Print("invoke")
  8.             Me.Invoke(New DelegateForSomeSub(AddressOf AppendText), arg0)
  9.         Else
  10.             Debug.Print("append")
  11.             AppendText(arg0)
  12.         End If
  13.         'Debug.Print(arg0)
  14.  
  15.     End Sub
  16.  
  17.     Private Sub AppendText(ByVal arg0 As String)
  18.         TextBox2.Text = arg0
  19.  
  20.     End Sub
  21.     Private Sub Form1_Disposed(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Disposed
  22.         midiInClose(hMidiIn)
  23.     End Sub
  24.  
  25.     Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
  26.         ' open the first available midi input device
  27.         midiInOpen(hMidiIn, 0, AddressOf MidiInProc, 0, CALLBACK_FUNCTION)
  28.         ' For explanation of parameters, see http://msdn.microsoft.com/en-us/library/ms711610
  29.         midiInStart(hMidiIn)
  30.  
  31.     End Sub
  32. End Class



And here is the Module 1 code
Codice sorgente - presumibilmente VB.NET

  1. Module Module1
  2.  
  3.  
  4.     'all the midi declarations
  5.     Delegate Function MidiIn_Callback(ByVal hMidiIn As Integer, ByVal wMsg As UInteger, ByVal dwInstance As Integer, ByVal dwParam1 As Integer, ByVal dwParam2 As Integer) As Integer
  6.     Public Declare Function midiInOpen Lib "winmm.dll" (ByRef lphMidiIn As Integer, ByVal uDeviceID As Integer, ByVal dwCallback As MidiIn_Callback, ByVal dwInstance As Integer, ByVal dwFlags As Integer) As Integer
  7.     Public Declare Function midiInClose Lib "winmm.dll" (ByVal hMidiIn As Integer) As Integer
  8.     Public Declare Function midiInStart Lib "winmm.dll" (ByVal hMidiIn As Integer) As Integer
  9.     Public hMidiIn As Integer
  10.     Public Const CALLBACK_FUNCTION As Integer = &H30000
  11.  
  12.     'these are public for debug purposes.
  13.     Public frames As Int16
  14.     Public seconds As Int16
  15.     Public minutes As Int16
  16.     Public hours As Int16
  17.     Public timecode As Long
  18.     Public byte1 As Byte
  19.     Public byte2 As Byte
  20.     Public nibble1 As Byte
  21.     Public nibble2 As Byte
  22.  
  23.    
  24.  
  25.     Function MidiInProc(ByVal hMidiIn As Integer, ByVal wMsg As UInteger, ByVal dwInstance As Integer, ByVal dwParam1 As Integer, ByVal dwParam2 As Integer) As Integer
  26.  
  27.         'MTC is 2 bytes. Byte 1 is F1 (means its an MTC packet). Byte 2 is a frame counter & frame value
  28.         byte1 = dwParam1 And &HFF
  29.         'skip if it isnt a frame packet
  30.         If byte1 <> &HF1 Then
  31.             Return 0
  32.             Exit Function
  33.         End If
  34.  
  35.         'byte 2 is split into nibbles. MS Nibble is Message Type, LS Nibble is Message
  36.         byte2 = dwParam1 >> 8
  37.         nibble1 = byte2 And &HF
  38.         nibble2 = byte2 >> 4
  39.  
  40.         'operate!
  41.         Select Case nibble2
  42.             Case 0  'frame lsb
  43.                 'mask
  44.                 frames = (frames And &HF0) Or nibble1
  45.             Case 1  'frame msb
  46.                 'shift
  47.                 nibble1 = nibble1 << 4
  48.                 'apply
  49.                 frames = (frames And &HF) Or nibble1
  50.             Case 2  'second lsb
  51.                 'apply
  52.                 seconds = (seconds And &HF0) Or nibble1
  53.             Case 3  'second msb
  54.                 'shift
  55.                 nibble1 = nibble1 << 4
  56.                 'apply
  57.                 seconds = (seconds And &HF) Or nibble1
  58.             Case 4  'minute lsb
  59.                 'apply
  60.                 minutes = (minutes And &HF0) Or nibble1
  61.                 frames = frames + 1
  62.             Case 5  'second msb
  63.                 'shift
  64.                 nibble1 = nibble1 << 4
  65.                 'apply
  66.                 minutes = (minutes And &HF) Or nibble1
  67.             Case 6  'hours lsb
  68.                 'apply
  69.                 hours = (hours And &HF0) Or nibble1
  70.             Case 7  'hours msb
  71.                 'shift
  72.                 nibble1 = nibble1 << 4
  73.                 'apply
  74.                 hours = (hours And &HF) Or (nibble1 And &H1)
  75.         End Select
  76.  
  77.         If nibble2 = 1 Or nibble2 = 5 Then
  78.             DirectCast(My.Application.OpenForms.Item("Form1"), Form1).SomeSub(hours & ":" & minutes & ":" & seconds & ":" & frames & " -- " & nibble2)
  79.         End If
  80.     End Function
  81. End Module



thanks

Pablo.

PM