I got this little piece of code which is working fine for now. However I want to play a sound in the callback function but I read in the MSDN pages:
"Applications should not call any multimedia functions from inside the callback function, as doing so can cause a deadlock. Other system functions can safely be called from the callback".
I'm quite new to programming and my question is: How can I work around this and still be able to play sounds when a MIDI-key is hit.
#include<iostream>
#include<cstdlib>
#include<windows.h>
#include<Mmsystem.h>
#include<stdio.h>
using namespace std;
void CALLBACK midiCallback(HMIDIIN handle, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
{
switch (uMsg)
{
case MIM_OPEN:
cout << "-----OPENED.-----" << endl;
break;
case MIM_CLOSE:
cout << "-----EVERYTHING IS CLOSING.-----" << endl;
break;
case MIM_DATA:
cout << "-----APPARENTLY THERE I5 DATA.-----" << endl;
break;
case MIM_LONGDATA:
cout << "-----LONGDATA'D.-----" << endl;
break;
case MIM_ERROR:
cout << "-----ERROR.-----" << endl;
break;
case MIM_LONGERROR:
cout << "-----LONGERROR. EVEN WORSE.-----" << endl;
break;
}
cout << "dwInstance is " << dwInstance << endl;
cout << "Handle is " << handle << endl;
cout << "dwParam1 is " << dwParam1 << endl; //dwParam1 is the bytes of the MIDI Message packed into an unsigned long
cout << "dwParam1_hiword is " << HIWORD(dwParam1) << endl; //velocity
cout << "dwParam1_loword is " << LOWORD(dwParam1) << endl; //keyID
cout << "dwParam2 is " << dwParam2 << endl; //dwParam2 is the timestamp of key press
cout << "uMsg is " << uMsg << endl;
cout << "-----" << endl;
}
void MidiThing() {
MIDIINCAPS mic;
unsigned long result;
HMIDIIN inHandle;
unsigned long iNumDevs, i;
iNumDevs = midiInGetNumDevs(); /* Get the number of MIDI In devices in this computer */
/* Go through all of those devices, displaying their names */
for (i = 0; i < iNumDevs; i++)
{
/* Get info about the next device */
if (!midiInGetDevCaps(i, &mic, sizeof(MIDIINCAPS)))
{
/* Display its Device ID and name */
cout << "Device ID [" << i << "]: " << mic.szPname << endl;
}
}
cout << endl;
// Open the default MIDI In device. (DevID 0)
result = midiInOpen(&inHandle, 0, (DWORD)midiCallback, 0, CALLBACK_FUNCTION);
if (result != MMSYSERR_NOERROR) {
cout << "midiInOpen() failed...rv= " << result << endl;
}
else
{
midiInStart(inHandle);
}
cout << endl;
cout << "Press \"ESC\" to quit." << endl;
while (1) {
if (GetAsyncKeyState(VK_ESCAPE))
{
break;
cout << "exit=true." << endl;
}
Sleep(100);
}
midiInStop(inHandle);
midiInReset(inHandle);
midiInClose(inHandle);
cout << endl;
cout << inHandle << " was the MIDIIN handle." << endl;
cout << endl;
cout << "MIDI is closed now." << endl;
}
int main(int argc, char *argv[])
{
MidiThing();
cout << "Exit is success." << endl;
return EXIT_SUCCESS;
}
Wake up another thread from the callback.
Related
I'm trying to create a program that will categorize all the connected USB devices and their port GUID.
I found an example of how to get all the information from connected input devices:
#include <windows.h>
#include <iostream>
// Namespace
using namespace std;
// Main
int main()
{
// Program
cout << "USB Device Lister." << endl;
// Get Number Of Devices
UINT nDevices = 0;
GetRawInputDeviceList(NULL, &nDevices, sizeof(RAWINPUTDEVICELIST));
// Got Any?
if (nDevices < 1)
{
// Exit
cout << "ERR: 0 Devices?";
cin.get();
return 0;
}
// Allocate Memory For Device List
PRAWINPUTDEVICELIST pRawInputDeviceList;
pRawInputDeviceList = new RAWINPUTDEVICELIST[sizeof(RAWINPUTDEVICELIST) * nDevices];
// Got Memory?
if (pRawInputDeviceList == NULL)
{
// Error
cout << "ERR: Could not allocate memory for Device List.";
cin.get();
return 0;
}
// Fill Device List Buffer
int nResult;
nResult = GetRawInputDeviceList(pRawInputDeviceList, &nDevices, sizeof(RAWINPUTDEVICELIST));
// Got Device List?
if (nResult < 0)
{
// Clean Up
delete[] pRawInputDeviceList;
// Error
cout << "ERR: Could not get device list.";
cin.get();
return 0;
}
// Loop Through Device List
for (UINT i = 0; i < nDevices; i++)
{
// Get Character Count For Device Name
UINT nBufferSize = 0;
nResult = GetRawInputDeviceInfo(pRawInputDeviceList[i].hDevice, // Device
RIDI_DEVICENAME, // Get Device Name
NULL, // NO Buff, Want Count!
&nBufferSize); // Char Count Here!
// Got Device Name?
if (nResult < 0)
{
// Error
cout << "ERR: Unable to get Device Name character count.. Moving to next device." << endl << endl;
// Next
continue;
}
// Allocate Memory For Device Name
WCHAR* wcDeviceName = new WCHAR[nBufferSize + 1];
// Got Memory
if (wcDeviceName == NULL)
{
// Error
cout << "ERR: Unable to allocate memory for Device Name.. Moving to next device." << endl << endl;
// Next
continue;
}
// Get Name
nResult = GetRawInputDeviceInfo(pRawInputDeviceList[i].hDevice, // Device
RIDI_DEVICENAME, // Get Device Name
wcDeviceName, // Get Name!
&nBufferSize); // Char Count
// Got Device Name?
if (nResult < 0)
{
// Error
cout << "ERR: Unable to get Device Name.. Moving to next device." << endl << endl;
// Clean Up
delete[] wcDeviceName;
// Next
continue;
}
// Set Device Info & Buffer Size
RID_DEVICE_INFO rdiDeviceInfo;
rdiDeviceInfo.cbSize = sizeof(RID_DEVICE_INFO);
nBufferSize = rdiDeviceInfo.cbSize;
// Get Device Info
nResult = GetRawInputDeviceInfo(pRawInputDeviceList[i].hDevice,
RIDI_DEVICEINFO,
&rdiDeviceInfo,
&nBufferSize);
// Got All Buffer?
if (nResult < 0)
{
// Error
cout << "ERR: Unable to read Device Info.. Moving to next device." << endl << endl;
// Next
continue;
}
// Mouse
if (rdiDeviceInfo.dwType == RIM_TYPEMOUSE)
{
// Current Device
cout << endl << "Displaying device " << i + 1 << " information. (MOUSE)" << endl;
wcout << L"Device Name: " << wcDeviceName << endl;
cout << "Mouse ID: " << rdiDeviceInfo.mouse.dwId << endl;
cout << "Mouse buttons: " << rdiDeviceInfo.mouse.dwNumberOfButtons << endl;
cout << "Mouse sample rate (Data Points): " << rdiDeviceInfo.mouse.dwSampleRate << endl;
if (rdiDeviceInfo.mouse.fHasHorizontalWheel)
{
cout << "Mouse has horizontal wheel" << endl;
}
else
{
cout << "Mouse does not have horizontal wheel" << endl;
}
}
// Keyboard
else if (rdiDeviceInfo.dwType == RIM_TYPEKEYBOARD)
{
// Current Device
cout << endl << "Displaying device " << i + 1 << " information. (KEYBOARD)" << endl;
wcout << L"Device Name: " << wcDeviceName << endl;
cout << "Keyboard mode: " << rdiDeviceInfo.keyboard.dwKeyboardMode << endl;
cout << "Number of function keys: " << rdiDeviceInfo.keyboard.dwNumberOfFunctionKeys << endl;
cout << "Number of indicators: " << rdiDeviceInfo.keyboard.dwNumberOfIndicators << endl;
cout << "Number of keys total: " << rdiDeviceInfo.keyboard.dwNumberOfKeysTotal << endl;
cout << "Type of the keyboard: " << rdiDeviceInfo.keyboard.dwType << endl;
cout << "Subtype of the keyboard: " << rdiDeviceInfo.keyboard.dwSubType << endl;
}
// Some HID
else // (rdi.dwType == RIM_TYPEHID)
{
// Current Device
cout << endl << "Displaying device " << i + 1 << " information. (HID)" << endl;
wcout << L"Device Name: " << wcDeviceName << endl;
cout << "Vendor Id:" << rdiDeviceInfo.hid.dwVendorId << endl;
cout << "Product Id:" << rdiDeviceInfo.hid.dwProductId << endl;
cout << "Version No:" << rdiDeviceInfo.hid.dwVersionNumber << endl;
cout << "Usage for the device: " << rdiDeviceInfo.hid.usUsage << endl;
cout << "Usage Page for the device: " << rdiDeviceInfo.hid.usUsagePage << endl;
}
// Delete Name Memory!
delete[] wcDeviceName;
}
// Clean Up - Free Memory
delete[] pRawInputDeviceList;
// Exit
cout << endl << "Finnished.";
cin.get();
return 0;
}
I tried to convert this code to get all the connected USB devices but failed.
So my question is what is the best way to collect the data I'm looking for?
If you want all USB devices, not just "input" devices, then you need to use the same APIs that Device Manager does.
For example, all devices shown by Device Manager can be listed with the help of the SetupDiGetClassDevs function.
For listing USB devices, you'll want to use the enumerator parameter set to "USB" (the enumerator is the bus where the device is attached, for example it can be "PCI", "PCMCIA", "USB" for the main computer busses, and it can also be a secondary bus provided by an expansion device, e.g. "SCSI", "FTDIBUS", and so on). You may sometimes find that you're more interested in child devices than the USB-attached parent device itself.
Keep in mind that it is not enough just to comment // (rdi.dwType == RIM_TYPEHID) as you did in following sequence, since it will print only rdiDeviceInfo.hid.SOMETHING info. If device is not HID, I would expect some junk, or similar to be printed.
else // (rdi.dwType == RIM_TYPEHID)
{
// Current Device
cout << endl << "Displaying device " << i + 1 << " information. (HID)" << endl;
wcout << L"Device Name: " << wcDeviceName << endl;
cout << "Vendor Id:" << rdiDeviceInfo.hid.dwVendorId << endl;
cout << "Product Id:" << rdiDeviceInfo.hid.dwProductId << endl;
cout << "Version No:" << rdiDeviceInfo.hid.dwVersionNumber << endl;
cout << "Usage for the device: " << rdiDeviceInfo.hid.usUsage << endl;
cout << "Usage Page for the device: " << rdiDeviceInfo.hid.usUsagePage << endl;
}
I would recommend you to add some logging and breakpoints (to print number of devices, to print all device names etc.). If you don't solve it, please paste the code that you use for testing with precise issue explanation.
UPDATE:
GetRawInputDeviceList function
Remarks
The devices returned from this function are the mouse, the keyboard, and other Human Interface Device (HID) devices.
If your device is not HID don't expect to see it in a list.
I'm completely new to Libusb. I have written a c++ program in Ubuntu, I can connect to the device, I transfer some data to the device using libusb_bulk_transfer(...). It works the first time, but the second time it returns -1 code. But when I reject the device and then when I reinstall the device to my computer, it works again.
Here is my code:
#include <iostream>
#include <stdio.h>
#include <libusb.h>
using namespace std;
#define BULK_OUTPUT LIBUSB_ENDPOINT_OUT | 0x01
#define BULK_INPUT LIBUSB_ENDPOINT_IN | 0x01
union usb_relator {
unsigned char usb_data[4];
int32_t number;
};
int main()
{
libusb_device_handle *handle = NULL;
if (libusb_init(NULL) < 0)
{
cout << "Failure" << endl;
return 0;
}
cout << "libusb inited successfully!!" << endl;
libusb_device **devices;
libusb_get_device_list(NULL, &devices);
if (libusb_open(devices[0], &handle) < 0)
{
cout << "The device can not be open!!" << endl;
return 0;
}
cout << "device opened successfully!!" << endl;
libusb_device_descriptor descriptor;
libusb_get_device_descriptor(devices[0], &descriptor);
cout << "Vendor id: " << (int)descriptor.idVendor << endl;
cout << "Product Id: " << (int)descriptor.idProduct << endl;
libusb_detach_kernel_driver(handle, 0);
if (libusb_claim_interface(handle, 0) < 0)
{
cout << "Can not claim interface!!" << endl;
return 0;
}
cout << "Handle has been claimed!!" << endl;
if (libusb_set_interface_alt_setting(handle, 0, 0) < 0)
{
cout << "Could not set alternate setting of the handle!!" << endl;
return 0;
}
cout << "alt_setting set successfully!!" << endl;
usb_relator number;
cout << "Please insert your number: ";
cin >> number.number;
int transfer_size;
int returnCode = libusb_bulk_transfer(handle, BULK_OUTPUT, number.usb_data, sizeof(usb_relator), &transfer_size, 5000);
if (returnCode == 0)
{
cout << "Data sent!!" << endl;
}
else
{
cout << "Data could not be send!! Code: " << returnCode << endl;
}
returnCode = libusb_bulk_transfer(handle, BULK_INPUT, number.usb_data, sizeof(usb_relator), &transfer_size, 5000);
if (returnCode == 0)
{
cout << "Data recieved!!" << endl;
cout << number.usb_data << endl;
}
else
{
cout << "Data could not recieve!! Code: " << returnCode << endl;
}
libusb_release_interface(handle, 0);
libusb_close(handle);
libusb_free_device_list(devices, 1);
libusb_exit(NULL);
}
I'm using Ubuntu 14.04, and I'm using VMWare. Thanks for your help.
I think it has something to do with the libusb_detach_kernal_driver(...) methode I call in my code.(Right before the line I claim the interface).
I am working on a power engineering project on 4th semester, and programming isn't my strong side. I've been working on using libusb for communication between a PSoC 5 and a Linux terminal program written in C++. The terminal code is:
The problem is that libusb_open_device_with_vid_pid(NULL, 0x1111, 0x2222) returns 0 every time, even though the device is recognized by the Linux OS. OS is Ubuntu if that is relevant.
#include <iostream>
#include "libusb-1.0/libusb.h"
#include "usb.h"
#include <time.h>
using namespace std;
union USB_DATA
{
unsigned char USB_ARRAY[1200];
int DirectionOfPower;
int menu;
float Voltage;
float Current;
float Temperature;
float PowerFactor;
float DistortionPowerFactor;
float Amplitude_Of_Harmonics[1001];
float Regulate_To;
};
union USB_DATA USB_;
/*
void error(string s, int err)
{
cout << s " ERROR: " << libusb_error_name(err) << endl;
exit(err);
}
*/
int main()
{
int transfer_size;
int err;
float Reg_To;
// Device Handle
libusb_device_handle* dev;
// Initialize libusb with default context
libusb_init(NULL);
// Open Device VID = 0x1111, PID = 0x2222 with the default libusb context
dev = libusb_open_device_with_vid_pid( NULL, 0x1111, 0x2222 );
// If device is null, we didn't find it
/*
if (dev == NULL)
{
cout << "Device not found, exiting." << endl;
return -1;
}
int k = 0;
while (dev == NULL)
{
cout << "Device not found, trying again." << " " << k << endl;
//sleep(1);
k = k+1;
}
*/
// Claim interface 0 on the device. Here we te the operation system that wewan this device
libusb_claim_interface(dev, 0);
libusb_detach_kernel_driver(dev, 0);
// Set alternate setting 0 on interface 0
libusb_set_interface_alt_setting(dev, 0, 0);
while(true)
{
cout << "Welcome to Spaendingsregulering!" << endl;
cout << endl;
cout << "MENU" << endl;
cout << "Indtast nummer for navigation" << endl;
cout << "1. Indsaet driftsparametre " << endl;
cout << "2. Analyser harmoniske " << endl;
cout << "3. Fremvis data " << endl;
while(true)
{
cin >> USB_.menu;
if(cin.good())
break;
cin.clear();
}
/*
err = libusb_bulk_transfer(dev, 0x02, USB_.USB_ARRAY, sizeof(union USB_), &transfer_size, 1000);
if( err )
error( "Bulk OUT Transfer Failed!", err);
err = libusb_bulk_transfer(dev, 0x81, USB_.USB_ARRAY, sizeof(union USB_), &transfer_size, 1000);
if( err )
error( "Bulk IN Transfer Failed!", err);
*/
if(USB_.menu == 1)
while(true)
{
cout << "Indsaet oensket spaending" << endl;
cout << "Indtast 999 for at vende tilbage til hovedmenuen" << endl;
cin >> Reg_To;
cout << endl;
if(Reg_To == 999)
{
break;
}
USB_.Regulate_To = Reg_To;
cout << "=======================" << endl;
cout << "Saetter oensket spaending til:" << " " << USB_.Regulate_To << "V" << endl;
cout << "=======================" << endl;
cout << endl;
cout << "Vender tilbage til hovedmenu" << endl;
cout << "..." << endl;
cout << endl;
if(cin.good())
break;
cin.clear();
}
}
}
libusb_open_device_with_vid_pid combines finding and opening and doesn't return an error code. If you are sure the device is there, have you checked you have the rights to read/write to it ? You can also increase the verbosity of error messages.
– Leiaz
Thanks! that did it!. I forgot to use sudo.. rookie mistake – Çağrı Esen
for (;;)
{
cout << "You are playing for:" << playtime << "seconds." << endl;
cout << "You have " << bytes << " bytes." << endl;
cout << "You are compiling " << bps << " bytes per second." << endl;
cout << "Press a to buy assembler monkey (produces 1 byte per second)/(cost 10 bytes)" << endl;
switch(getch())
{
case 'a': bytes = bytes - 10; bps++; break;
}
bytes = bytes + bps;
playtime++;
Sleep(1000);
system("cls");
}
Let's say that's my incremental game. I want refresh my game after 1 second. How can I make getch() to wait for input without stopping all other stuff?
Use kbhit() function to detect if a key was pressed :)
something like:
for (;;)
{
cout << "You are playing for:" << playtime << "seconds." << endl;
cout << "You have " << bytes << " bytes." << endl;
cout << "You are compiling " << bps << " bytes per second." << endl;
cout << "Press a to buy assembler monkey (produces 1 byte per second)/(cost 10 bytes)" << endl;
if(kbhit()){ //is true when a key was pressed
char c = getch(); //capture the key code and insert into c
switch(c)
{
case 'a': bytes = bytes - 10; bps++; break;
}
}
bytes = bytes + bps;
playtime++;
Sleep(1000);
system("cls");
}
You could use another thread, to get the user input.
The for (;;) is unnecessary, instead you should use while (true).
#include <Windows.h>
#include <iostream>
#include <conio.h>
using namespace std;
DWORD WINAPI SpeedThread(LPVOID lpParam);
int main ()
{
int playtime = 0,
bytes = 0,
bps = 1;
bool bKeyPressed = false;
CreateThread( NULL, 0, SpeedThread, &bKeyPressed, 0, NULL);
while (true)
{
cout << "You are playing for:" << playtime << "seconds." << endl;
cout << "You have " << bytes << " bytes." << endl;
cout << "You are compiling " << bps << " bytes per second." << endl;
cout << "Press a to buy assembler monkey (produces 1 byte per second)/(cost 10 bytes)" << endl;
if (bKeyPressed && bytes >= 10)
{
bytes -= 10;
bps++;
bKeyPressed = false;
}
bytes = bytes + bps;
playtime++;
Sleep(1000);
system("cls");
}
}
DWORD WINAPI SpeedThread (LPVOID lpParam)
{
bool * bKeyPressed = (bool *) lpParam;
while (true)
{
if (_getch () == 'a')
*bKeyPressed = true;
}
}
What worked for me is not to use getch() but instead use scanf().
In order to stop scanf from stopping you have to use :
scanf("%c \n",example);
Keep in mind, that example is a pointer (char* example;)
Not sure why SendMessage isn't getting the text from the class I need. I have done this before but it was is VisualBasic and I wanted to port it over to c++. I have not tried this code on any other program. I was reading something about it possibly being unicode but I wasn't sure on how to implement that.
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <iostream>
using namespace std;
void FindmIRC()
{
cout << "[mIRC]" << endl;
cout << "- find mIRC window" << endl;
HWND hwndmIRC = FindWindow(L"mIRC", NULL);
if (NULL != hwndmIRC)
{
cout << " + found mIRC window" << endl;
cout << "- find MDIClient window" << endl;
HWND hwndMDIClient = FindWindowEx(hwndmIRC, NULL, L"MDIClient", NULL);
if (NULL != hwndMDIClient)
{
cout << " + found MDIClient window" << endl;
cout << "- find mIRC_Channel window" << endl;
HWND hwndmIRC_Channel = FindWindowEx(hwndMDIClient, NULL, L"mIRC_Channel", NULL);
if (NULL != hwndmIRC_Channel)
{
cout << " + found mIRC_Channel window" << endl;
cout << "- find Static window" << endl;
HWND hwndStatic = FindWindowEx(hwndmIRC_Channel, NULL, L"Static", NULL);
if (NULL != hwndStatic)
{
cout << " + found Static window" << endl;
cout << "- get text length" << endl;
int textLen = (int)SendMessage(hwndStatic, WM_GETTEXTLENGTH, 0, 0);
if (0 < textLen)
{
cout << "- getting text" << endl;
const int bufferSize = 1024;
char textBuffer[bufferSize] = "";
SendMessage(hwndStatic, WM_GETTEXT, (WPARAM)bufferSize, (LPARAM)textBuffer);
cout << "[begin text]" << endl;
cout << textBuffer << endl;
cout << "[end text]" << endl;
}
else
{
cerr << "No text." << endl;
}
}
else
{
cerr << "Static not found." << endl;
}
}
else
{
cerr << "mIRC_Channel not found." << endl;
}
}
else
{
cerr << "MDIClient not found." << endl;
}
}
else
{
cerr << "mIRC not open." << endl;
}
}
int main()
{
FindmIRC();
return 0;
}
The highlighted class is what has the text:
The program find the class with no problem and does not report not finding it so I don't see a reason why it should not find it. Any help is great!
As you can see on your spy++ output, highlighted control does not contain any text. It should appear on the left of Static in "".