I want to use PortAudio in Game Maker by using a DLL.
I made the callback function in C++ and used that to calculate the frequency of the incoming sample stream. In the DLL I made a few export functions: one that initiates the stream, one that closes the stream and one that gets the frequency variable generated by the callback.
Now when I called the PortAudioStart() function in Game Maker, the game shut down without any warning/error/message of any kind. I put MessageBox()'es in between the lines of code, to check what was the source of the crash. It showed the first, second and third ones, and then it crashed, not even showing the error MessageBox. So it turned out that Pa_StartStream() caused it.
Now I wonder: why does this crash occur, and how can I fix it?
Note: I tested this DLL by letting a C++ program call it, and in that case it worked totally as planned.
I am using GM8.0 and NetBeans 7.3 with the gcc compiler from Cygwin 4.
The start and end functions (leaving out all includes and definitions of global variables):
#define GMEXPORT extern "C" __declspec (dllexport)
GMEXPORT double __cdecl PortAudioStart() {
err = Pa_Initialize();
if( err != paNoError ) goto error;
MessageBoxA(NULL, "1", "PortAudio DLL", MB_ICONINFORMATION);
inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */
if (inputParameters.device == paNoDevice) {
goto error;
}
inputParameters.channelCount = 1; /* mono input */
inputParameters.sampleFormat = PA_SAMPLE_TYPE;
inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency;
inputParameters.hostApiSpecificStreamInfo = NULL;
MessageBoxA(NULL, "2", "PortAudio DLL", MB_ICONINFORMATION);
err = Pa_OpenStream(
&stream,
&inputParameters,
NULL, //&outputParameters
SAMPLE_RATE,
FRAMES_PER_BUFFER,
0,
PaCallback,
NULL );
if( err != paNoError ) goto error;
MessageBoxA(NULL, "3", "PortAudio DLL", MB_ICONINFORMATION);
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
MessageBoxA(NULL, "4", "PortAudio DLL", MB_ICONINFORMATION);
return 1;
error:
MessageBoxA(NULL, "Apparently it doesn't work!", "PortAudio DLL", MB_ICONINFORMATION);
Pa_Terminate();
return 0;
}
GMEXPORT double __cdecl PortAudioEnd() {
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
Pa_Terminate();
return 1;
error:
MessageBoxA(NULL, "Apparently it doesn't work!", "PortAudio DLL", MB_ICONINFORMATION);
Pa_Terminate();
return 0;
}
GMEXPORT double __cdecl getFreq()
{
if (Pa_IsStreamStopped(stream) == 0)
{
return frequency; // this variable is constantly changed in the callback function
}
else
{
return 0;
}
}
void calculateFreq(bool sign)
{
unsigned int j;
bool check;
diffsamp = maxsamp - minsamp;
if (!sign)
{
diffsampmax = max((diffsampmax*.85), (double)diffsamp);
maxsamp = 0;
}
if (sign)
{
diffsampmax = max((diffsampmax*.85), (double)diffsamp);
minsamp = 0;
}
check = ( diffsamp > max(25.0,diffsampmax*.90) );
if (sign == lastsign)
{
check = false;
}
if (check)
{
if (timepassed - peaks[0] < 500)
{
for ( j=numpeaks-1; j>0; j-- )
{
peaks[j] = peaks[j-1];
}
}
else
{
for ( j=0; j<numpeaks; j++ )
{
peaks[j] = 0;
}
}
peaks[0] = timepassed;
double diff = peaks[0]-peaks[numpeaks-1];
double peaktime = diff/(numpeaks-1)*2; //*2 because maxdiff is at +>- and ->+
frequency = 1/((double)peaktime/(double)SAMPLE_RATE);
if (peaks[numpeaks-1] <= 0 || frequency < 20) frequency = 0;
lastsign = sign;
}
}
static int PaCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
const SAMPLE *in = (const SAMPLE*)inputBuffer;
unsigned int i;
unsigned int j;
(void) timeInfo; // Prevent unused variable warnings.
(void) statusFlags;
(void) userData;
SAMPLE samp;
if( inputBuffer == NULL )
{
//nothing happens
}
else
{
for( i=0; i<framesPerBuffer; i++ )
{
timepassed += 1;
samp = *in++;
changed = false;
if (samp > 0)
{
if (!sign)
{
sign = true;
changed = true;
}
maxsamp = max(maxsamp,samp);
}
else
{
if (sign)
{
sign = false;
changed = true;
}
minsamp = min(minsamp,samp);
}
if (changed)
{
calculateFreq(sign);
}
}
}
return paContinue;
}
GML:
//// Script: pa_init()
globalvar _pa_freq,_pa_start,_pa_end;
var dll_name;
dll_name = "c:\Users\<Username>\Documents\NetBeansProjects\GMDLLtest\dist\Debug\Cygwin_4.x-Windows\libGMDLLtest.dll";
_pa_freq = external_define(dll_name, "getFreq", dll_cdecl, ty_real, 0);
_pa_start = external_define(dll_name, "PortAudioStart", dll_cdecl, ty_real, 0);
_pa_end = external_define(dll_name, "PortAudioEnd", dll_cdecl, ty_real, 0);
////--------------------------------------------------------------------------------
//// Script: pa_start()
return external_call(_pa_start);
////--------------------------------------------------------------------------------
//// Script: pa_end()
return external_call(_pa_end);
////--------------------------------------------------------------------------------
//// Script: pa_freq()
return external_call(_pa_freq);
P.S: If anything is unclear, please ask, my knowledge of C++ isn't really outstanding.
Related
I've been struggling lately when i had to change some code that i wrote a while ago to do image processing in Qt and OpenGl to support multithreading.
the problem is that I want to use it to apply batches of filters on a set of images,
i'm using openMP to do the multi-threading like this:
void batchProcess(QVector<QImage> &images)
{
#pragma omp parallel
{
#pragma omp for schedule(dynamic) nowait
for (int i = 1; i < images.count(); i++)
{
images[i] = ImageProcessing::processImage(images[i], _vertexShader, _fragmentShader, _textureVar, _vertexPosVar, _textureCoordVar);
}
}
}
and the ImageProcessing::processImage() function looks like this:
QImage ImageProcessing::processImage(const QImage &source, const QString &vertexShader, const QString &fragmentShader, const QString &textureVar, const QString &vertexPosVar, const QString &textureCoordVar)
{
QOpenGLContext context;
if(!context.create())
return source;
QOffscreenSurface surface;
surface.setFormat(context.format());
surface.create();
if(!surface.isValid())
return source;
if(!context.makeCurrent(&surface))
return source;
QOpenGLFramebufferObject fbo(source.size());
context.functions()->glViewport(0, 0, source.width(), source.height());
QOpenGLShaderProgram program(&context);
if (!program.addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShader))
return source;
if (!program.addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShader))
return source;
if (!program.link())
return source;
if (!program.bind())
return source;
QOpenGLTexture texture(QOpenGLTexture::Target2D);
texture.setData(source);
texture.bind();
if(!texture.isBound())
return source;
VertexData vertices[] =
{
{{ -1.0f, +1.0f }, { 0.0f, 1.0f }}, // top-left
{{ +1.0f, +1.0f }, { 1.0f, 1.0f }}, // top-right
{{ -1.0f, -1.0f }, { 0.0f, 0.0f }}, // bottom-left
{{ +1.0f, -1.0f }, { 1.0f, 0.0f }} // bottom-right
};
GLuint indices[] =
{
0, 1, 2, 3
};
QOpenGLBuffer vertexBuf(QOpenGLBuffer::VertexBuffer);
QOpenGLBuffer indexBuf(QOpenGLBuffer::IndexBuffer);
if(!vertexBuf.create())
return source;
if(!indexBuf.create())
return source;
if(!vertexBuf.bind())
return source;
vertexBuf.allocate(vertices, 4 * sizeof(VertexData));
if(!indexBuf.bind())
return source;
indexBuf.allocate(indices, 4 * sizeof(GLuint));
int offset = 0;
program.enableAttributeArray(vertexPosVar.toLatin1().data());
program.setAttributeBuffer(vertexPosVar.toLatin1().data(), GL_FLOAT, offset, 2, sizeof(VertexData));
offset += sizeof(QVector2D);
program.enableAttributeArray(textureCoordVar.toLatin1().data());
program.setAttributeBuffer(textureCoordVar.toLatin1().data(), GL_FLOAT, offset, 2, sizeof(VertexData));
program.setUniformValue(textureVar.toLatin1().data(), 0);
context.functions()->glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, Q_NULLPTR);
return fbo.toImage(false);
}
it works fine when OpenMP is disabled, but when i enable it i get the following error:
Attempting to create QWindow-based QOffscreenSurface outside the gui thread. Expect failures.
according to the documentation, this is an expected behavior, because the QOffscreenSurface is just a hidden QWindow on some platforms, which means that it can only be created or destroyed from the main thread.
so in order to create the QOffscreenSurface in the Main thread i followed this answer and implemented the following class
class OpenGlFilterPrivate : public QObject
{
Q_OBJECT
public:
enum CustomEventTypes
{
CreateSurface = QEvent::User,
CreateContext = QEvent::User + 1,
CreateProgram = QEvent::User + 2
};
void moveToMainThread()
{
moveToThread(QApplication::instance()->thread());
}
virtual bool event(QEvent *event )
{
switch (event->type())
{
case CreateSurface: // m_surface (create an offscreen surface from the main thread)
m_surface = QSharedPointer<QOffscreenSurface>::create();
m_surface->setFormat(m_context->format());
m_surface->create();
break;
case CreateContext: // m_context (create an openGl context from the main thread)
m_context = QSharedPointer<QOpenGLContext>::create();
break;
case CreateProgram: // m_shaderProgram (create an openGl shader program from the main thread)
m_shaderProgram = QSharedPointer<QOpenGLShaderProgram>::create(&*m_context);
}
return false;
}
QSharedPointer<QOpenGLContext> m_context;
QSharedPointer<QOffscreenSurface> m_surface;
QSharedPointer<QOpenGLShaderProgram> m_shaderProgram;
};
and now instead of directly creating a QOffscreenSurface in my processImage function i do the following:
OpenGlFilterPrivate openGlFilterPrivate;
openGlFilterPrivate.moveToMainThread();
QCoreApplication::postEvent(&openGlFilterPrivate, new QEvent(QEvent::Type(OpenGlFilterPrivate::CreateSurface)));
QSharedPointer<QOffscreenSurface> surface = openGlFilterPrivate.m_surface;
it works, but now i keep getting the following message:
QObject::~QObject: Timers cannot be stopped from another thread
and then my application crashes immediately.
i know that any QObject contains a QTimer internally and that this is what's causing the problem, but i can't think of any other way to get around this.
Can anyone help with this?
all i need to do is to apply some image processing filters using openGl or any other hardware accelerated method and at the same time have the ability to do it in a thread-safe way.
i think it can be done using the same method used by QPainter, it's thread safe and as far as i know it's hardware accelerated using OpenGl. but i couldn't find any resources on how to do such thing.
Oh my, OpenMP and OpenGL probably don't mix very well. The way OpenMP creates multiple threads is not pinned down in terms that would be accessible to OpenGL implementations. Most likely it's using regular POSIX threads or Windows native threads. But it could also be anything else, that creates additional tasks inside the same address space.
I think it'd be far more robust and easier to tackle to create a pool of N threads, each with its own sharing OpenGL context and then use work stealing to schedule the tasks; keep the OpenGL current on the threads between worklets.
Conveniently enough with modern OpenGL one doesn't even need a window or similar drawable to make a context current. glXMakeContextCurrent and wglMakeContextCurrent will accept Nil parameters for the drawables/HDCs. So you can do OpenGL operations on framebuffer objects and all the other stuff, with the only caveat being, that there's no main default framebuffer.
Feel free to use those code snippets for creating the helper contexts.
#include "wglu_context.h"
#include <windows.h>
#include <GL/gl.h>
#include <GL/wglext.h>
#include <stdio.h>
#include <stddef.h>
#include <stdint.h>
#include <assert.h>
static char const *wgl_create_context_attribs_name = "wglCreateContextAttribsARB";
static
int wglu_get_proc_address(char const *name, PROC *pproc)
{
int rc= 0;
*pproc = wglGetProcAddress(name);
fprintf(stderr, "%s: %p\n", name, (void*)*pproc );
if( !(*pproc) ){
rc= GetLastError();
fprintf(stderr,
"error wglGetProcAddress('%s'): 0x%x\n",
name, rc);
}
if( rc ){ fprintf(stderr, "%s: %d\n", __func__, rc); }
return rc;
}
/* -----------------------------------------------------------------------
* Create a OpenGL context of desired version and share it */
int wglu_create_context_with_sharing(
int major, int minor, int profile,
HDC surface,
HGLRC share_context,
HGLRC *out_context )
{
int rc= 0;
int attribs[8] = {0};
size_t i_attrib = 0;
HGLRC context = 0;
HDC const save_surface = wglGetCurrentDC();
HGLRC const save_context = wglGetCurrentContext();
if( save_surface != surface
|| save_context != share_context
){
wglMakeCurrent(surface, share_context);
}
PFNWGLCREATECONTEXTATTRIBSARBPROC wgl_create_context_attribs;
if( (rc= wglu_get_proc_address(
wgl_create_context_attribs_name,
(PROC*)&wgl_create_context_attribs))
){
goto fail;
}
if( major ){
attribs[i_attrib++] = WGL_CONTEXT_MAJOR_VERSION_ARB;
attribs[i_attrib++] = major;
}
if( minor ){
attribs[i_attrib++] = WGL_CONTEXT_MINOR_VERSION_ARB;
attribs[i_attrib++] = minor;
}
if( profile ){
attribs[i_attrib++] = WGL_CONTEXT_PROFILE_MASK_ARB;
attribs[i_attrib++] = profile;
}
attribs[i_attrib] = attribs[i_attrib+1] = 0;
context = wgl_create_context_attribs(surface, *share_context, attribs);
if( !context ){
rc= GetLastError();
fprintf(stderr,
"error %s(surface=0x%x, share_context=0x%x, attribs=0x%p): %x\n",
wgl_create_context_attribs_name,
(uintptr_t)surface, (uintptr_t)share_context,
attribs,
rc );
goto fail;
}
if( !(wglMakeCurrent(surface, context)) ){
rc= GetLastError();
fprintf(stderr,
"error %s(surface=0x%x, contest=0x%x): 0x%x\n",
"wglMakeCurrent",
(uintptr_t)surface, (uintptr_t)context,
rc );
goto fail;
}
assert( context == wglGetCurrentContext() );
fprintf(stderr,
"GL_VENDOR = %s\n"
"GL_RENDERER = %s\n"
"GL_VERSION = %s\n",
glGetString(GL_VENDOR),
glGetString(GL_RENDERER),
glGetString(GL_VERSION) );
if( !(wglMakeCurrent(NULL, NULL)) ){
rc= GetLastError();
fprintf(stderr,
"error %s(0, 0): 0x%x\n",
"wglMakeCurrent",
(uintptr_t)surface, (uintptr_t)context,
rc );
goto fail;
}
if( !(wglShareLists(context, share_context)) ){
rc= GetLastError();
fprintf(stderr,
"error %s(context=0x%x, share_context=0x%x): 0x%x\n",
"wglShareLists",
(uintptr_t)context, (uintptr_t)share_context,
rc );
goto fail;
}
wglMakeCurrent(save_surface, save_context);
if( !rc ){
if( out_context ){ *out_context = context; }
} else {
if( context ){ wglDeleteContext(context); }
}
if( rc ){ fprintf(stderr, "%s: %d\n", __func__, rc); }
return rc;
}
#include <GL/glxext.h>
#include <stdio.h>
#include <stddef.h>
#include <stdint.h>
#include <assert.h>
#include <errno.h>
#include <dlfcn.h>
static char const *glX_create_context_attribs_name = "glXCreateContextAttribsARB";
typedef void (*PROC)();
static
int glxu_get_proc_address(char const *name, PROC *pproc)
{
int rc= 0;
static PROC (*glX_get_proc_address)(char const*) = NULL;
if( !glX_get_proc_address ){
*(void**)(&glX_get_proc_address) = dlsym(RTLD_DEFAULT, "glXGetProcAddress");
}
if( !glX_get_proc_address ){
rc = -EFAULT;
} else {
*pproc = glX_get_proc_address(name);
fprintf(stderr, "%s: %p\n", name, (void*)*pproc );
if( !(*pproc) ){
rc= -ENOENT;
fprintf(stderr, "error glXGetProcAddress('%s'): so such function\n", name);
}
}
if( rc ){ fprintf(stderr, "%s: %d\n", __func__, rc); }
return rc;
}
static
int glxu_get_fbconfig_for_xid(
Display *display,
GLXFBConfigID const id,
GLXFBConfig *out_fbconfig )
{
static GLXFBConfig* (*glX_get_fb_configs)(Display*,int,int*) = NULL;
static int (*glX_get_fb_config_attrib)(Display*,GLXFBConfig,int,int*) = NULL;
if( !glX_get_fb_configs ){
*(void**)(&glX_get_fb_configs) = dlsym(RTLD_DEFAULT, "glXGetFBConfigs");
}
if( !glX_get_fb_config_attrib ){
*(void**)(&glX_get_fb_config_attrib) = dlsym(RTLD_DEFAULT, "glXGetFBConfigAttrib");
}
int rc = 0;
int n_configs = 0;
/* we always assume to operate on screen 0, since hardly any X connection
* encountered these days actually operates on multiple screens. */
if( !glX_get_fb_configs || !glX_get_fb_config_attrib ){
rc = -EFAULT;
} else {
GLXFBConfig *const fbconfig = glX_get_fb_configs(display, 0, &n_configs);
for(int i=0; !rc && i < n_configs; ++i){
unsigned int qry_id;
rc= glX_get_fb_config_attrib(display, fbconfig[i], GLX_FBCONFIG_ID, &qry_id);
if( !rc && id == qry_id ){
*out_fbconfig = fbconfig[i];
break;
}
}
}
return rc;
}
Display *glxu_get_current_display(void)
{
static Display* (*glX_get_current_display)(void) = NULL;
if( !glX_get_current_display ){
*(void**)(&glX_get_current_display) = dlsym(RTLD_DEFAULT, "glXGetCurrentDisplay");
}
if( !glX_get_current_display ){
return NULL;
}
return glX_get_current_display();
}
GLXDrawable glxu_get_current_drawable(void)
{
static GLXDrawable (*glX_get_current_drawable)(void) = NULL;
if( !glX_get_current_drawable ){
*(void**)(&glX_get_current_drawable) = dlsym(RTLD_DEFAULT, "glXGetCurrentDrawable");
}
if( !glX_get_current_drawable ){
return 0;
}
return glX_get_current_drawable();
}
/* -----------------------------------------------------------------------
* Create a OpenGL context of desired version and share it */
int glxu_create_context_with_sharing(
int major, int minor, int profile,
Display *display,
GLXDrawable surface,
GLXContext share_context,
GLXContext *out_context )
{
int rc= 0;
int attribs[8] = {0};
size_t i_attrib = 0;
GLXContext context = 0;
unsigned int fbconfigxid = 0;
GLXFBConfig fbconfig = 0;
static GLXContext (*glX_get_current_context)(void) = NULL;
static void (*glX_query_drawable)(Display*,GLXDrawable,int,unsigned*) = NULL;
static Bool (*glX_make_current)(Display*,Drawable,GLXContext) = NULL;
static void (*glX_destroy_context)(Display*,GLXContext) = NULL;
if( !glX_get_current_context ){
*(void**)(&glX_get_current_context) = dlsym(RTLD_DEFAULT, "glXGetCurrentContext");
}
if( !glX_query_drawable ){
*(void**)(&glX_query_drawable) = dlsym(RTLD_DEFAULT, "glXQueryDrawable");
}
if( !glX_make_current ){
*(void**)(&glX_make_current) = dlsym(RTLD_DEFAULT, "glXMakeCurrent");
}
if( !glX_destroy_context ){
*(void**)(&glX_destroy_context) = dlsym(RTLD_DEFAULT, "glXDestroyContext");
}
if( !glX_get_current_context || !glX_query_drawable
|| !glX_make_current || !glX_destroy_context
){
return -EFAULT;
}
Display *const save_display = glxu_get_current_display();
GLXDrawable const save_surface = glxu_get_current_drawable();
GLXContext const save_context = glX_get_current_context();
if( !display ){ display = save_display; }
if( !surface ){ surface = save_surface; }
if( !share_context ){ share_context = save_context; }
if( save_display != display
|| save_surface != surface
|| save_context != share_context
){
fprintf(stderr, ".....\n");
if( !(glX_make_current(display, surface, share_context)) ){
rc = -1;
goto fail;
}
}
PFNGLXCREATECONTEXTATTRIBSARBPROC glX_create_context_attribs;
if( (rc= glxu_get_proc_address(
glX_create_context_attribs_name,
(PROC*)&glX_create_context_attribs))
){
rc = -2;
goto fail;
}
glX_query_drawable(display, surface, GLX_FBCONFIG_ID, &fbconfigxid);
glxu_get_fbconfig_for_xid(display, fbconfigxid, &fbconfig);
if( major ){
attribs[i_attrib++] = GLX_CONTEXT_MAJOR_VERSION_ARB;
attribs[i_attrib++] = major;
}
if( minor ){
attribs[i_attrib++] = GLX_CONTEXT_MINOR_VERSION_ARB;
attribs[i_attrib++] = minor;
}
if( profile ){
attribs[i_attrib++] = GLX_CONTEXT_PROFILE_MASK_ARB;
attribs[i_attrib++] = profile;
}
attribs[i_attrib] = attribs[i_attrib+1] = 0;
context = glX_create_context_attribs(display, fbconfig, share_context, True, attribs);
if( !context ){
rc= -3;
fprintf(stderr,
"error %s(surface=0x%p, share_context=0x%p, attribs=0x%p): %x\n",
glX_create_context_attribs_name,
(void*)surface, (void*)share_context,
attribs,
rc );
goto fail;
}
if( !(glX_make_current(display, surface, context)) ){
rc= -4;
fprintf(stderr,
"error %s(surface=0x%p, contest=0x%p): 0x%x\n",
"wglMakeCurrent",
(void*)surface, (void*)context,
rc );
goto fail;
}
assert( context == glX_get_current_context() );
fprintf(stderr,
"GL_VENDOR = %s\n"
"GL_RENDERER = %s\n"
"GL_VERSION = %s\n",
glGetString(GL_VENDOR),
glGetString(GL_RENDERER),
glGetString(GL_VERSION) );
fail:
glX_make_current(display, save_surface, save_context);
if( !rc ){
if( out_context ){ *out_context = context; }
} else {
if( context ){ glX_destroy_context(display, context); }
}
if( rc ){ fprintf(stderr, "%s: %d\n", __func__, rc); }
return rc;
}
Bool glxu_make_context_current(
Display* display,
GLXDrawable read, GLXDrawable draw,
GLXContext ctx )
{
static Bool (*glX_make_context_current)(Display*,Drawable,Drawable,GLXContext) = NULL;
if( !glX_make_context_current ){
*(void**)(&glX_make_context_current) = dlsym(RTLD_DEFAULT, "glXMakeContextCurrent");
}
if( !glX_make_context_current ){
return False;
}
return glX_make_context_current(display, read, draw, ctx);
}
For example, my computer has two monitors, the primary monitor's resolution is 800*600, the other monitor's resolution is 1600*900.
I would like define the resolution on one monitor only ?
The function 'SetDisplayConfig' change the resolution screen on the two minotors...
https://learn.microsoft.com/fr-fr/windows-hardware/drivers/display/ccd-apis
https://learn.microsoft.com/fr-fr/windows/win32/api/winuser/nf-winuser-setdisplayconfig
[DllImport("User32.dll")]
public static extern int SetDisplayConfig(
uint numPathArrayElements,
[In] DisplayConfigPathInfo[] pathArray,
uint numModeInfoArrayElements,
[In] DisplayConfigModeInfo[] modeInfoArray,
SdcFlags flags
);
private static Boolean SetDisplaySettings(int Id_Monitor, uint Width, uint Height, uint Scaling)
{
try
{
CCDWrapper.DisplayConfigPathInfo[] pathInfoArray = new CCDWrapper.DisplayConfigPathInfo[0] { };
CCDWrapper.DisplayConfigModeInfo[] modeInfoArray = new CCDWrapper.DisplayConfigModeInfo[0] { };
CCDWrapper.MonitorAdditionalInfo[] additionalInfo = new CCDWrapper.MonitorAdditionalInfo[0] { };
bool Status = GetDisplaySettings(ref pathInfoArray, ref modeInfoArray, ref additionalInfo, true);
CCDWrapper.DisplayConfigPathInfo[] pathInfoArrayCurrent = new CCDWrapper.DisplayConfigPathInfo[0] { };
CCDWrapper.DisplayConfigModeInfo[] modeInfoArrayCurrent = new CCDWrapper.DisplayConfigModeInfo[0] { };
CCDWrapper.MonitorAdditionalInfo[] additionalInfoCurrent = new CCDWrapper.MonitorAdditionalInfo[0] { };
bool StatusCurrent = GetDisplaySettings(ref pathInfoArrayCurrent, ref modeInfoArrayCurrent, ref additionalInfoCurrent, false);
if (StatusCurrent)
{
for (int iPathInfo = 0; iPathInfo <= pathInfoArray.Length-1; iPathInfo++)
//for (int iPathInfo = 0; iPathInfo <= pathInfoArray.Length - 1; iPathInfo++)
{
for (int iPathInfoCurrent = 0; iPathInfoCurrent <= pathInfoArrayCurrent.Length - 1; iPathInfoCurrent++)
{
if ((pathInfoArray[iPathInfo].sourceInfo.id == pathInfoArrayCurrent[iPathInfoCurrent].sourceInfo.id) && (pathInfoArray[iPathInfo].targetInfo.id == pathInfoArrayCurrent[iPathInfoCurrent].targetInfo.id))
{
pathInfoArray[iPathInfo].sourceInfo.adapterId.LowPart = pathInfoArrayCurrent[iPathInfoCurrent].sourceInfo.adapterId.LowPart;
pathInfoArray[iPathInfo].targetInfo.adapterId.LowPart = pathInfoArrayCurrent[iPathInfoCurrent].targetInfo.adapterId.LowPart;
pathInfoArray[iPathInfo].targetInfo.scaling = (CCDWrapper.DisplayConfigScaling)Scaling;
break;
}
}
}
for (int iModeInfo = 0; iModeInfo <= modeInfoArray.Length - 1; iModeInfo++)
{
for (int iPathInfo = 0; iPathInfo <= pathInfoArray.Length - 1; iPathInfo++)
{
if ((modeInfoArray[iModeInfo].id == pathInfoArray[iPathInfo].targetInfo.id) && (modeInfoArray[iModeInfo].infoType == CCDWrapper.DisplayConfigModeInfoType.Target))
{
for (int iModeInfoSource = 0; iModeInfoSource <= modeInfoArray.Length - 1; iModeInfoSource++)
{
if ((modeInfoArray[iModeInfoSource].id == pathInfoArray[iPathInfo].sourceInfo.id) && (modeInfoArray[iModeInfoSource].adapterId.LowPart == modeInfoArray[iModeInfo].adapterId.LowPart) && (modeInfoArray[iModeInfoSource].infoType == CCDWrapper.DisplayConfigModeInfoType.Source))
{
modeInfoArray[iModeInfoSource].adapterId.LowPart = pathInfoArray[iPathInfo].sourceInfo.adapterId.LowPart;
modeInfoArray[iModeInfoSource].sourceMode.height = Height;
modeInfoArray[iModeInfoSource].sourceMode.width = Width;
break;
}
}
modeInfoArray[iModeInfo].adapterId.LowPart = pathInfoArray[iPathInfo].targetInfo.adapterId.LowPart;
break;
}
}
}
uint numPathArrayElements = System.Convert.ToUInt32(pathInfoArray.Length);
uint numModeInfoArrayElements = System.Convert.ToUInt32(modeInfoArray.Length);
long Result = CCDWrapper.SetDisplayConfig(numPathArrayElements, pathInfoArray, numModeInfoArrayElements, modeInfoArray, CCDWrapper.SdcFlags.Apply | CCDWrapper.SdcFlags.UseSuppliedDisplayConfig | CCDWrapper.SdcFlags.SaveToDatabase | CCDWrapper.SdcFlags.NoOptimization | CCDWrapper.SdcFlags.AllowChanges);
if (Result == 0)
return true;
else
return false;
}
else
return false;
}
catch (Exception ex)
{
EventLog.WriteEntry("ResolutionEcran", "Erreur SetDisplaySettings : " + ex.Message, EventLogEntryType.Error);
return false;
}
}
private static Boolean GetDisplaySettings(ref CCDWrapper.DisplayConfigPathInfo[] pathInfoArray, ref CCDWrapper.DisplayConfigModeInfo[] modeInfoArray, ref CCDWrapper.MonitorAdditionalInfo[] additionalInfo, Boolean ActiveOnly, [System.Runtime.InteropServices.Optional] int ID_Monitor)
{
uint numPathArrayElements;
uint numModeInfoArrayElements;
CCDWrapper.QueryDisplayFlags queryFlags = CCDWrapper.QueryDisplayFlags.AllPaths;
if (ActiveOnly)
{
//queryFlags = CCDWrapper.QueryDisplayFlags.OnlyActivePaths;
queryFlags = CCDWrapper.QueryDisplayFlags.OnlyActivePaths;
}
var status = CCDWrapper.GetDisplayConfigBufferSizes(queryFlags, out numPathArrayElements, out numModeInfoArrayElements);
if (status == 0)
{
pathInfoArray = new CCDWrapper.DisplayConfigPathInfo[numPathArrayElements];
modeInfoArray = new CCDWrapper.DisplayConfigModeInfo[numModeInfoArrayElements];
additionalInfo = new CCDWrapper.MonitorAdditionalInfo[numModeInfoArrayElements];
status = CCDWrapper.QueryDisplayConfig(queryFlags, ref numPathArrayElements, pathInfoArray, ref numModeInfoArrayElements, modeInfoArray, IntPtr.Zero);
if (status == 0)
{
for (var iMode = 0; iMode < numModeInfoArrayElements; iMode++)
{
if (modeInfoArray[iMode].infoType == CCDWrapper.DisplayConfigModeInfoType.Target)
{
try
{
additionalInfo[iMode] = CCDWrapper.GetMonitorAdditionalInfo(modeInfoArray[iMode].adapterId, modeInfoArray[iMode].id);
}
catch (Exception)
{
additionalInfo[iMode].valid = false;
}
}
}
return true;
}
else
{
//Erreur : Querying display;
}
}
else
{
//Erreur : Taille Buffer;
}
return false;
}
Use ChangeDisplaySettingsEx function to change the settings of the specified display device to the specified graphics mode. The following is an example you can refer to.
#include <windows.h>
int main()
{
for (DWORD devNum = 0; ; devNum++)
{
DISPLAY_DEVICE dev = {0};
dev.cb = sizeof(DISPLAY_DEVICE);
if (!EnumDisplayDevices(NULL, devNum, &dev, EDD_GET_DEVICE_INTERFACE_NAME))
break;
wprintf(L"Display name: %s \n", dev.DeviceName);
DEVMODE dMode = { 0 };
dMode.dmSize = sizeof(dMode);
if (!EnumDisplaySettings(dev.DeviceName, ENUM_CURRENT_SETTINGS, &dMode))
{
wprintf(L"EnumDisplaySettings error: %d \n", GetLastError());
continue;
}
wprintf(L"Display old settings: \n");
wprintf(L"dmBitsPerPel: %d \n", dMode.dmBitsPerPel);
wprintf(L"dmPelsWidth: %d \n", dMode.dmPelsWidth);
wprintf(L"dmPelsHeight: %d \n", dMode.dmPelsHeight);
wprintf(L"dmDisplayFlags: %x \n", dMode.dmDisplayFlags);
wprintf(L"dmDisplayFrequency: %d \n", dMode.dmDisplayFrequency);
dMode.dmPelsWidth = 800;
dMode.dmPelsHeight = 600;
ChangeDisplaySettingsEx(dev.DeviceName, &dMode, NULL, 0, NULL);
DEVMODE dModeNew = { 0 };
dModeNew.dmSize = sizeof(DEVMODE);
if (!EnumDisplaySettings(dev.DeviceName, ENUM_CURRENT_SETTINGS, &dModeNew))
{
wprintf(L"EnumDisplaySettings error: %d \n", GetLastError());
continue;
}
wprintf(L"Display new settings: \n");
wprintf(L"dmBitsPerPel: %d \n", dModeNew.dmBitsPerPel);
wprintf(L"dmPelsWidth: %d \n", dModeNew.dmPelsWidth);
wprintf(L"dmPelsHeight: %d \n", dModeNew.dmPelsHeight);
wprintf(L"dmDisplayFlags: %x \n", dModeNew.dmDisplayFlags);
wprintf(L"dmDisplayFrequency: %d \n", dModeNew.dmDisplayFrequency);
}
getchar();
}
I set dwflags to 0 let the graphics mode for the current screen change dynamically. Refer to dwflags parameter part of ChangeDisplaySettingsEx's document for deciding how you would like the graphics mode should be changed.
Sorry for my late response...I was absent.
I also need to change the scaling of monitor (Black bars removed on certain resolutions).
[Flags]
public enum DisplayConfigScaling : uint
{
Zero = 0x0,
Identity = 1,
Centered = 2,
Stretched = 3,
Aspectratiocenteredmax = 4,
Custom = 5,
Preferred = 128,
ForceUint32 = 0xFFFFFFFF
}
The function 'ChangeDisplaySettingsEx' may change the scale of monitor ?
Thank you very for your help.
I am writing a C++ console program using WinAPI. This program works with files and directories. The program is launched as follows:
app -R -1 "mask"
(for example, "D: \ Work \*").
-R is a recursive directory traversal, -1 - output of information about files (creation date, size, attributes).
Full program code:
LIBSPEC BOOL ConsolePrompt(LPCTSTR, LPTSTR, DWORD, BOOL);
LIBSPEC BOOL PrintStrings(HANDLE, ...);
LIBSPEC BOOL PrintMsg(HANDLE, LPCTSTR);
LIBSPEC VOID ReportError(LPCTSTR, DWORD, BOOL);
BOOL TraverseDirectory(LPCTSTR, DWORD, LPBOOL);
DWORD FileType(LPWIN32_FIND_DATA);
BOOL ProcessItem(LPWIN32_FIND_DATA, DWORD, LPBOOL);
DWORD Options(int argc, LPCTSTR argv[], LPCTSTR OptStr, ...) {
va_list pFlagList;
LPBOOL pFlag;
int iFlag = 0, iArg;
va_start(pFlagList, OptStr);
while ((pFlag = va_arg(pFlagList, LPBOOL)) != NULL && iFlag < (int)_tcslen(OptStr)) {
*pFlag = FALSE;
for (iArg = 1; !(*pFlag) && iArg < argc && argv[iArg][0] == '-'; iArg++)
*pFlag = memchr(argv[iArg], OptStr[iFlag], _tcslen(argv[iArg])) != NULL;
iFlag++;
}
va_end(pFlagList);
for (iArg = 1; iArg < argc && argv[iArg][0] == '-'; iArg++);
return iArg;
}
void pr_err(int code) {
setlocale(LC_ALL, "Russian");
if (code == 3) {
printf("Файл с указанным названием по указанному пути не найден.");
}
else if (code == 5) {
printf("Операция отклонена. Возможны следующие причины: \n");
printf("Копируемый файл защищен от копирования, скрыт или используется операционной системой.\n");
printf("В целевой директории стоит запрет на запись файлов.\n");
}
else if (code == 20) {
printf("Устройство не найдено.\n");
}
else if (code == 123) {
printf("Указано некорректное название для файла или директории. Возможно были использованы запрещенные символы.\n");
}
}
static void PrintAttributes(DWORD Attrs)
{
setlocale(LC_ALL, "Russian");
if (Attrs == INVALID_FILE_ATTRIBUTES)
{
printf(" Ошибка чтения атрибутов\n");
}
else
{
printf(" \nАтрибуты: ");
if (Attrs & FILE_ATTRIBUTE_ARCHIVE)
{
printf("A ");
}
if (Attrs & FILE_ATTRIBUTE_COMPRESSED)
{
printf("C ");
}
if (Attrs & FILE_ATTRIBUTE_DIRECTORY)
{
printf("D ");
}
if (Attrs & FILE_ATTRIBUTE_HIDDEN)
{
printf("H ");
}
if (Attrs & FILE_ATTRIBUTE_READONLY)
{
printf("R ");
}
printf("\n");
}
}
int _tmain(int argc, LPCTSTR argv[]) {
setlocale(LC_ALL, "Russian");
BOOL Flags[MAX_OPTIONS], ok = TRUE;
TCHAR PathName[buffsize + 1], CurrPath[buffsize + 1];
LPCTSTR pFileName;
int i, FileIndex;
FileIndex = Options(argc, argv, _T("R1"), &Flags[0], &Flags[1], &Flags[2], NULL);
GetCurrentDirectory(buffsize, CurrPath);
printf("argc = %d Index = %d\n", argc, FileIndex);
if (argc < FileIndex + 1) {
printf("Поиск в текущей директории:\n (%s)\n", CurrPath);
ok = TraverseDirectory(_T("*"), MAX_OPTIONS, Flags);
}
else {
for (i = FileIndex; i < argc; i++) {
pFileName = argv[i];
/* Нужно из pFileName вытащить сабстринг по разделителю *
FileAddress = ... // тут получение адреса
SetCurrentDirectory(FileAddress);
*/
printf("DIR: %s\n", pFileName);
if (!SetCurrentDirectory(pFileName)) {
printf("Ошибка установки директории %s как текущей...", pFileName);
return 1;
}
else {
ok = TraverseDirectory(pFileName, MAX_OPTIONS, Flags) && ok;
SetCurrentDirectory(CurrPath);
}
}
}
return ok ? 0 : 1;
}
static BOOL TraverseDirectory(LPCTSTR PathName, DWORD NumFlags, LPBOOL Flags) {
HANDLE SearchHandle;
WIN32_FIND_DATA FindData;
BOOL Recursive = Flags[0];
DWORD FType, iPass;
TCHAR CurrPath[buffsize + 1];
GetCurrentDirectory(buffsize, CurrPath);
for (iPass = 1; iPass <= 2; iPass++) {
SearchHandle = FindFirstFile(PathName, &FindData);
if (SearchHandle == INVALID_HANDLE_VALUE) {
pr_err(GetLastError());
return 1;
}
do {
FType = FileType(&FindData);
if (iPass == 1)
ProcessItem(&FindData, MAX_OPTIONS, Flags);
if (FType == TYPE_DIR && iPass == 2 && Recursive) {
_tprintf(_T("%s\\%s:\n"), CurrPath, FindData.cFileName);
if (!SetCurrentDirectory(FindData.cFileName))
{
printf("Ошибка установки %s как текущей директории...", FindData.cFileName);
}
else {
TraverseDirectory(_T("*"), NumFlags, Flags);
SetCurrentDirectory(_T(".."));
}
}
} while (FindNextFile(SearchHandle, &FindData));
FindClose(SearchHandle);
}
return TRUE;
}
static BOOL ProcessItem(LPWIN32_FIND_DATA pFileData, DWORD NumFlags, LPBOOL Flags)
{
const TCHAR FileTypeChar[] = { 'c', 'd' };
DWORD FType = FileType(pFileData);
BOOL Long = Flags[1];
SYSTEMTIME LastWrite;
if (FType != TYPE_FILE && FType != TYPE_DIR)
return FALSE;
_tprintf(_T("\n"));
if (Long) {
_tprintf(_T("%c"), FileTypeChar[FType - 1]);
_tprintf(_T("%10d"), pFileData->nFileSizeLow);
FileTimeToSystemTime(&(pFileData->ftLastWriteTime), &LastWrite);
_tprintf(_T(" %02d/%02d/%04d %02d:%02d:%02d "), LastWrite.wMonth, LastWrite.wDay,
LastWrite.wYear, LastWrite.wHour, LastWrite.wMinute, LastWrite.wSecond);
}
_tprintf(_T("%s"), pFileData->cFileName);
PrintAttributes(GetFileAttributesA(pFileData->cFileName));
return TRUE;
}
static DWORD FileType(LPWIN32_FIND_DATA pFileData) {
BOOL IsDir;
DWORD FType;
FType = TYPE_FILE;
IsDir = (pFileData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
if (IsDir)
if (lstrcmp(pFileData->cFileName, _T(".")) == 0 ||
lstrcmp(pFileData->cFileName, _T("..")) == 0)
FType = TYPE_DOT;
else
FType = TYPE_DIR;
return FType;
}
The problem is switching to the specified path does not work. How can I solve this problem?
Wildcard characters are not accepted in SetCurrentDirectory.
You should to specify a valid path, like "D:\\work\\".
Then, you should call GetFileAttributes to decide whether to add wildcards after the filename.
TCHAR file[MAX_PATH] = {0};
_stprintf(file, _T("%s\\*"), pFileName);
ok = TraverseDirectory(file, MAX_PATH, Flags) && ok;
I am trying to setup the Interactive Brokers API on Ubuntu (18.04). I have installed both the IB Gateway, which is used for communicating with exchanges, as well as other API software for developing trading algorithms in Java, C++, C# and Python. (Which you can find here). The API is written in both Java and C++, and as stated prior it offers support for both. However when attempting to compile an example from their source code there is an error in the EReader.cpp file. I have dealt with several other C++ errors in their code however this one I cannot figure out. Here is the code:
#include "StdAfx.h"
#include "shared_ptr.h"
#include "Contract.h"
#include "EDecoder.h"
#include "EMutex.h"
#include "EReader.h"
#include "EClientSocket.h"
#include "EPosixClientSocketPlatform.h"
#include "EReaderSignal.h"
#include "EMessage.h"
#include "DefaultEWrapper.h"
#define IN_BUF_SIZE_DEFAULT 8192
static DefaultEWrapper defaultWrapper;
EReader::EReader(EClientSocket *clientSocket, EReaderSignal *signal)
: processMsgsDecoder_(clientSocket->EClient::serverVersion(), clientSocket->getWrapper(), clientSocket) {
m_isAlive = true;
m_pClientSocket = clientSocket;
m_pEReaderSignal = signal;
m_needsWriteSelect = false;
m_nMaxBufSize = IN_BUF_SIZE_DEFAULT;
m_buf.reserve(IN_BUF_SIZE_DEFAULT);
}
EReader::~EReader(void) {
m_isAlive = false;
#if defined(IB_WIN32)
WaitForSingleObject(m_hReadThread, INFINITE);
#endif
}
void EReader::checkClient() {
m_needsWriteSelect = !m_pClientSocket->getTransport()-
isOutBufferEmpty();
}
void EReader::start() {
#if defined(IB_POSIX)
pthread_t thread;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create( &thread, &attr, readToQueueThread, this );
pthread_attr_destroy(&attr);
#elif defined(IB_WIN32)
m_hReadThread = CreateThread(0, 0, readToQueueThread, this, 0, 0);
#else
# error "Not implemented on this platform"
#endif
}
#if defined(IB_POSIX)
void * EReader::readToQueueThread(void * lpParam)
#elif defined(IB_WIN32)
DWORD WINAPI EReader::readToQueueThread(LPVOID lpParam)
#else
# error "Not implemented on this platform"
#endif
{
EReader *pThis = reinterpret_cast<EReader *>(lpParam);
pThis->readToQueue();
return 0;
}
void EReader::readToQueue() {
EMessage *msg = 0;
while (m_isAlive) {
if (m_buf.size() == 0 && !processNonBlockingSelect() && m_pClientSocket->isSocketOK())
continue;
if (!putMessageToQueue())
break;
}
m_pClientSocket->handleSocketError();
m_pEReaderSignal->issueSignal(); //letting client know that socket was closed
}
bool EReader::putMessageToQueue() {
EMessage *msg = 0;
if (m_pClientSocket->isSocketOK())
msg = readSingleMsg();
if (msg == 0)
return false;
m_csMsgQueue.Enter();
m_msgQueue.push_back(ibapi::shared_ptr<EMessage>(msg));
m_csMsgQueue.Leave();
m_pEReaderSignal->issueSignal();
return true;
}
bool EReader::processNonBlockingSelect() {
fd_set readSet, writeSet, errorSet;
struct timeval tval;
tval.tv_usec = 100 * 1000; //100 ms
tval.tv_sec = 0;
if( m_pClientSocket->fd() >= 0 ) {
FD_ZERO( &readSet);
errorSet = writeSet = readSet;
FD_SET( m_pClientSocket->fd(), &readSet);
if (m_needsWriteSelect)
FD_SET( m_pClientSocket->fd(), &writeSet);
FD_SET( m_pClientSocket->fd(), &errorSet);
int ret = select( m_pClientSocket->fd() + 1, &readSet, &writeSet, &errorSet, &tval);
if( ret == 0) { // timeout
return false;
}
if( ret < 0) { // error
m_pClientSocket->eDisconnect();
return false;
}
if( m_pClientSocket->fd() < 0)
return false;
if( FD_ISSET( m_pClientSocket->fd(), &errorSet)) {
// error on socket
m_pClientSocket->onError();
}
if( m_pClientSocket->fd() < 0)
return false;
if( FD_ISSET( m_pClientSocket->fd(), &writeSet)) {
// socket is ready for writing
onSend();
}
if( m_pClientSocket->fd() < 0)
return false;
if( FD_ISSET( m_pClientSocket->fd(), &readSet)) {
// socket is ready for reading
onReceive();
}
return true;
}
return false;
}
void EReader::onSend() {
m_pEReaderSignal->issueSignal();
}
void EReader::onReceive() {
int nOffset = m_buf.size();
m_buf.resize(m_nMaxBufSize);
int nRes = m_pClientSocket->receive(m_buf.data() + nOffset, m_buf.size() - nOffset);
if (nRes <= 0)
return;
m_buf.resize(nRes + nOffset);
}
bool EReader::bufferedRead(char *buf, int size) {
while (size > 0) {
while (m_buf.size() < size && m_buf.size() < m_nMaxBufSize)
if (!processNonBlockingSelect() && !m_pClientSocket->isSocketOK())
return false;
int nBytes = (std::min<unsigned int>)(m_nMaxBufSize, size);
std::copy(m_buf.begin(), m_buf.begin() + nBytes, buf);
std::copy(m_buf.begin() + nBytes, m_buf.end(), m_buf.begin());
m_buf.resize(m_buf.size() - nBytes);
size -= nBytes;
buf += nBytes;
}
return true;
}
EMessage * EReader::readSingleMsg() {
if (m_pClientSocket->usingV100Plus()) {
int msgSize;
if (!bufferedRead((char *)&msgSize, sizeof(msgSize)))
return 0;
msgSize = htonl(msgSize);
if (msgSize <= 0 || msgSize > MAX_MSG_LEN)
return 0;
std::vector<char> buf = std::vector<char>(msgSize);
if (!bufferedRead(buf.data(), buf.size()))
return 0;
return new EMessage(buf);
}
else {
const char *pBegin = 0;
const char *pEnd = 0;
int msgSize = 0;
while (msgSize == 0)
{
if (m_buf.size() >= m_nMaxBufSize * 3/4)
m_nMaxBufSize *= 2;
if (!processNonBlockingSelect() && !m_pClientSocket->isSocketOK())
return 0;
pBegin = m_buf.data();
pEnd = pBegin + m_buf.size();
msgSize = EDecoder(m_pClientSocket->EClient::serverVersion(), &defaultWrapper).parseAndProcessMsg(pBegin, pEnd);
}
std::vector<char> msgData(msgSize);
if (!bufferedRead(msgData.data(), msgSize))
return 0;
if (m_buf.size() < IN_BUF_SIZE_DEFAULT && m_buf.capacity() > IN_BUF_SIZE_DEFAULT)
{
m_buf.resize(m_nMaxBufSize = IN_BUF_SIZE_DEFAULT);
m_buf.shrink_to_fit();
}
EMessage * msg = new EMessage(msgData);
return msg;
}
}
ibapi::shared_ptr<EMessage> EReader::getMsg(void) {
m_csMsgQueue.Enter();
if (m_msgQueue.size() == 0) {
m_csMsgQueue.Leave();
return ibapi::shared_ptr<EMessage>();
}
ibapi::shared_ptr<EMessage> msg = m_msgQueue.front();
m_msgQueue.pop_front();
m_csMsgQueue.Leave();
return msg;
}
void EReader::processMsgs(void) {
m_pClientSocket->onSend();
checkClient();
ibapi::shared_ptr<EMessage> msg = getMsg();
if (!msg.get())
return;
const char *pBegin = msg->begin();
while (processMsgsDecoder_.parseAndProcessMsg(pBegin, msg->end()) > 0)
{
msg = getMsg();
if (!msg.get())
break;
pBegin = msg->begin();
}
}
The error I get it is the following:
error: 'min' was not declared in this scope int nBytes =
min(m_nMaxBuffSize, size);
I have had to do other things such as editing other source code and makefiles, I am stuck here. Any insight would be appreciated.
In my version 973 source at that line I have
int nBytes = (std::min<unsigned int>)(m_nMaxBufSize, size);
Make sure you are using the latest version. The problem may be an example of what happens here Why is "using namespace std" considered bad practice?
I'm using portaudio to play a sound. I want to be able to select the output via the UI. I managed it like that :
PaError err = Pa_Initialize();
if( err != paNoError )
return false;
qDebug() <<"Port audio succeed initialization !";
int numDevices;
numDevices = Pa_GetDeviceCount();
if( numDevices <= 0 )
{
qDebug() << "ERROR: Pa_CountDevices returned " << numDevices;
return false;
}
const PaDeviceInfo *deviceInfo;
bool isThereOutput = false;
int i = 0;
while(i < numDevices and !isThereOutput)
{
deviceInfo = Pa_GetDeviceInfo( i );
isThereOutput = (deviceInfo->maxOutputChannels > 0);
i++;
}
if(!isThereOutput)
{
qDebug() << "No output device";
return false;
}
PaError errorOpening;
if(outputDevice != "")
{
PaStreamParameters outputDeviceInfo;
int numDevices = Pa_GetDeviceCount();
const PaDeviceInfo *deviceInfo;
for(int i = 0; i<numDevices; i++ )
{
deviceInfo = Pa_GetDeviceInfo( i );
if(deviceInfo->maxOutputChannels > 0 && deviceInfo->name == outputDevice)
{
outputDeviceInfo.device = i;
outputDeviceInfo.channelCount = 1;
outputDeviceInfo.sampleFormat = paInt8;
outputDeviceInfo.suggestedLatency = deviceInfo->defaultLowOutputLatency;
}
}
if(outputDeviceInfo.channelCount > 1)
{
errorOpening = Pa_OpenStream(&stream, NULL, &outputDeviceInfo, SAMPLE_RATE, FRAME_PER_BUFFER, paNoFlag, audioCallback, this);
}
}
if(outputDevice == "" or errorOpening != paNoError)
{
if(errorOpening != paNoError)
qDebug() << "Can't open selected device ("<< outputDevice <<"), switching to the default one. Error : " << Pa_GetErrorText(errorOpening);
errorOpening = Pa_OpenDefaultStream( &stream,
0, /* no input channels */
1, /* mono output */
paInt8, /* 8 bits output */
SAMPLE_RATE,
FRAME_PER_BUFFER, /* frames per buffer, i.e. the number
of sample frames that PortAudio will
request from the callback. Many apps
may want to use
paFramesPerBufferUnspecified, which
tells PortAudio to pick the best,
possibly changing, buffer size.*/
audioCallback, /* this is your callback function */
this ); /*This is a pointer that will be passed to
your callback*/
}
if(errorOpening != paNoError)
return false;
if(Pa_StartStream( stream ) != paNoError)
return false;
And it fails :
Can't open selected device ( "Sortie intégr" ), switching to the default one. Error : Invalid error code (value greater than zero)
But I can't figure why OpenStream fails with a strange error code and Pa_OpenDefaultStream works like a charm.
So :
Why does it fails ?
Why does it throw a wrong error code ?
I assume you use C++ (though there are several curious and and or in your code.)
If your for loop didn't find any PaDeviceInfo which satisfies eviceInfo->maxOutputChannels > 0 && deviceInfo->name == outputDevice, then your outputDeviceInfo is left un-initialized. That means its channelConnect can have any values including large negative values. Then Pa_OpenStream isn't invoked and your errorOpening is also left un-initialized. I bet that's the reason of Invalid error code (value greater than zero) when you feed it into Pa_GetErrorText().