what is the wrong in this code(openAl in vc++) - visual-c++-6

how are you all?
i need your help
i have this code
#include <conio.h>
#include <stdlib.h>
#include <stdio.h>
#include <al.h>
#include <alc.h>
#include <alut.h>
#pragma comment(lib, "openal32.lib")
#pragma comment(lib, "alut.lib")
/*
* These are OpenAL "names" (or "objects"). They store and id of a buffer
* or a source object. Generally you would expect to see the implementation
* use values that scale up from '1', but don't count on it. The spec does
* not make this mandatory (as it is OpenGL). The id's can easily be memory
* pointers as well. It will depend on the implementation.
*/
// Buffers to hold sound data.
ALuint Buffer;
// Sources are points of emitting sound.
ALuint Source;
/*
* These are 3D cartesian vector coordinates. A structure or class would be
* a more flexible of handling these, but for the sake of simplicity we will
* just leave it as is.
*/
// Position of the source sound.
ALfloat SourcePos[] = { 0.0, 0.0, 0.0 };
// Velocity of the source sound.
ALfloat SourceVel[] = { 0.0, 0.0, 0.0 };
// Position of the Listener.
ALfloat ListenerPos[] = { 0.0, 0.0, 0.0 };
// Velocity of the Listener.
ALfloat ListenerVel[] = { 0.0, 0.0, 0.0 };
// Orientation of the Listener. (first 3 elements are "at", second 3 are "up")
// Also note that these should be units of '1'.
ALfloat ListenerOri[] = { 0.0, 0.0, -1.0, 0.0, 1.0, 0.0 };
/*
* ALboolean LoadALData()
*
* This function will load our sample data from the disk using the Alut
* utility and send the data into OpenAL as a buffer. A source is then
* also created to play that buffer.
*/
ALboolean LoadALData()
{
// Variables to load into.
ALenum format;
ALsizei size;
ALvoid* data;
ALsizei freq;
ALboolean loop;
// Load wav data into a buffer.
alGenBuffers(1, &Buffer);
if(alGetError() != AL_NO_ERROR)
return AL_FALSE;
alutLoadWAVFile((ALbyte *)"C:\Users\Toshiba\Desktop\Graduation Project\OpenAL\open AL test\wavdata\FancyPants.wav", &format, &data, &size, &freq, &loop);
alBufferData(Buffer, format, data, size, freq);
alutUnloadWAV(format, data, size, freq);
// Bind the buffer with the source.
alGenSources(1, &Source);
if(alGetError() != AL_NO_ERROR)
return AL_FALSE;
alSourcei (Source, AL_BUFFER, Buffer );
alSourcef (Source, AL_PITCH, 1.0 );
alSourcef (Source, AL_GAIN, 1.0 );
alSourcefv(Source, AL_POSITION, SourcePos);
alSourcefv(Source, AL_VELOCITY, SourceVel);
alSourcei (Source, AL_LOOPING, loop );
// Do another error check and return.
if(alGetError() == AL_NO_ERROR)
return AL_TRUE;
return AL_FALSE;
}
/*
* void SetListenerValues()
*
* We already defined certain values for the Listener, but we need
* to tell OpenAL to use that data. This function does just that.
*/
void SetListenerValues()
{
alListenerfv(AL_POSITION, ListenerPos);
alListenerfv(AL_VELOCITY, ListenerVel);
alListenerfv(AL_ORIENTATION, ListenerOri);
}
/*
* void KillALData()
*
* We have allocated memory for our buffers and sources which needs
* to be returned to the system. This function frees that memory.
*/
void KillALData()
{
alDeleteBuffers(1, &Buffer);
alDeleteSources(1, &Source);
alutExit();
}
int main(int argc, char *argv[])
{
printf("MindCode's OpenAL Lesson 1: Single Static Source\n\n");
printf("Controls:\n");
printf("p) Play\n");
printf("s) Stop\n");
printf("h) Hold (pause)\n");
printf("q) Quit\n\n");
// Initialize OpenAL and clear the error bit.
alutInit(NULL, 0);
alGetError();
// Load the wav data.
if(LoadALData() == AL_FALSE)
{
printf("Error loading data.");
return 0;
}
SetListenerValues();
// Setup an exit procedure.
atexit(KillALData);
// Loop.
ALubyte c = ' ';
while(c != 'q')
{
c = getche();
switch(c)
{
// Pressing 'p' will begin playing the sample.
case 'p': alSourcePlay(Source); break;
// Pressing 's' will stop the sample from playing.
case 's': alSourceStop(Source); break;
// Pressing 'h' will pause the sample.
case 'h': alSourcePause(Source); break;
};
}
return 0;
}
and it is run will>>but i cant here any thing>>
also i am new in programong and wont to program a virtual reality sound in my graduation project >>>and start to learn opeal and vc++
but i dont how to start and from where i must begin
and i want to ask if i need to learn about API win ?? and if i need how i can learn that>>
thank you alote
and i am sorry coz of my english

I recently tried running this very same sample source code from devmaster.net as well. Make sure to change the #includes to reflect the appropriate paths to your OpenAL header files. If you are using C++ and not C, you will need to change #include <conio.h> to be #include <iostream> and use getchar() instead of getche().
Also, I've discovered that the version of alut.h that I have declares the alutLoadWAVFile function to only accept 5 parameters, not 6. The 6th parameter in this example (the loop variable) makes for too many arguments to the function (at least in my version of OpenAL).
{Edited note: Okay, I just discovered that apparently, the Windows version of OpenAL requires the 6th boolean loop parameter, while the Mac version of OpenAL does not.}
Hope this helps.

Related

How to use GDCM to write voxel data, slice by slice?

In all the examples I've seen for GDCM on how to write image data, they always consider the image volume as a single whole, cohesive buffer. The basic structure is along the lines
#include "gdcmImage.h"
#include "gdcmImageWriter.h"
#include "gdcmFileDerivation.h"
#include "gdcmUIDGenerator.h"
int write_image(...)
{
size_t width = ..., height = ..., depth = ...;
auto im = new gdcm::Image;
std::vector<...> buffer;
auto p = buffer.data();
im->SetNumberOfDimensions(3);
im->SetDimension(0, width);
im->SetDimension(1, height);
im->SetDimension(1, depth);
im->GetPixelFormat().SetSamplesPerPixel(...);
im->SetPhotometricInterpretation( gdcm::PhotometricInterpretation::... );
unsigned long l = im->GetBufferLength();
if( l != width * height * depth * sizeof(...) ){ return SOME_ERROR; }
gdcm::DataElement pixeldata( gdcm::Tag(0x7fe0,0x0010) );
pixeldata.SetByteValue( buffer.data(), buffer.size()*sizeof(*buffer.data()) );
im->SetDataElement( pixeldata );
gdcm::UIDGenerator uid;
auto file = new gdcm::File;
gdcm::FileDerivation fd;
const char UID[] = ...;
fd.AddReference( ReferencedSOPClassUID, uid.Generate() );
fd.SetFile( *file );
// If all Code Value are ok the filter will execute properly
if( !fd.Derive() ){ return SOME_ERROR; }
gdcm::ImageWriter w;
w.SetImage( *im );
w.SetFile( fd.GetFile() );
// Set the filename:
w.SetFileName( "some_image.dcm" );
if( !w.Write() ){ return SOME_ERROR; }
return 0;
}
The problem I'm facing with this approach is, that the amount of image data I need to store easily exceeds the available system memory, if an additional copy is being made; specifically these are volumes of 4096×4096×2048 voxels of 12 bits each, so about 48GiB of data in memory.
However the approach of using gdcm::DataElement and gdcm::Image::SetDataElement will obviously create a full copy of the data in buffer, which is troublesome. For one, the data as produced by my imaging system does not reside in memory as a cohesive, singular block of values; it is split into slices. And the total amount of data fits into the memory of the systems being used only once.
It is trivial for me, to read in the data slice by slice, which would cut down the memory requirements significantly. However I'm at a loss, how that'd be done with GDCM.
Did you check gdcm::FileStreamer:
http://gdcm.sourceforge.net/3.0/html/classgdcm_1_1FileStreamer.xhtml
See typical setup at:
https://github.com/malaterre/GDCM/blob/master/Examples/Csharp/FileStreaming.cs
The example show how to create an out of memory private element, but you can do the same with public DataElement.
A more complex example to read where Pixel Data is written in chunks is at:
https://github.com/malaterre/GDCM/blob/master/Examples/Csharp/FileChangeTS.cs#L126-L154

Non-blockings reads/writes to stdin/stdout in C on Linux or Mac

I have two programs communicating via named pipes (on a Mac), but the buffer size of named pipes is too small. Program 1 writes 50K bytes to pipe 1 before reading pipe 2. Named pipes are 8K (on my system) so program 1 blocks until the data is consumed. Program 2 reads 20K bytes from pipe 1 and then writes 20K bytes to pipe2. Pipe2 can't hold 20K so program 2 now blocks. It will only be released when program 1 does its reads. But program 1 is blocked waiting for program 2. deadlock
I thought I could fix the problem by creating a gasket program that reads stdin non-blocking and writes stdout non-blocking, temporarily storing the data in a large buffer. I tested the program using cat data | ./gasket 0 | ./gasket 1 > out, expecting out to be a copy of data. However, while the first invocation of gasket works as expected, the read in the second program returns 0 before all the data is consumed and never returns anything other than 0 in follow on calls.
I tried the code below both on a MAC and Linux. Both behave the same. I've added logging so that I can see that the fread from the second invocation of gasket starts getting no data even though it has not read all the data written by the first invocation.
#include <stdio.h>
#include <fcntl.h>
#include <time.h>
#include <stdlib.h>
#include <unistd.h>
#define BUFFER_SIZE 100000
char buffer[BUFFER_SIZE];
int elements=0;
int main(int argc, char **argv)
{
int total_read=0, total_write=0;
FILE *logfile=fopen(argv[1],"w");
int flags = fcntl(fileno(stdin), F_GETFL, 0);
fcntl(fileno(stdin), F_SETFL, flags | O_NONBLOCK);
flags = fcntl(fileno(stdout), F_GETFL, 0);
fcntl(fileno(stdout), F_SETFL, flags | O_NONBLOCK);
while (1) {
int num_read=0;
if (elements < (BUFFER_SIZE-1024)) { // space in buffer
num_read = fread(&buffer[elements], sizeof(char), 1024, stdin);
elements += num_read;
total_read += num_read;
fprintf(logfile,"read %d (%d) elements \n",num_read, total_read); fflush(logfile);
}
if (elements > 0) { // something in buffer that we can write
int num_written = fwrite(&buffer[0],sizeof(char),elements, stdout); fflush(stdout);
total_write += num_written;
fprintf(logfile,"wrote %d (%d) elements \n",num_written, total_write); fflush(logfile);
if (num_written > 0) { // copy data to top of buffer
for (int i=0; i<(elements-num_written); i++) {
buffer[i] = buffer[i+num_written];
}
elements -= num_written;
}
}
}
}
I guess I could make the gasket multi-threaded and use blocking reads in one thread and blocking writes in the other, but I would like to understand why non-blocking IO seems to break for me.
Thanks!
My general solution to any IPC project is to make the client and server non-blocking I/O. To do so requires queuing data both on writing and reading, to handle cases where the OS can't read/write, or can only read/write a portion of your message.
The code below will probably seem like EXTREME overkill, but if you get it working, you can use it the rest of your career, whether for named pipes, sockets, network, you name it.
In pseudo-code:
typedef struct {
const char* pcData, * pcToFree; // pcData may no longer point to malloc'd region
int iToSend;
} DataToSend_T;
queue of DataToSend_T qdts;
// Caller will use malloc() to allocate storage, and create the message in
// that buffer. MyWrite() will free it now, or WritableCB() will free it
// later. Either way, the app must NOT free it, and must not even refer to
// it again.
MyWrite( const char* pcData, int iToSend ) {
iSent = 0;
// Normally the OS will tell select() if the socket is writable, but if were hugely
// compute-bound, then it won't have a chance to. So let's call WritableCB() to
// send anything in our queue that is now sendable. We have to send the data in
// order, of course, so can't send the new data until the entire queue is done.
WritableCB();
if ( qdts has no entries ) {
iSent = write( pcData, iToSend );
// TODO: check error
// Did we send it all? We're done.
if ( iSent == iToSend ) {
free( pcData );
return;
}
}
// OK, either 1) we had stuff queued already meaning we can't send, or 2)
// we tried to send but couldn't send it all.
add to queue qdts the DataToSend ( pcData + iSent, pcData, iToSend - iSent );
}
WritableCB() {
while ( qdts has entries ) {
DataToSend_T* pdts = qdts head;
int iSent = write( pdts->cData, pdts->iToSend );
// TODO: check error
if ( iSent == pdts->iToSend ) {
free( pdts->pcToFree );
pop the front node off qdts
else {
pdts->pcData += iSent;
pdts->iToSend -= iSent;
return;
}
}
}
// Off-subject but I like a TINY buffer as an original value, that will always
// exercise the "buffer growth" code for almost all usage, so we're sure it works.
// If the initial buffer size is like 1M, and almost never grows, then the grow code
// may be buggy and we won't know until there's a crash years later.
int iBufSize = 1, iEnd = 0; iEnd is the first byte NOT in a message
char* pcBuf = malloc( iBufSize );
ReadableCB() {
// Keep reading the socket until there's no more data. Grow buffer if necessary.
while (1) {
int iRead = read( pcBuf + iEnd, iBufSize - iEnd);
// TODO: check error
iEnd += iRead;
// If we read less than we had space for, then read returned because this is
// all the available data, not because the buffer was too small.
if ( iRead < iBufSize - iEnd )
break;
// Otherwise, double the buffer and try reading some more.
iBufSize *= 2;
pcBuf = realloc( pcBuf, iBufSize );
}
iStart = 0;
while (1) {
if ( pcBuf[ iStart ] until iEnd-1 is less than a message ) {
// If our partial message isn't at the front of the buffer move it there.
if ( iStart ) {
memmove( pcBuf, pcBuf + iStart, iEnd - iStart );
iEnd -= iStart;
}
return;
}
// process a message, and advance iStart by the size of that message.
}
}
main() {
// Do your initial processing, and call MyWrite() to send and/or queue data.
while (1) {
select() // see man page
if ( the file handle is readable )
ReadableCB();
if ( the file handle is writable )
WritableCB();
if ( the file handle is in error )
// handle it;
if ( application is finished )
exit( EXIT_SUCCESS );
}
}

Arduino/MPU6050/AdafruitMotorShieldV2: script hangs/freezes when turn on motors

I'm a newby to robotics and electronics in general, so please don't assume I tried anything you might think is obvious.
I'm trying to create a cart which will basically run around by itself (simple AI routines to avoid obstacles, go from pt. A to pt. B around corners, follow lines, etc.). I'm putting together an Adafruit Arduino Uno R3 with the Adafruit Motor Shield v2 and an MPU-6050. I'm using the "breadboard" on the Motor Shield for the circuitry, soldering everything there.
I can get all the pieces working independently with their own scripts: the Motor Shield drives the 4 motors as expected using the Adafruit library; I'm using the "JRowberg" library for the MPU-6050, and started with the example MPU6050_DMP6.ino, which works fine as long as the cart motors are turned off. My only changes in the example script below are motor startup and some simple motor commands.
As long as I leave the switch which powers the motors off, everything seems fine: it outputs to the Serial window continuously with Euler data which, I assume, is correct. However, a few seconds after I turn on the power to the motors (and the wheels start turning), it just hangs/freezes: the output to the Serial window stops (sometimes in mid-line), and the wheels keep turning at the speed of their last change. Sometimes I see "FIFO overflow" errors, but not always. Sometimes I see "nan" for some of the floating point values before it hangs, but not always.
Some things I've tried, all of which changed noting:
* I've swapped out the MPU-6050 board for another from the same manufacturer.
* I've tried moving the MPU-6050 away from the motors using a ribbon cable.
* I've changed the I2C clock using JRowber's advice (a change in a .h file and changing the value of the TWBR variable), but I don't think I've tried all possible values.
* I've changed the speed of the MotorShield in the AFMS.begin() command, although, again, there are probably other values I haven't tried, and I'm not sure how in-sync this and the TWBR value need to be.
And some other things, all to no avail.
Below is an example script which fails for me:
#include "I2Cdev.h"
#include "MPU6050_6Axis_MotionApps20.h"
// is used in I2Cdev.h
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
#include "Wire.h"
#endif
#include "Adafruit_MotorShield.h"
#include "utility/Adafruit_PWMServoDriver.h"
#define DEBUG 1
MPU6050 mpu;
#define OUTPUT_READABLE_EULER
#define LED_PIN 13
bool blinkState = false;
bool dmpReady = false; // set true if DMP init was successful
uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU
uint8_t devStatus; // return status after each device operation (0 = success, !0 = error)
uint16_t packetSize; // expected DMP packet size (default is 42 bytes)
uint16_t fifoCount; // count of all bytes currently in FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer
Quaternion q; // [w, x, y, z] quaternion container
VectorInt16 aa; // [x, y, z] accel sensor measurements
VectorInt16 aaReal; // [x, y, z] gravity-free accel sensor measurements
VectorInt16 aaWorld; // [x, y, z] world-frame accel sensor measurements
VectorFloat gravity; // [x, y, z] gravity vector
float euler[3]; // [psi, theta, phi] Euler angle container
float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector
uint8_t teapotPacket[14] = { '$', 0x02, 0,0, 0,0, 0,0, 0,0, 0x00, 0x00, '\r', '\n' };
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
#define NUM_MOTORS 4
#define MOTOR_FL 0
#define MOTOR_FR 1
#define MOTOR_RR 2
#define MOTOR_RL 3
Adafruit_DCMotor *myMotors[NUM_MOTORS] = {
AFMS.getMotor(1),
AFMS.getMotor(2),
AFMS.getMotor(3),
AFMS.getMotor(4),
};
#define CHANGE_SPEED_TIME 500
long changeSpeedMillis = 0;
int curSpeed = 30;
volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high
void dmpDataReady() {
mpuInterrupt = true;
}
void setup() {
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
Wire.begin();
TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz)
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
Fastwire::setup(400, true);
#endif
Serial.begin(115200);
while (!Serial); // wait for Leonardo enumeration, others continue immediately
// start the motor shield.
AFMS.begin(); // create with the default frequency 1.6KHz
// AFMS.begin(4000); // OR with a different frequency, say 4KHz
// kill all the motors.
myMotors[MOTOR_FL]->run(BRAKE);
myMotors[MOTOR_FL]->setSpeed(0);
myMotors[MOTOR_FR]->run(BRAKE);
myMotors[MOTOR_FR]->setSpeed(0);
myMotors[MOTOR_RR]->run(BRAKE);
myMotors[MOTOR_RR]->setSpeed(0);
myMotors[MOTOR_RL]->run(BRAKE);
myMotors[MOTOR_RL]->setSpeed(0);
Serial.println("Motor Shield ready!");
Serial.println(F("Initializing I2C devices..."));
mpu.initialize();
// verify connection
Serial.println(F("Testing device connections..."));
Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));
// wait for ready
Serial.println(F("\nSend any character to begin DMP programming and demo: "));
while (Serial.available() && Serial.read()); // empty buffer
while (!Serial.available()); // wait for data
while (Serial.available() && Serial.read()); // empty buffer again
// load and configure the DMP
Serial.println(F("Initializing DMP..."));
devStatus = mpu.dmpInitialize();
// supply your own gyro offsets here, scaled for min sensitivity
mpu.setXGyroOffset(220);
mpu.setYGyroOffset(76);
mpu.setZGyroOffset(-85);
mpu.setZAccelOffset(1788); // 1688 factory default for my test chip
// make sure it worked (returns 0 if so)
if (devStatus == 0) {
// turn on the DMP, now that it's ready
Serial.println(F("Enabling DMP..."));
mpu.setDMPEnabled(true);
// enable Arduino interrupt detection
Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)..."));
attachInterrupt(0, dmpDataReady, RISING);
mpuIntStatus = mpu.getIntStatus();
// set our DMP Ready flag so the main loop() function knows it's okay to use it
Serial.println(F("DMP ready! Waiting for first interrupt..."));
dmpReady = true;
// get expected DMP packet size for later comparison
packetSize = mpu.dmpGetFIFOPacketSize();
} else {
// ERROR!
// 1 = initial memory load failed
// 2 = DMP configuration updates failed
// (if it's going to break, usually the code will be 1)
Serial.print(F("DMP Initialization failed (code "));
Serial.print(devStatus);
Serial.println(F(")"));
}
// configure LED for output
pinMode(LED_PIN, OUTPUT);
}
void loop() {
// if programming failed, don't try to do anything
if (!dmpReady) return;
// wait for MPU interrupt or extra packet(s) available
while (!mpuInterrupt && fifoCount < packetSize) {
// as per Vulpo's post.
delay(10);
if (millis() > changeSpeedMillis) {
curSpeed += 20;
if (curSpeed > 256) {
curSpeed = 30;
}
Serial.print("changing speed to: ");
Serial.println(curSpeed);
myMotors[MOTOR_FL]->run(FORWARD);
myMotors[MOTOR_FL]->setSpeed(curSpeed);
myMotors[MOTOR_FR]->run(FORWARD);
myMotors[MOTOR_FR]->setSpeed(curSpeed);
myMotors[MOTOR_RR]->run(FORWARD);
myMotors[MOTOR_RR]->setSpeed(curSpeed);
myMotors[MOTOR_RL]->run(FORWARD);
myMotors[MOTOR_RL]->setSpeed(curSpeed);
changeSpeedMillis = millis() + CHANGE_SPEED_TIME;
}
}
// reset interrupt flag and get INT_STATUS byte
mpuInterrupt = false;
mpuIntStatus = mpu.getIntStatus();
// get current FIFO count
fifoCount = mpu.getFIFOCount();
// check for overflow (this should never happen unless our code is too inefficient)
if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
// reset so we can continue cleanly
mpu.resetFIFO();
Serial.println(F("FIFO overflow!"));
// otherwise, check for DMP data ready interrupt (this should happen frequently)
} else if (mpuIntStatus & 0x02) {
// wait for correct available data length, should be a VERY short wait
while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();
// read a packet from FIFO
mpu.getFIFOBytes(fifoBuffer, packetSize);
// track FIFO count here in case there is > 1 packet available
// (this lets us immediately read more without waiting for an interrupt)
fifoCount -= packetSize;
#ifdef OUTPUT_READABLE_EULER
// display Euler angles in degrees
mpu.dmpGetQuaternion(&q, fifoBuffer);
mpu.dmpGetEuler(euler, &q);
Serial.print("euler\t");
Serial.print(euler[0] * 180/M_PI);
Serial.print("\t");
Serial.print(euler[1] * 180/M_PI);
Serial.print("\t");
Serial.println(euler[2] * 180/M_PI);
#endif
// blink LED to indicate activity
blinkState = !blinkState;
digitalWrite(LED_PIN, blinkState);
}
}
Have you considered that your troubles are caused by interference from the currents flowing into your motors?
If your motors are DC brush, then more interference may be radiated from the brushes back into your various wires.
As a first step, perhaps let only one motor work and see if hangups diminish in frequency (although, to be sure, you need a 'scope onto a few wires carrying logic signals.

Touch doesnt work with Qt5.1.1 when used with Wayland & qtwayland

I want to make Qt 5.1.1 touch example application work with qtwayland module.
I get the window on display, and also I get the touch traces from Weston. I see qtwayland is also getting triggered with the callback function that is registered for touch-up, touch-down, touch-motion.
But, QT doesn't invoke the QPushButton handler in QT application.
Connect API I am using as below:
connect(ui->b_audio, SIGNAL(pressed()), this, SLOT(on_b_audio_clicked()));
Any clue why this could happen? Please suggest probable problems so that I can explore and debug.
Thanks in Advance.
Bhushan.
In QtWayland, QWaylandInputDevice::touch_frame() passes the touch points to Qt internal window system through QWindowSystemInterface::handleTouchEvent(). Weston does not send WL_TOUCH_FRAME event at all, so the buttons or the QML MouseArea never receive touch event.
You can add the following line to the end of evdev_flush_motion() in weston/src/evdev.c:
notify_touch(master, time, 0, 0, 0, WL_TOUCH_FRAME);
And rewrite the notify_touch() in weston/src/input.c:
WL_EXPORT void
notify_touch(struct weston_seat *seat, uint32_t time, int touch_id,
wl_fixed_t x, wl_fixed_t y, int touch_type)
{
struct weston_compositor *ec = seat->compositor;
struct weston_touch *touch = seat->touch;
struct weston_touch_grab *grab = touch->grab;
struct weston_surface *es;
wl_fixed_t sx, sy;
struct weston_touch *grab_touch = grab->touch;
/* Update grab's global coordinates. */
touch->grab_x = x;
touch->grab_y = y;
switch (touch_type) {
case WL_TOUCH_DOWN:
weston_compositor_idle_inhibit(ec);
seat->num_tp++;
/* the first finger down picks the surface, and all further go
* to that surface for the remainder of the touch session i.e.
* until all touch points are up again. */
if (seat->num_tp == 1) {
es = weston_compositor_pick_surface(ec, x, y, &sx, &sy);
weston_touch_set_focus(seat, es);
} else if (touch->focus) {
es = (struct weston_surface *) touch->focus;
weston_surface_from_global_fixed(es, x, y, &sx, &sy);
} else {
/* Unexpected condition: We have non-initial touch but
* there is no focused surface.
*/
weston_log("touch event received with %d points down"
"but no surface focused\n", seat->num_tp);
return;
}
grab->interface->down(grab, time, touch_id, sx, sy);
if (seat->num_tp == 1) {
touch->grab_serial =
wl_display_get_serial(ec->wl_display);
touch->grab_time = time;
touch->grab_x = x;
touch->grab_y = y;
}
break;
case WL_TOUCH_MOTION:
es = (struct weston_surface *) touch->focus;
if (!es)
break;
weston_surface_from_global_fixed(es, x, y, &sx, &sy);
grab->interface->motion(grab, time, touch_id, sx, sy);
break;
case WL_TOUCH_UP:
weston_compositor_idle_release(ec);
seat->num_tp--;
grab->interface->up(grab, time, touch_id);
break;
case WL_TOUCH_FRAME:
if (grab_touch->focus_resource) {
wl_touch_send_frame(grab_touch->focus_resource);
if (seat->num_tp == 0)
weston_touch_set_focus(seat, NULL);
}
}
}
Meanwhile, I find that weston does not handle multi-touch properly because its mt structure (below) uses an int value 'slot' which can only track the current slot number.
struct {
int slot;
int32_t x[MAX_SLOTS];
int32_t y[MAX_SLOTS];
} mt;
In multi-touch protocol type B, each slot associates with a finger contact and you get multiple slot events in a touch frame, for example, a touch_down frame;
ABS_MT_SLOT
ABS_MT_TRACKING_ID
ABS_MT_POSITION_X
ABS_MT_POSITION_Y
ABS_MT_SLOT
ABS_MT_TRACKING_ID
ABS_MT_POSITION_X
ABS_MT_POSITION_Y
EV_SYN
weston handles events from first slot event to the EV_SYN event, and it call notify_touch() if EV_SYN is encountered. Therefore, weston cannot send the two touch down events sequentially via notify_touch() with different slot number parameter.
In my reimplementation, I change the mt structure:
struct {
int current_slot;
uint32_t num_down_event;
uint32_t num_motion_event;
uint32_t num_up_event;
int slots[MAX_CONTACTS];
int32_t x[MAX_SLOTS];
int32_t y[MAX_SLOTS];
} mt;
num_down_event: track how many fingers touch down
num_motion_event: track how many fingers move
num_up_event: track how many fingers lift up
slots: track slot numbers in every touch frame
This is https://bugreports.qt-project.org/browse/QTBUG-36602 and we are planning to have a workaround in Qt 5.4.0. By the time that we did that, it seems that touch_frame is being sent for touch_motion but not for touch_up. (Testing with latest versions of wayland, weston and libinput)

Setting volumes for multiple streams using Media Foundation

I'm providing audio code for an application that will have multiple streams of audio being played back at the same time. I'm a bit confused by all of the different options, and there are some specific things that I don't quite understand.
I am using the IAudioClient calls to get and set volumes. Is that the best way to get volumes for multiple streams?
It appears that I have to call IAudioClient::Initialize. This function requires a WAVEFORMATEX structure. Are any parameters from that other than the number of channels used in volume setting? Also, it appears that Initialize can only be used once, and volume setting and reading happens many times. Should I save the reference to the IAudioClient and use it each time, or can I release it each time I get or set a volume?
How do I differentiate between two streams being played on the same device (endpoint)?
Here's the code that sets the volume (with the usual checks to make sure each call succeeded eliminated to save space):
hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&DeviceEnumerator));
hr = DeviceEnumerator->GetDevice((wchar_t *)currentPlaybackDevice.id, &pPlaybackDevice);
hr = pPlaybackDevice->Activate(__uuidof(IAudioClient), CLSCTX_INPROC_SERVER, NULL, reinterpret_cast<void **>(&pPlaybackClient));
hr = pPlaybackClient->Initialize(AUDCLNT_SHAREMODE_SHARED, 0, 0, 0, &pWaveFormat, 0);
hr = pPlaybackClient->GetService(__uuidof(IAudioStreamVolume), (void **)&pStreamVolume);
hr = pStreamVolume->GetChannelCount(&channels);
for(UINT32 i = 0; i < channels; i++)
chanVolumes[i] = playbackLevel;
hr = pStreamVolume->SetAllVolumes(channels, chanVolumes);
Number of channels is irrelevant to volume. T adjust volume you need to obtain interfaces IAudioStreamVolume, IChannelAudioVolume. See MSDN writes:
The IAudioStreamVolume interface enables a client to control and
monitor the volume levels for all of the channels in an audio stream.
The client obtains a reference to the IAudioStreamVolume interface on
a stream object by calling the IAudioClient::GetService method with
parameter riid set to REFIID IID_IAudioStreamVolume.
Here is the code snippet for you. It plays synthesized sine wave at louder volume for a few seconds, then continues with updated volume to keep playing quietly.
#define _USE_MATH_DEFINES
#include <math.h>
#include <mmdeviceapi.h>
#include <audioclient.h>
#define _A ATLASSERT
#define __C ATLENSURE_SUCCEEDED
#define __D ATLENSURE_THROW
int _tmain(int argc, _TCHAR* argv[])
{
__C(CoInitialize(NULL));
CComPtr<IMMDeviceEnumerator> pMmDeviceEnumerator;
__C(pMmDeviceEnumerator.CoCreateInstance(__uuidof(MMDeviceEnumerator)));
CComPtr<IMMDevice> pMmDevice;
__C(pMmDeviceEnumerator->GetDefaultAudioEndpoint(eRender, eMultimedia, &pMmDevice));
CComPtr<IAudioClient> pAudioClient;
__C(pMmDevice->Activate(__uuidof(IAudioClient), CLSCTX_ALL, NULL, (VOID**) &pAudioClient));
CComHeapPtr<WAVEFORMATEX> pWaveFormatEx;
__C(pAudioClient->GetMixFormat(&pWaveFormatEx));
static const REFERENCE_TIME g_nBufferTime = 60 * 1000 * 10000i64; // 1 minute
__C(pAudioClient->Initialize(AUDCLNT_SHAREMODE_SHARED, 0, g_nBufferTime, 0, pWaveFormatEx, NULL));
#pragma region Data
CComPtr<IAudioRenderClient> pAudioRenderClient;
__C(pAudioClient->GetService(__uuidof(IAudioRenderClient), (VOID**) &pAudioRenderClient));
UINT32 nSampleCount = (UINT32) (g_nBufferTime / (1000 * 10000i64) * pWaveFormatEx->nSamplesPerSec) / 2;
_A(pWaveFormatEx->wFormatTag == WAVE_FORMAT_EXTENSIBLE);
const WAVEFORMATEXTENSIBLE* pWaveFormatExtensible = (const WAVEFORMATEXTENSIBLE*) (const WAVEFORMATEX*) pWaveFormatEx;
_A(pWaveFormatExtensible->SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT);
// ASSU: Mixing format is IEEE Float PCM
BYTE* pnData = NULL;
__C(pAudioRenderClient->GetBuffer(nSampleCount, &pnData));
FLOAT* pfFloatData = (FLOAT*) pnData;
for(UINT32 nSampleIndex = 0; nSampleIndex < nSampleCount; nSampleIndex++)
for(WORD nChannelIndex = 0; nChannelIndex < pWaveFormatEx->nChannels; nChannelIndex++)
pfFloatData[nSampleIndex * pWaveFormatEx->nChannels + nChannelIndex] = sin(1000.0f * nSampleIndex / pWaveFormatEx->nSamplesPerSec * 2 * M_PI);
__C(pAudioRenderClient->ReleaseBuffer(nSampleCount, 0));
#pragma endregion
CComPtr<ISimpleAudioVolume> pSimpleAudioVolume;
__C(pAudioClient->GetService(__uuidof(ISimpleAudioVolume), (VOID**) &pSimpleAudioVolume));
__C(pSimpleAudioVolume->SetMasterVolume(0.50f, NULL));
_tprintf(_T("Playing Loud\n"));
__C(pAudioClient->Start());
Sleep(5 * 1000);
_tprintf(_T("Playing Quiet\n"));
__C(pSimpleAudioVolume->SetMasterVolume(0.10f, NULL));
Sleep(15 * 1000);
// NOTE: We don't care for termination crash
return 0;
}

Resources