Attaching a callback to the output element of the Remote IO - core-audio

I want to capture audio from the microphone of an iOS device and write it to a .caf file.
I'm able to connect a Remote IO audio unit to a multichannel mixer unit (MCMU) and attach a callback to the input of the MCMU. Inside that callback I can successfully write the audio data from the mic to a file using ExtAudioFileAsyncWrite().
I want to simplify things and remove the MCMU from the picture. My thinking is I can simply attach a callback to the output bus of the Remote IO's input scope and inside that callback call ExtAudioFileAsyncWrite().
However when I try this ExtAudioFileAsyncWrite() returns a -50 (paramError).
Is it not possible to attach a callback to the output bus of the input element of the Remote IO?

It is possible. You'll want to use AudioUnitSetProperty to set the kAudioOutputUnitProperty_SetInputCallback property. This callback will function much like a render callback, but will be called whenever the RemoteIO / mic has some new data for you (instead of as a request for data from your program).
Example:
AURenderCallbackStruct callbackInfo = {YourInputCallback, NULL};
AudioUnitSetProperty(remoteIO,
kAudioOutputUnitProperty_SetInputCallback,
kAudioUnitScope_Global,
0,
&callbackInfo,
sizeof(callbackInfo));
This will make the RemoteIO / mic call YourInputCallback whenever it has a new batch of samples. You can use this callback to call ExtAudioFileWriteAsync as you did before. Note that you'll have to call AudioUnitRender on the RemoteIO as well, to get the new samples out of it.
Regarding the -50 error, that's not a very helpful error diagnostic. It basically just says "there was an error with one of your parameters". Most likely your ExtAudioFile was NULL or not set up properly (in which case, one of the ExtAudioFile* functions you used on it earlier would have returned a more helpful error code you can use to diagnose it).

Related

Can I call multiple IOCTL's at the same time? (Windows Driver)

I have searched widely, I am writing a network filter and I am putting my registry filter in the same driver. Can I call multiple IOCTL's of the same driver at the same time? Would it be better if I separated my network filter and registry filter?
Open the device using FILE_FLAG_OVERLAPPED.
Then, when sending the IOCTL, use the Overlapped argument. Then the call will return immediately (async) and you can either wait (using WaitForSingleObject), call more things, or do whatever. Beware that the way the data is returned may have some gotchas in this case, depending on the use case.
OVERLAPPED async_data = { 0 };
async_data.hEvent = event_handle;
if (DeviceIoControl(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesReturned, &async_data)
{
// do stuff, more deviceiocontrol if you want
WaitForSingleObjects(async_data.hEvent, INFINITE);
// We wait until it finishes
}
// Handle error

The renderer thread don't call SbDecodeTargetGetInfo() while playing 360 video

While testing 360 video on our device with cobalt, the application renderer thread will call function SbPlayerGetCurrentFrame() frequently, but there is no SbDecodeTargetGetInfo() and SbDecodeTargetRelease() even we returned SbDecodeTarget object by function SbPlayerGetCurrentFrame(). In howto_decode_to_texture.md, it told that:
Once the application has acquired a valid SbDecodeTarget object through a call to SbPlayerGetCurrentFrame(), it will call SbDecodeTargetGetInfo() on it.
Does this mean that we don't return a valid SbDecodeTarget in function SbPlayerGetCurrentFrame(), if so, how does renderer thread check the SbDecodeTarget is valid or not?
The Cobalt version is 10.56829.
I found that we called SbPlayerGetCurrentFrame() without return the correct decode target, so that the renderer thread get invalid target object and don't call SbDecodeTargetGetInfo() and SbDecodeTargetRelease()

usb: why my f_uvc doesn't answer GET_DEF request?

I need to implement uvc1.5 spec in my device, I choose linux3.4 as my kernel, and I want to use the drivers/usb/gadget/webcam.c
as my function driver. But it doesn't function properly.
According to the signals captured by wireshark, when the host sends the GET_DEF request to the device, my device answer -ENOENT which results in a failure to the enumeration.
I find out that when the composite.c receives this kind of requests, it will forward them to f->set_up to continue.
The main part of f->set_up is:
uvc->event_setup_out = !(ctrl->bRequestType & USB_DIR_IN);
uvc->event_length = le16_to_cpu(ctrl->wLength);
memset(&v4l2_event, 0, sizeof(v4l2_event));
v4l2_event.type = UVC_EVENT_SETUP;
memcpy(&uvc_event->req, ctrl, sizeof(uvc_event->req));
v4l2_event_queue(&uvc->vdev, &v4l2_event);
The call of v4l2_event_queue is what puzzles me: who will handle this event?
I didn't see any code doing such event related initialization work.....
And my question is how to handle this event properly, so I can answer the GET_DEF request ?
It's a V4L2 event you should deal with in another place. You can receive v4l2 event through
rt = ioctl(dev->fd, VIDIOC_DQEVENT,&v4l2_event);
Then you can parse this v4l2_event, it maybe GET_CUR, GER_LEN,etc. So you can response those requests by yourself define.

OSX Cocoa input source detect change

Does anyone know how to detect when the user changes the current input source in OSX?
I can call TISCopyCurrentKeyboardInputSource() to find out which input source ID is being used like this:
TISInputSourceRef isource = TISCopyCurrentKeyboardInputSource();
if ( isource == NULL )
{
cerr << "Couldn't get the current input source\n.";
return -1;
}
CFStringRef id = (CFStringRef)TISGetInputSourceProperty(
isource,
kTISPropertyInputSourceID);
CFRelease(isource);
If my input source is "German", then id ends up being "com.apple.keylayout.German", which is mostly what I want. Except:
The results of TISCopyCurrentKeyboardInputSource() doesn't change once my process starts? In particular, I can call TISCopyCurrentKeyboardInputSource() in a loop and switch my input source, but TISCopyCurrentKeyboardInputSource() keeps returning the input source that my process started with.
I'd really like to be notified when the input source changes. Is there any way of doing this? To get a notification or an event of some kind telling me that the input source has been changed?
You can observe the NSTextInputContextKeyboardSelectionDidChangeNotification notification posted by NSTextInputContext to the default Cocoa notification center. Alternatively, you can observe the kTISNotifySelectedKeyboardInputSourceChanged notification delivered via the Core Foundation distributed notification center.
However, any such change starts in a system process external to your app. The system then notifies the frameworks in each app process. The frameworks can only receive such notifications when it is allowed to run its event loop. Likewise, if you're observing the distributed notification yourself, that can only happen when the event loop (or at least the main thread's run loop) is allowed to run.
So, that explains why running a loop which repeatedly checks the result of TISCopyCurrentKeyboardInputSource() doesn't work. You're not allowing the frameworks to monitor the channel over which it would be informed of the change. If, rather than a loop, you were to use a repeating timer with a low enough frequency that other stuff has a chance to run, and you returned control to the app's event loop, you would see the result of TISCopyCurrentKeyboardInputSource() changing.

Uploading a file using post() method of QNetworkAccessManager

I'm having some trouble with a Qt application; specifically with the QNetworkAccessManager class. I'm attempting to perform a simple HTTP upload of a binary file using the post() method of the QNetworkAccessManager. The documentation states that I can give a pointer to a QIODevice to post(), and that the class will transmit the data found in the QIODevice. This suggests to me that I ought to be able to give post() a pointer to a QFile. For example:
QFile compressedFile("temp");
compressedFile.open(QIODevice::ReadOnly);
netManager.post(QNetworkRequest(QUrl("http://mywebsite.com/upload") ), &compressedFile);
What seems to happen on the Windows system where I'm developing this is that my Qt application pushes the data from the QFile, but then doesn't complete the request; it seems to be sitting there waiting for more data to show up from the file. The post request isn't "closed" until I manually kill the application, at which point the whole file shows up at my server end.
From some debugging and research, I think this is happening because the read() operation of QFile doesn't return -1 when you reach the end of the file. I think that QNetworkAccessManager is trying to read from the QIODevice until it gets a -1 from read(), at which point it assumes there is no more data and closes the request. If it keeps getting a return code of zero from read(), QNetworkAccessManager assumes that there might be more data coming, and so it keeps waiting for that hypothetical data.
I've confirmed with some test code that the read() operation of QFile just returns zero after you've read to the end of the file. This seems to be incompatible with the way that the post() method of QNetworkAccessManager expects a QIODevice to behave. My questions are:
Is this some sort of limitation with the way that QFile works under Windows?
Is there some other way I should be using either QFile or QNetworkAccessManager to push a file via post()?
Is this not going to work at all, and will I have to find some other way to upload my file?
Any suggestions or hints would be appreciated.
Update: It turns out that I had two different problems: one on the client side and one on the server side. On the client side, I had to ensure that my QFile object stayed around for the duration of the network transaction. The post() method of QNetworkAccessManager returns immediately but isn't actually finished immediately. You need to attach a slot to the finished() signal of QNetworkAccessManager to determine when the POST is actually finished. In my case it was easy enough to keep the QFile around more or less permanently, but I also attached a slot to the finished() signal in order to check for error responses from the server.
I attached the signal to the slot like this:
connect(&netManager, SIGNAL(finished(QNetworkReply*) ), this, SLOT(postFinished(QNetworkReply*) ) );
When it was time to send my file, I wrote the post code like this (note that compressedFile is a member of my class and so does not go out of scope after this code):
compressedFile.open(QIODevice::ReadOnly);
netManager.post(QNetworkRequest(QUrl(httpDestination.getCString() ) ), &compressedFile);
The finished(QNetworkReply*) signal from QNetworkAccessManager triggers my postFinished(QNetworkReply*) method. When this happens, it's safe for me to close compressedFile and to delete the data file represented by compressedFile. For debugging purposes I also added a few printf() statements to confirm that the transaction is complete:
void CL_QtLogCompressor::postFinished(QNetworkReply* reply)
{
QByteArray response = reply->readAll();
printf("response: %s\n", response.data() );
printf("reply error %d\n", reply->error() );
reply->deleteLater();
compressedFile.close();
compressedFile.remove();
}
Since compressedFile isn't closed immediately and doesn't go out of scope, the QNetworkAccessManager is able to take as much time as it likes to transmit my file. Eventually the transaction is complete and my postFinished() method gets called.
My other problem (which also contributed to the behavior I was seeing where the transaction never completed) was that the Python code for my web server wasn't fielding the POST correctly, but that's outside the scope of my original Qt question.
You're creating compressedFile on the stack, and passing a pointer to it to your QNetworkRequest (and ultimately your QNetworkAccessManager). As soon as you leave the method you're in, compressedFile is going out of scope. I'm surprised it's not crashing on you, though the behavior is undefined.
You need to create the QFile on the heap:
QFile *compressedFile = new QFile("temp");
You will of course need to keep track of it and then delete it once the post has completed, or set it as the child of the QNetworkReply so that it it gets destroyed when the reply gets destroyed later:
QFile *compressedFile = new QFile("temp");
compressedFile->open(QIODevice::ReadOnly);
QNetworkReply *reply = netManager.post(QNetworkRequest(QUrl("http://mywebsite.com/upload") ), compressedFile);
compressedFile->setParent(reply);
You can also schedule automatic deletion of a heap-allocated file using signals/slots
QFile* compressedFile = new QFile(...);
QNetworkReply* reply = Manager.post(...);
// This is where the tricks is
connect(reply, SIGNAL(finished()), reply, SLOT(deleteLater());
connect(reply, SIGNAL(destroyed()), compressedFile, SLOT(deleteLater());
IMHO, it is much more localized and encapsulated than having to keep around your file in the outer class.
Note that you must remove the first connect() if you have your postFinished(QNetworkReply*) slot, in which you must then not forget to call reply->deleteLater() inside it for the above to work.

Resources