Problem using MIDI streams in Windows - c++

I'm writing a Windows program using C++ and the Windows API, and, am trying to queue MIDI messages in a MIDI stream, but am receiving a strange error when I try to do so. If I use midiOutShortMsg to send a non-queued MIDI message to the stream, it works correctly. However, midiStreamOut always returns error code 68, which is #defined to MCIERR_WAVE_OUTPUTUNSPECIFIED. midiOutGetErrorText gives the following description of the error:
The current MIDI Mapper setup refers to a MIDI device that is not installed on the system. Use MIDI Mapper to edit the setup.
I am using Windows 7 (64-bit) and have tried opening the MIDI stream with device IDs of both MIDI_MAPPER and all four MIDI output devices on my system, and still receive the exact same error message.
Here is the code to open the MIDI stream:
UINT device_id = MIDI_MAPPER; //Also tried 0, 1, 2 and 3
midiStreamOpen( &midi, &device_id, 1, ( DWORD_PTR )hwnd, 0, CALLBACK_WINDOW );
Here is the code to send the MIDI message:
MIDIHDR header;
MIDIEVENT *event;
event = ( MIDIEVENT * )malloc( sizeof( *event ) );
event->dwDeltaTime = delta_time;
event->dwStreamID = 0;
event->dwEvent = ( MEVT_F_SHORT | MEVT_SHORTMSG ) << 24 | ( msg & 0x00FFFFFF );
header.lpData = ( LPSTR )event;
header.dwBufferLength = sizeof( *event );
header.dwBytesRecorded = sizeof( *event );
header.dwUser = 0;
header.dwFlags = 0;
header.dwOffset = 0;
midiOutPrepareHeader( ( HMIDIOUT )midi, &header, sizeof( header ) );
midiStreamOut( midi, &header, sizeof( header ) );
How can I resolve this problem?

The problem was that I was using the entire event structure as the buffer for the MIDI stream. It turns out that the fourth member of the structure, dwParms, should actually be omitted from short messages. To correct the code in the posted question, two of the lines of code could be changed to the following:
header.dwBufferLength = sizeof( *event ) - sizeof( event->dwParms );
header.dwBytesRecorded = sizeof( *event ) - sizeof( event->dwParms );
When adding multiple events to the stream, it's actually a lot easier to just use an array of DWORDs rather than even bothering with the MIDIEVENT structures.
For anyone else doing MIDI programming using the Windows API, beware that some of the MSDN documentation is misleading, inadequate or completely wrong.
The documentation for the MIDIEVENT structure says the following:
dwParms
If dwEvent specifies MEVT_F_SHORT, do not use this member in the stream buffer.
This is ambiguous because it is not clear that "use" is intended to mean "include" rather than "specify".
Here are two other flaws in the documentation that programmers need to be aware of:
dwEvent
Event code and event parameters or length. [...] The high byte of this member contains flags and an event code. Either the MEVT_F_LONG or MEVT_F_SHORT flag must be specified. The MEVT_F_CALLBACK flag is optional.
When the header files are checked, the MEVT_F_ preprocessor definitions actually specify complete DWORDs rather than just the individual flags, so in my code in the question, the line specifying this member should have been as follows:
event->dwEvent = MEVT_F_SHORT | MEVT_SHORTMSG << 24 | ( msg & 0x00FFFFFF );
In addition to this, it has also turned out that the memory containing the MIDIHDR structure should be retained until the buffer has finished playing, so it should be allocated on the heap rather than the stack for most implementations.

Related

Translate windows serial port code to Macos

I have been struggling to translate this specific code, so it works on my Xcode program without the windows.h file. Does anybody have some ideas about how I can make it work?
Thank you in advance
This is the following code:
COMPort::COMPort ( const char * const portName )
: theDCB (NULL)
{
thePortHandle = (unsigned ) CreateFile ( portName
, GENERIC_READ | GENERIC_WRITE
, 0
, NULL
, OPEN_EXISTING
, FILE_FLAG_NO_BUFFERING
, NULL
);
if (thePortHandle == HFILE_ERROR)
{
throw runtime_error ("COMPort: failed to open.");
}
theDCB = new char [sizeof(DCB)];
getState();
setBlockingMode();
setHandshaking();
}
COMPort::~COMPort()
{
delete [] theDCB;
if (CloseHandle ((HANDLE)thePortHandle) == FALSE )
{
throw runtime_error ("COMPort: failed to close.");
}
}
It looks as if you are rewriting Windows code for serial communication. Windows and macOS are very different in this respect.
You will find many examples of how to do this, e.g.: https://www.pololu.com/docs/0J73/15.5
CreateFile translates to open
CloseHandle translates to close
The DCB struct translates to termios and is probably only needed temporarily for setting baud rate.
Most likely, your code also uses GetComm and SetComm. Those would translate to tcgetattr, tcsetattr and possibly cfsetispeed and cfsetospeed.
When it comes to concurrently writing to and reading from a serial port, macOS is much simpler than Windows where it is mutually exclusive unless non-blocking I/O is used. On macOS, reading and writing are independent.
If you also translate your code to Linux as well, you will find that macOS and Linux are almost the same.

(Windows HID API) HidD_GetPreparsedData() failing in WM_INPUT message handler due to incorrect handle?

I am trying to write custom handling for an Apple Magic Trackpad 2 (ultimately any Windows Precision Touchpad) into a Windows Desktop application. I am using this project as a guide, as it accomplishes similar goals. I am at the point where I have registered the HID touchpad, and am able to receive WM_INPUT messages, which I am handling in the code below. Note, I did have to download open-source drivers in order for the touchpad to work correctly and trigger WM_INPUT messages.
afx_msg void CSimulatorWnd::OnRawInput( UINT nInputCode, HRAWINPUT hRawInput )
{
/*----------------------------------------------------------
Local variables
----------------------------------------------------------*/
HIDP_CAPS hid_capabilities;
UINT data_size = 0;
PHIDP_PREPARSED_DATA preparsed_data = NULL; // allocated by HidD_GetPreparsedData
PRAWINPUT raw_data_buffer = NULL;
RAWINPUTDEVICELIST * connected_devices = NULL;
// add vars that need to be de-allocated here
#define free_and_return() free( raw_data_buffer ); \
if( preparsed_data ){ HidD_FreePreparsedData( preparsed_data ); } \
return;
// get the required raw data size (returns 0 if successful)
if( GetRawInputData( hRawInput, RID_INPUT, NULL, &data_size, sizeof( RAWINPUTHEADER ) ) != 0
|| data_size == 0 )
{
free_and_return();
}
// allocate space in the input data buffer
raw_data_buffer = (RAWINPUT *)malloc( data_size );
// get the raw data (returns the required buffer size from above if successful)
if( GetRawInputData( hRawInput, RID_INPUT, raw_data_buffer, &data_size, sizeof( RAWINPUTHEADER ) ) != data_size )
{
free_and_return();
}
// only handle registered HIDs
if( raw_data_buffer->header.dwType != RIM_TYPEHID )
{
free_and_return();
}
// get pre-parsed HID data. need this structure
if( !HidD_GetPreparsedData( raw_data_buffer->header.hDevice, &preparsed_data ) )
{
// NOTE: raw_data_buffer->header.hDevice = 0x000000004ddd0ce9,
// returning a ERROR_INVALID_HANDLE for some reason.
//
// Below is the information for the HID I registered.
// The handle is correct. The printout below was from
// enumerating over available devices from GetRawInputDeviceList()
// and the output from GetRawInputDeviceInfo()
//
// *********** HID INFO ***********
// HNDL: 000000004DDD0CE9
// Product ID: 613
// Vendor ID: 35088
// Version Number: 1
// Usage Page: 0X0000000D
// Usage: 0X00000005
// ********************************
DWORD error = GetLastError();
free_and_return();
}
// get multi-touch HID capabilities and data
// https://learn.microsoft.com/en-us/windows-hardware/design/component-guidelines/supporting-usages-in-multitouch-digitizer-drivers
HidP_GetCaps( preparsed_data, &hid_capabilities );
// free dynamically allocated memory
free_and_return();
} /* CSimulatorWnd::OnRawInput() */
Right now, I am at the stage of trying to use the hidpi.h API calls to get raw x, y, contact, etc. data. In order to access any of this, I need preparsed data output by HidD_GetPreparsedData(). Unfortunately, that function is failing, and returning an error code stating the provided handle (from the raw data) is wrong.
Am I missing something? As I commented, the handle I'm passing in looks correct, matching that of the device I registered.
I fixed it! I am not sure as to why I couldn't use HidD_GetPreparsedData(), but getting the data with GetRawInputDeviceInfo(), using the RIDI_PREPARSEDDATA param, worked just fine.
RAWINPUTHEADER.hDevice handle is not usable with HidD_GetPreparsedData() API. This handle could be used only with GetRawInputDeviceInfo() (as you already found).
To use HidD_GetPreparsedData() and other HIDClass support routines you need:
Get HID device file name via ::GetRawInputDeviceInfo(raw_data_buffer->header.hDevice, RIDI_DEVICENAME, ..) call.
Open device file via ::CreateFile(device_name, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, nullptr, nullptr) call to get a real HIDs device_handle.
Now you can use HidD_GetPreparsedData().
Also you can use WriteFile API on that handle to send output reports to a HID collection. Details are here and here.

Multipart messages passing in ZMQ

I am trying to do a multipart message passing in ZeroMQ. More specifically, I want to pass an int followed by a pointer to a vector vector<T>*. I came up with the following code:
zmq::zmq_msg_t msg1;
zmq::zmq_msg_init_data ( &msg1, i, sizeof( i ), NULL, NULL );
zmq::zmq_send ( publisher_, &msg, ZMQ_SNDMORE );
zmq::zmq_msg_t msg2;
zmq::zmq_msg_init_data ptr, sizeof( ptr ), NULL, NULL );
zmq::zmq_send ( s, &msg, 0 );
I am not sure if this will work since it seems that the data parameter in the zmq_send method is of type void* and I am sending just a value.
Also, can anyone tell me how do I separately receive these two messages on the other side? Zero-copy and Multi-part Messages only shows how to get the messages when the number of messages to get is unknown. But in my case it is two. Is there an easier way to do this?

Libevent writes to the socket only after second buffer_write

Libevent is great and I love it so far. However, on a echo server, the write only sends to the socket on a second write. My writing is from another thread, a pump thread that talks to a db and does some minimal data massaging.
I verified this by setting up a callback for the write:
bufferevent_setcb( GetBufferEvent(), DataAvailable, DataWritten, HandleSocketError, this );
calling bufferevent_flush( m_bufferEvent, EV_READ|EV_WRITE, BEV_NORMAL ) doesn't seem to have any effect.
Here is the setup, just in case I blew it somewhere. I have dramatically simplified the overhead in my code base in order to obtain some help. This includes initialization of sockets, my thread init, etc. This is a multi-threaded app, so there may be some problem there. I start with this:
m_LibEventInstance = event_base_new();
evthread_use_windows_threads();
m_listener = evconnlistener_new_bind( m_LibEventInstance,
OnAccept,
this,
LEV_OPT_CLOSE_ON_FREE | LEV_OPT_CLOSE_ON_EXEC | LEV_OPT_REUSEABLE,
-1,// no maximum number of backlog connections
(struct sockaddr*)&ListenAddress, socketSize );
if (!m_listener) {
perror("Couldn't create listener");
return false;
}
evconnlistener_set_error_cb( m_listener, OnSystemError );
AFAIK, this is copy and paste from samples so it should work. My OnAccept does the following:
void OnAccept( evconnlistener* listenerObj, evutil_socket_t newConnectionId, sockaddr* ClientAddr, int socklen, void* context )
{
// We got a new connection! Set up a bufferevent for it.
struct event_base* base = evconnlistener_get_base( listenerObj );
struct bufferevent* bufferEvent = bufferevent_socket_new( base, newConnectionId, BEV_OPT_CLOSE_ON_FREE );
bufferevent_setcb( GetBufferEvent(), DataAvailable, DataWritten,
HandleSocketError, this );
// We have to enable it before our callbacks will be called.
bufferevent_enable( GetBufferEvent(), EV_READ | EV_WRITE );
DisableNagle( m_connectionId );
}
Now, I simply respond to data coming in and store it in a buffer for later processing. This is a multi-threaded application, so I will process the data later, massage it, or return a response to the client.
void DataAvailable( struct bufferevent* bufferEventObj, void* arg )
{
const U32 MaxBufferSize = 8192;
MyObj* This = (MyObj*) arg;
U8 data[ MaxBufferSize ];
size_t numBytesreceived;
/* Read 8k at a time and send it to all connected clients. */
while( 1 )
{
numBytesreceived = bufferevent_read( bufferEventObj, data, sizeof( data ) );
if( numBytesreceived <= 0 ) // nothing to send
{
break;
}
if( This )
{
This->OnDataReceived( data, numBytesreceived );
}
}
}
the last thing that happens, once I look up my data, package into a buffer, and then on a threaded timeslice I do this:
bufferevent_write( m_bufferEvent, buffer, bufferOffset );
It never, ever sends the first time. To get it to send, I have to send a second buffer full of data.
This behavior is killing me and I have spent a lot of hours on it. Any ideas?
//-------------------------------------------------------
I finally gave up and used this hack instead... there just was not enough info to tell me why libevent wasn't writing to the socket. This works just fine.
int result = send( m_connectionId, (const char* )buffer, bufferOffset, 0 );
I met the problem, too! I spent one day on this problem. At last, I solved it.
When the thread you call event_base_dispatch, it will be asleep until any semaphore wakes it up. So, when it sleeps, you call bufferevent_write, the bufferevent's fd adds to the event list, but it won't be epoll until next time. So you must send semaphore to wake up the dispatch thread after you called bufferevent_write. The way you can use is set up an event bind pair socket and add it to event_base. Then send 1 byte anytime when you need to wake up the disptach thread.

Watching a file for changes in Windows 7

I have a Visual Studio 2008 C++ application for Windows 7 where I would like to watch a file for changes.
The file may be changed like this:
std::ofstream myfile_;
void LogData( const char* data )
{
myfile_ << data << std::endl;
// note that the file output buffer is flushed by std::endl, but the file is not closed.
}
I have tried watching the file's directory using both ReadDirectoryChangesW and FindFirstChangeNotification with FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_LAST_ACCESS | FILE_NOTIFY_CHANGE_SECURITY | FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_FILE_NAME flags. But, neither of those APIs will detect file changes until the file handle is actually closed.
Is there any way to detect a change when the file is actually written, but before the file handle is closed?
Thanks,
PaulH
Update
On #Edwin's suggestion, I'm attempting to use the Journal feature. But, I'm having a couple issues.
FSCTL_READ_USN_JOURNAL returns instantly. It does not block. (though, this may be related to issue 2)
Regardless of where my handle points to (I have tried opening a handle to the directory "C:\Foo\Bar" and to the file "C:\Foo\Bar\MyFile.txt") I seem to get any changes made to the the C: volume. Is there a way to limit what FSCTL_READ_USN_JOURNAL gives me?
Error checking omitted for brevity.
boost::shared_ptr< void > directory(
::CreateFileW( L"C:\\Foo\\Bar\\Myfile.txt",
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL ),
::CloseHandle );
USN_JOURNAL_DATA journal = { 0 };
DWORD returned = 0;
::DeviceIoControl( directory.get(), FSCTL_QUERY_USN_JOURNAL, NULL, 0, &journal, sizeof( journal ), &returned, NULL );
BYTE buffer[ 4096 ] = { 0 };
READ_USN_JOURNAL_DATA read = { 0, USN_REASON_DATA_EXTEND | USN_REASON_DATA_TRUNCATION, FALSE, 0, 0, journal.UsnJournalID };
::DeviceIoControl( directory.get(), FSCTL_READ_USN_JOURNAL, &read, sizeof( read ), &buffer, sizeof( buffer ), &returned, NULL );
for( USN_RECORD* record = ( USN_RECORD* )( buffer + sizeof( USN ) );
( ( BYTE* )record - buffer ) < returned;
record = ( USN_RECORD* )( ( BYTE* )record + record->RecordLength ) )
{
ATLTRACE( L"%s\r\n", record->FileName );
}
Example output (none of these are in the C:\Foo\Bar directory):
AeXProcessList.txt`
AeXProcessList.txt`
AeXAMInventory.txt`
AeXAMInventory.txt`
AeXProcessList.txt`
AeXProcessList.txtP
access.log`
mysqlgeneral.log
E804.tmp
apache_error.log
E804.tmp
CHROME.EXE-5FE9909D.pfh
CHROME.EXE-5FE9909D.pfp
SyncData.sqlite3-journal
CHROME.EXE-5FE9909D.pfh
CHROME.EXE-5FE9909D.pfP
1211.tmp
SyncData.sqlite3-journal
AeXAMInventory.txt
You can use
Change Journal Operations
(see MSDN docs)
That's the only 100% garanteed way to detect any change in the filesystem.
But it's pretty complicated.
To read data for a specific file or directory, I believe you want to use FSCTL_READ_FILE_USN_DATA instead of FSCTL_READ_USN_JOURNAL. I believe the latter always retrieves data for an entire volume. That does not, however, fill in the TimeStamp, Reason, or SourceInfo fields of the USN record you get. If you need those, I believe you can read them with FSCTL_READ_USN_JOURNAL, specifying the exact USN you want to read.
No, because until you close the file handle there is no guarantee a single byte ever gets written by the OS.
The exception would probably be by calling flush on your file handle and then call the Windows API function FlushFileBuffers, but unless the program writing into the file does this no bytes probably get written.
This can be done with a filter driver that monitors the FASTIO_WRITE and IRP_MJ_WRITE operations. Here is a pretty good how-to article.