Related
I write driver .
Creates an Device Object (name = ICOCTL_1) when the service starts but getlastError function return not_foun_file(code 2)
enter image description here
void CUserAppDlg::OnBnClickedbtncreate(){
deviceHandle = CreateFile(L"\\\\.\\IOCTL_1", GENERIC_ALL, 0, 0, OPEN_EXISTING,
FILE_ATTRIBUTE_SYSTEM, 0);
DWORD data = GetLastError();
TCHAR s[100];
_stprintf_s(s, _T("%X"), data);
MessageBox(s);}
I need to do some math on the pixels of a GL texture. I have a working OpenCL kernel. I can convert the GL texture to an OpenCL buffer (at least, it doesn't give an error). But when I try to set that buffer as an argument to the kernel I get error -38 (CL_INVALID_MEM_OBJECT).
I originally tried it using rust, but when that was failing, I switched to C just to see if the problem existed independent of rust's wrappers.
This is my C app that is duct taped together from a couple of examples (c++ -g -o check2 check2.cxx -lOpenCL -lGL -lX11):
/*
https://www.khronos.org/opengl/wiki/Tutorial:_OpenGL_3.0_Context_Creation_(GLX)
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <GL/gl.h>
#include <GL/glx.h>
#include <CL/cl.h>
#include <CL/cl_gl.h>
#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*);
// Helper to check for extension string presence. Adapted from:
// http://www.opengl.org/resources/features/OGLextensions/
static bool isExtensionSupported(const char *extList, const char *extension)
{
const char *start;
const char *where, *terminator;
/* Extension names should not have spaces. */
where = strchr(extension, ' ');
if (where || *extension == '\0')
return false;
/* It takes a bit of care to be fool-proof about parsing the
OpenGL extensions string. Don't be fooled by sub-strings,
etc. */
for (start=extList;;) {
where = strstr(start, extension);
if (!where)
break;
terminator = where + strlen(extension);
if ( where == start || *(where - 1) == ' ' )
if ( *terminator == ' ' || *terminator == '\0' )
return true;
start = terminator;
}
return false;
}
static bool ctxErrorOccurred = false;
static int ctxErrorHandler( Display *dpy, XErrorEvent *ev )
{
ctxErrorOccurred = true;
return 0;
}
void test_kernel(cl_mem a_mem_obj, cl_mem b_mem_obj, cl_mem c_mem_obj, cl_kernel kernel, int LIST_SIZE, cl_command_queue command_queue)
{
int err;
err = clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&a_mem_obj);
printf("err? %d\tset kernel arg 0\n", err);
err = clSetKernelArg(kernel, 1, sizeof(cl_mem), (void *)&b_mem_obj);
printf("err? %d\n", err);
err = clSetKernelArg(kernel, 2, sizeof(cl_mem), (void *)&c_mem_obj);
printf("err? %d\n", err);
// Execute the OpenCL kernel on the list
size_t global_item_size = LIST_SIZE; // Process the entire lists
size_t local_item_size = 64; // Divide work items into groups of 64
err = clEnqueueNDRangeKernel(command_queue, kernel, 1, NULL, &global_item_size, &local_item_size, 0, NULL, NULL);
printf("err? %d\t(kernel diff)\n", err);
// Read the memory buffer C on the device to the local variable C
long long *C;
C= (long long*)malloc(sizeof(*C)*LIST_SIZE);
err = clEnqueueReadBuffer(command_queue, c_mem_obj, CL_TRUE, 0,
LIST_SIZE * sizeof(*C), C, 0, NULL, NULL);
printf("err? %d(copy result)\n", err);
for (int i=0; i<LIST_SIZE && i<10; i++) {
printf("%lld\n", C[i]);
}
free(C);
}
int main(int argc, char* argv[])
{
Display *display = XOpenDisplay(NULL);
if (!display)
{
printf("Failed to open X display\n");
exit(1);
}
// Get a matching FB config
static int visual_attribs[] =
{
GLX_X_RENDERABLE , True,
GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT,
GLX_RENDER_TYPE , GLX_RGBA_BIT,
GLX_X_VISUAL_TYPE , GLX_TRUE_COLOR,
GLX_RED_SIZE , 8,
GLX_GREEN_SIZE , 8,
GLX_BLUE_SIZE , 8,
GLX_ALPHA_SIZE , 8,
GLX_DEPTH_SIZE , 24,
GLX_STENCIL_SIZE , 8,
GLX_DOUBLEBUFFER , True,
//GLX_SAMPLE_BUFFERS , 1,
//GLX_SAMPLES , 4,
None
};
int glx_major, glx_minor;
// FBConfigs were added in GLX version 1.3.
if ( !glXQueryVersion( display, &glx_major, &glx_minor ) ||
( ( glx_major == 1 ) && ( glx_minor < 3 ) ) || ( glx_major < 1 ) )
{
printf("Invalid GLX version");
exit(1);
}
printf( "Getting matching framebuffer configs\n" );
int fbcount;
GLXFBConfig* fbc = glXChooseFBConfig(display, DefaultScreen(display), visual_attribs, &fbcount);
if (!fbc)
{
printf( "Failed to retrieve a framebuffer config\n" );
exit(1);
}
printf( "Found %d matching FB configs.\n", fbcount );
// Pick the FB config/visual with the most samples per pixel
printf( "Getting XVisualInfos\n" );
int best_fbc = -1, worst_fbc = -1, best_num_samp = -1, worst_num_samp = 999;
int i;
for (i=0; i<fbcount; ++i)
{
XVisualInfo *vi = glXGetVisualFromFBConfig( display, fbc[i] );
if ( vi )
{
int samp_buf, samples;
glXGetFBConfigAttrib( display, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf );
glXGetFBConfigAttrib( display, fbc[i], GLX_SAMPLES , &samples );
printf( " Matching fbconfig %d, visual ID 0x%2lx: SAMPLE_BUFFERS = %d,"
" SAMPLES = %d\n",
i, vi -> visualid, samp_buf, samples );
if ( best_fbc < 0 || samp_buf && samples > best_num_samp )
best_fbc = i, best_num_samp = samples;
if ( worst_fbc < 0 || !samp_buf || samples < worst_num_samp )
worst_fbc = i, worst_num_samp = samples;
}
XFree( vi );
}
GLXFBConfig bestFbc = fbc[ best_fbc ];
// Be sure to free the FBConfig list allocated by glXChooseFBConfig()
XFree( fbc );
#if 0
// Get a visual
XVisualInfo *vi = glXGetVisualFromFBConfig( display, bestFbc );
printf( "Chosen visual ID = 0x%lx\n", vi->visualid );
printf( "Creating colormap\n" );
XSetWindowAttributes swa;
Colormap cmap;
swa.colormap = cmap = XCreateColormap( display,
RootWindow( display, vi->screen ),
vi->visual, AllocNone );
swa.background_pixmap = None ;
swa.border_pixel = 0;
swa.event_mask = StructureNotifyMask;
printf( "Creating window\n" );
Window win = XCreateWindow( display, RootWindow( display, vi->screen ),
0, 0, 100, 100, 0, vi->depth, InputOutput,
vi->visual,
CWBorderPixel|CWColormap|CWEventMask, &swa );
if ( !win )
{
printf( "Failed to create window.\n" );
exit(1);
}
// Done with the visual info data
XFree( vi );
XStoreName( display, win, "GL 3.0 Window" );
printf( "Mapping window\n" );
XMapWindow( display, win );
#endif
// Get the default screen's GLX extension list
const char *glxExts = glXQueryExtensionsString( display,
DefaultScreen( display ) );
// NOTE: It is not necessary to create or make current to a context before
// calling glXGetProcAddressARB
glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0;
glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)
glXGetProcAddressARB( (const GLubyte *) "glXCreateContextAttribsARB" );
GLXContext ctx = 0;
// Install an X error handler so the application won't exit if GL 3.0
// context allocation fails.
//
// Note this error handler is global. All display connections in all threads
// of a process use the same error handler, so be sure to guard against other
// threads issuing X commands while this code is running.
ctxErrorOccurred = false;
int (*oldHandler)(Display*, XErrorEvent*) =
XSetErrorHandler(&ctxErrorHandler);
// Check for the GLX_ARB_create_context extension string and the function.
// If either is not present, use GLX 1.3 context creation method.
if ( !isExtensionSupported( glxExts, "GLX_ARB_create_context" ) ||
!glXCreateContextAttribsARB )
{
printf( "glXCreateContextAttribsARB() not found"
" ... using old-style GLX context\n" );
ctx = glXCreateNewContext( display, bestFbc, GLX_RGBA_TYPE, 0, True );
}
// If it does, try to get a GL 3.0 context!
else
{
int context_attribs[] =
{
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
GLX_CONTEXT_MINOR_VERSION_ARB, 0,
//GLX_CONTEXT_FLAGS_ARB , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
None
};
printf( "Creating context\n" );
ctx = glXCreateContextAttribsARB( display, bestFbc, 0,
True, context_attribs );
// Sync to ensure any errors generated are processed.
XSync( display, False );
if ( !ctxErrorOccurred && ctx )
printf( "Created GL 3.0 context\n" );
else
{
// Couldn't create GL 3.0 context. Fall back to old-style 2.x context.
// When a context version below 3.0 is requested, implementations will
// return the newest context version compatible with OpenGL versions less
// than version 3.0.
// GLX_CONTEXT_MAJOR_VERSION_ARB = 1
context_attribs[1] = 1;
// GLX_CONTEXT_MINOR_VERSION_ARB = 0
context_attribs[3] = 0;
ctxErrorOccurred = false;
printf( "Failed to create GL 3.0 context"
" ... using old-style GLX context\n" );
ctx = glXCreateContextAttribsARB( display, bestFbc, 0,
True, context_attribs );
}
}
// Sync to ensure any errors generated are processed.
XSync( display, False );
// Restore the original error handler
XSetErrorHandler( oldHandler );
if ( ctxErrorOccurred || !ctx )
{
printf( "Failed to create an OpenGL context\n" );
exit(1);
}
// Verifying that context is a direct context
if ( ! glXIsDirect ( display, ctx ) )
{
printf( "Indirect GLX rendering context obtained\n" );
}
else
{
printf( "Direct GLX rendering context obtained\n" );
}
printf( "Making context current\n" );
glXMakeCurrent( display, 0, ctx );
#define IMAGE_DIAM 512
#define LIST_SIZE (IMAGE_DIAM*IMAGE_DIAM*3)
GLuint texture_id;
{
glGenTextures(1, &texture_id);
printf("err? %d\n", glGetError());
glBindTexture(GL_TEXTURE_2D, texture_id);
printf("err? %d\t(bind texture)\n", glGetError());
unsigned char random_stack_crap[LIST_SIZE];
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, IMAGE_DIAM, IMAGE_DIAM, 0, GL_RGB, GL_UNSIGNED_BYTE, random_stack_crap);
printf("err? %d\n", glGetError());
}
//
//
//
cl_platform_id platform;
clGetPlatformIDs(1, &platform, NULL);
cl_device_id device;
clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &device, NULL);
printf("device\t%p\n", device);
printf ("context\t%p\t%p\n", ctx, glXGetCurrentContext());
printf ("display\t%p\t%p\n", display, glXGetCurrentDisplay());
cl_context_properties props[] =
{
CL_GL_CONTEXT_KHR,
(cl_context_properties) glXGetCurrentContext(),
CL_GLX_DISPLAY_KHR,
(cl_context_properties) glXGetCurrentDisplay(),
CL_CONTEXT_PLATFORM,
(cl_context_properties) platform,
0
};
int err=0;
cl_context cl = clCreateContext(props, 1, &device, NULL, NULL, &err);
printf("err? %d\n", err);
printf("cl context %p\n", cl);
//
// https://www.eriksmistad.no/getting-started-with-opencl-and-gpu-computing/
//
cl_command_queue command_queue = clCreateCommandQueue(cl, device, 0, &err);
printf("err? %d\n", err);
printf("cl queue %p\n", command_queue);
// Create memory buffers on the device for each vector
cl_mem z_mem_obj = clCreateFromGLTexture( cl,
CL_MEM_READ_WRITE,
GL_TEXTURE_2D,
0,
texture_id,
&err);
cl_mem a_mem_obj = clCreateBuffer(cl, CL_MEM_READ_ONLY,
LIST_SIZE , NULL, &err);
printf("err? %d\n", err);
cl_mem b_mem_obj = clCreateBuffer(cl, CL_MEM_READ_ONLY,
LIST_SIZE , NULL, &err);
printf("err? %d\n", err);
cl_mem c_mem_obj = clCreateBuffer(cl, CL_MEM_WRITE_ONLY,
LIST_SIZE*8 , NULL, &err);
printf("err? %d\n", err);
// Copy the lists A and B to their respective memory buffers
{
unsigned char *A = (unsigned char*) malloc(LIST_SIZE);
for (int i=0; i<LIST_SIZE; i++) {
A[i] = i+2;
}
unsigned char *B = (unsigned char*) malloc(LIST_SIZE);
for (int i=0; i<LIST_SIZE; i++) {
B[i] = 2*i;
}
err = clEnqueueWriteBuffer(command_queue, a_mem_obj, CL_TRUE, 0,
LIST_SIZE, A, 0, NULL, NULL);
printf("err? %d\tcopy A\n", err);
err = clEnqueueWriteBuffer(command_queue, b_mem_obj, CL_TRUE, 0,
LIST_SIZE, B, 0, NULL, NULL);
printf("err? %d\tcopy B\n", err);
}
const char* source_str = "__kernel void diff(__global uchar* rgb_a, __global uchar* rgb_b, __global ulong * diff_out)\n\
{\n\
int idx = get_global_id(0);\n\
diff_out[idx] = abs((int)rgb_a[idx] - (int)rgb_b[idx]);\n\
}";
size_t source_size = strlen(source_str);
// Create a program from the kernel source
cl_program program = clCreateProgramWithSource(cl, 1,
(const char **)&source_str, (const size_t *)&source_size, &err);
printf("err? %d\t(create program)\n", err);
// Build the program
err = clBuildProgram(program, 1, &device, NULL, NULL, NULL);
printf("err? %d\n", err);
// Create the OpenCL kernel
cl_kernel kernel = clCreateKernel(program, "diff", &err);
printf("err? %d\n", err);
err = clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&a_mem_obj);
printf("err? %d\n", err);
err = clSetKernelArg(kernel, 1, sizeof(cl_mem), (void *)&b_mem_obj);
printf("err? %d\n", err);
err = clSetKernelArg(kernel, 2, sizeof(cl_mem), (void *)&c_mem_obj);
printf("err? %d\n", err);
// Execute the OpenCL kernel on the list
size_t global_item_size = LIST_SIZE; // Process the entire lists
size_t local_item_size = 64; // Divide work items into groups of 64
err = clEnqueueNDRangeKernel(command_queue, kernel, 1, NULL, &global_item_size, &local_item_size, 0, NULL, NULL);
printf("err? %d\t(kernel diff)\n", err);
// Read the memory buffer C on the device to the local variable C
long long *C;
C= (long long*)malloc(sizeof(*C)*LIST_SIZE);
err = clEnqueueReadBuffer(command_queue, c_mem_obj, CL_TRUE, 0,
LIST_SIZE * sizeof(*C), C, 0, NULL, NULL);
printf("err? %d(copy resul)\n", err);
for (int i=0; i<LIST_SIZE && i<10; i++) {
printf("%lld\n", C[i]);
}
free(C);
test_kernel(a_mem_obj, b_mem_obj, c_mem_obj, kernel, LIST_SIZE, command_queue);
test_kernel(z_mem_obj, b_mem_obj, c_mem_obj, kernel, LIST_SIZE, command_queue);
return 0;
}
The output on my linux/gentoo box with mesa-progs-8.4.0 is
Getting matching framebuffer configs
Found 10 matching FB configs.
Getting XVisualInfos
Matching fbconfig 0, visual ID 0x24: SAMPLE_BUFFERS = 0, SAMPLES = 0
Matching fbconfig 1, visual ID 0x7a: SAMPLE_BUFFERS = 0, SAMPLES = 0
Matching fbconfig 2, visual ID 0x38: SAMPLE_BUFFERS = 1, SAMPLES = 2
Matching fbconfig 3, visual ID 0x8e: SAMPLE_BUFFERS = 1, SAMPLES = 2
Matching fbconfig 4, visual ID 0x3a: SAMPLE_BUFFERS = 1, SAMPLES = 4
Matching fbconfig 5, visual ID 0x90: SAMPLE_BUFFERS = 1, SAMPLES = 4
Matching fbconfig 6, visual ID 0x44: SAMPLE_BUFFERS = 1, SAMPLES = 8
Matching fbconfig 7, visual ID 0x9a: SAMPLE_BUFFERS = 1, SAMPLES = 8
Matching fbconfig 8, visual ID 0x4c: SAMPLE_BUFFERS = 1, SAMPLES = 16
Matching fbconfig 9, visual ID 0xa2: SAMPLE_BUFFERS = 1, SAMPLES = 16
Creating context
Created GL 3.0 context
Direct GLX rendering context obtained
Making context current
err? 0
err? 0 (bind texture)
err? 0
device 0x557c1755cef0
context 0x557c173e0b68 0x557c173e0b68
display 0x557c172ee950 0x557c172ee950
err? 0
cl context 0x557c17559340
err? 0
cl queue 0x557c177dd080
err? 0
err? 0
err? 0
err? 0 copy A
err? 0 copy B
err? 0 (create program)
err? 0
err? 0
err? 0
err? 0
err? 0
err? 0 (kernel diff)
err? 0(copy resul)
2
1
0
1
2
3
4
5
6
7
err? 0 set kernel arg 0
err? 0
err? 0
err? 0 (kernel diff)
err? 0(copy result)
2
1
0
1
2
3
4
5
6
7
err? -38 set kernel arg 0
err? 0
err? 0
err? 0 (kernel diff)
err? 0(copy result)
2
1
0
1
2
3
4
5
6
7
Notice the err? -38 set kernel arg 0 which corresponds to the final test where I pass z_mem_obj to use the buffer converted from a GL texture.
clinfo | grep khr lists cl_khr_gl_sharing in the Platform Extensions and Device Extensions.
So I am working on a project in C on the Raspberry Pi Model 3B+ and I am using GTK to draw. I have GTK on its own thread and my program logic on its own thread.
Basically, my program takes pictures from 3 DSLRs using gphoto2 and saves them to jpgs, then GTK loads those JPGs, resizes them to 500x300 with a pixbuf and updates the picture in the GUI
The problem I am having, is that the GTK window will fail to redraw and it is very inconsistent when, sometimes it will happen after 11 pictures are taken, sometimes it will happen after even 2 or 3 pictures are taken, there is no consistent fault.
Any help would be appreciated, one thread just initializes gtk and then calls GTK main to do the GUI, and the other does my program logic, updates the jpg files and then updates the GTK objects for the gtk main to redraw. Maybe this has something to do with my thread updating the gtk objects at a bad time and the loop running gtk main crashes and halts??
My original GUI looks like this:
The black boxes arent the problem, those are just the default blank pixbufs before any pictures have been taken. The problem is that it will fail and the image will just turn to the background color (see on the grid "CAM2 Front") and then after this call the whole window glitches and does nothing. I can drag it around and it will draw stuff I drag it over but thats it.
I know it is the whole app that is failing to draw because I am getting results like this when I move the window around.
Any help is super appreciated. I have been playing around with this for a while now.
This is the code called by my program logic main thread loop to update the image to the new jpg taken:
void set_image_scaled(GtkWidget* img, const char* path) {
pixbuf = gdk_pixbuf_new_from_file(path, &err);
g_assert_no_error(err);
pxbscaled = gdk_pixbuf_scale_simple(pixbuf, 500, 300, GDK_INTERP_BILINEAR);
gtk_image_set_from_pixbuf(GTK_IMAGE(img), pxbscaled);
g_object_unref(pixbuf);
g_object_unref(pxbscaled);
}
This is the main logic thread that updates the GtkImage object (calls set_image_scaled()):
void* cam_main() {
while (running == 1) {
if (digitalRead(4) == 0)
{
printf("taking pics of %s item %i\n", (front == 1) ? "front" : "back", pic);
for (int i = 0; i < count; i++)
{
int fd, retval;
CameraFile *file;
CameraFilePath cfPath;
strcpy(cfPath.folder, "/");
strcpy(cfPath.name, "foo1.jpg");
printf("Capturing cam%i...\n", i + 1);
int res = gp_camera_capture(cams[i], GP_CAPTURE_IMAGE, &cfPath, context);
//printf(gp_port_result_as_string(res));
printf("capture result: %i\n", res);
//Camera won't take pic if busy and will continue to program end
char buf[256];
snprintf(buf, sizeof(buf), "%s/cam-%i_%i_%s.jpg", workingDir, i + 1, pic, (front == 1) ? "a_front" : "b_back"); //a_ to make front come before back otherwise systems will order incorrectly
fd = open(buf, O_CREAT | O_WRONLY, 0644);
retval = gp_file_new_from_fd(&file, fd);
retval = gp_camera_file_get(cams[i], cfPath.folder, cfPath.name, GP_FILE_TYPE_NORMAL, file, context);
retval = gp_camera_file_delete(cams[i], cfPath.folder, cfPath.name, context);
gp_file_free(file);
//debug
//if (front == 1 && i == 0)
//set_image_scaled(front_cams[0], buf);
if (front == 1)
set_image_scaled(front_cams[i], buf);
else
set_image_scaled(back_cams[i], buf);
}
if (front == 1)
front = 0;
else
{
front = 1;
pic += 1;
}
printf("pics taken...\n");
}
}
}
My whole code for reference:
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdarg.h>
#include <gphoto2/gphoto2-camera.h>
#include <gphoto2/gphoto2-context.h>
#include <wiringPi.h>
#include <gtk/gtk.h>
#include <pthread.h>
//program
static int running = 1;
//libgphoto2
static CameraList* list;
static Camera** cams;
static GPContext* context;
static const char *name, *value;
static int ret, count;
static int pic = 0;
static int front = 1;
static const char* workingDir;
//GTK
static GtkWidget *window, *vbox,*hboxDir, *hboxCamLabels, *hboxFrontPics, *hboxBackPics, *hboxStatus, *lblDir, *btnConfigDir, *lblCams, *lblFront, *lblBack, *lblCurrentStatus;
static GtkWidget *front_cams[3];
static GtkWidget *back_cams[3];
static GdkPixbuf *pxbscaled = NULL;
static GdkPixbuf *pixbuf = NULL;
static GError* err = NULL;
static void btnConfigDir_ConfigureDirectory(GtkWidget* widget, gpointer data) {
GtkWidget *dialog;
GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_OPEN;
gint res;
dialog = gtk_file_chooser_dialog_new ("Open File", window,
action,
"_Cancel",
GTK_RESPONSE_CANCEL,
"_Open",
GTK_RESPONSE_ACCEPT,
NULL);
res = gtk_dialog_run (GTK_DIALOG (dialog));
if (res == GTK_RESPONSE_ACCEPT)
{
char *filename;
GtkFileChooser *chooser = GTK_FILE_CHOOSER (dialog);
workingDir = gtk_file_chooser_get_filename (chooser);
}
//gtk_label_set_text((GTK_LABEL)lblDir, workingDir);
gtk_widget_destroy (dialog);
}
void* main_gtk() {
//INIT GTK
//SETUP WINDOW
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
//button1=gtk_button_new_with_label("Click me");
//gtk_button_set_label(GTK_BUTTON(button1), "click me 1");
g_signal_connect(window,"delete-event", G_CALLBACK(gtk_main_quit), NULL);
workingDir = "/media/pi/SD CARD";
lblDir = gtk_label_new("Save to: dir\t");
btnConfigDir = gtk_button_new_with_label("Configure Directory");
g_signal_connect(btnConfigDir, "clicked", G_CALLBACK(btnConfigDir_ConfigureDirectory), NULL);
lblCams = gtk_label_new("\t\t\t\t\t\t\t\tCAM 1\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tCAM2\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tCAM3");
lblFront = gtk_label_new("Front");
lblBack = gtk_label_new("Back ");
lblCurrentStatus = gtk_label_new("Current Status: Idle");
//SET WINDOW SIZE AND TITLE
//gtk_widget_set_size_request(window, 600, 400);
gtk_window_set_title(GTK_WINDOW(window), "CaptureGui");
//RESIZE IMAGES
//image
front_cams[0] = gtk_image_new();
front_cams[1] = gtk_image_new();
front_cams[2] = gtk_image_new();
back_cams[0] = gtk_image_new();
back_cams[1] = gtk_image_new();
back_cams[2] = gtk_image_new();
GdkPixbuf* pxb;
pxb = gdk_pixbuf_new(0, 0, 8, 500, 300);
gtk_image_set_from_pixbuf(GTK_IMAGE(front_cams[0]), pxb);
gtk_image_set_from_pixbuf(GTK_IMAGE(front_cams[1]), pxb);
gtk_image_set_from_pixbuf(GTK_IMAGE(front_cams[2]), pxb);
gtk_image_set_from_pixbuf(GTK_IMAGE(back_cams[0]), pxb);
gtk_image_set_from_pixbuf(GTK_IMAGE(back_cams[1]), pxb);
gtk_image_set_from_pixbuf(GTK_IMAGE(back_cams[2]), pxb);
//g_print("1");
//front_cams[0] = gtk_image_new_from_file("/media/pi/SD CARD/cam-1_0_a_front.jpg");
//set_image_scaled(front_cams[0], "/media/pi/SD CARD/cam-1_1_a_front.jpg");
//set_image_scaled(front_cams[1], "/media/pi/SD CARD/cam-1_1_a_front.jpg");
//set_image_scaled(front_cams[2], "/media/pi/SD CARD/cam-1_1_b_back.jpg");
//PACK
hboxDir = gtk_box_new(0, 0);
hboxCamLabels = gtk_box_new(0, 0);
hboxFrontPics = gtk_box_new(0, 0);
hboxBackPics = gtk_box_new(0, 0);
hboxStatus = gtk_box_new(0, 0);
vbox = gtk_vbox_new(0, 10);
gtk_box_pack_end(GTK_BOX(hboxDir), btnConfigDir, 0, 0, 0);
gtk_box_pack_end(GTK_BOX(hboxDir), lblDir, 0, 0, 0);
gtk_box_pack_start(GTK_BOX(hboxCamLabels), lblCams, 0, 0, 0);
gtk_box_pack_start(GTK_BOX(hboxFrontPics), lblFront, 0, 0, 0);
gtk_box_pack_start(GTK_BOX(hboxFrontPics), front_cams[0], 0, 0, 10);
gtk_box_pack_start(GTK_BOX(hboxFrontPics), front_cams[1], 0, 0, 10);
gtk_box_pack_start(GTK_BOX(hboxFrontPics), front_cams[2], 0, 0, 10);
gtk_box_pack_start(GTK_BOX(hboxBackPics), lblBack, 0, 0, 0);
gtk_box_pack_start(GTK_BOX(hboxBackPics), back_cams[0], 0, 0, 10);
gtk_box_pack_start(GTK_BOX(hboxBackPics), back_cams[1], 0, 0, 10);
gtk_box_pack_start(GTK_BOX(hboxBackPics), back_cams[2], 0, 0, 10);
gtk_box_pack_start(GTK_BOX(hboxStatus), lblCurrentStatus, 0, 0, 10);
gtk_box_pack_start(GTK_BOX(vbox), hboxDir, 0, 0, 0);
gtk_box_pack_start(GTK_BOX(vbox), hboxCamLabels, 0, 0, 0);
gtk_box_pack_start(GTK_BOX(vbox), hboxFrontPics, 0, 0, 0);
gtk_box_pack_start(GTK_BOX(vbox), hboxBackPics, 0, 0, 0);
gtk_box_pack_start(GTK_BOX(vbox), hboxStatus, 0, 0, 0);
//gtk_box_pack_start(GTK_BOX(hbox), front_cams[0], 0, 0, 0);
//gtk_box_pack_start(GTK_BOX(hbox), front_cams[1], 0, 0, 0);
//gtk_box_pack_start(GTK_BOX(hbox), front_cams[2], 0, 0, 0);
//gtk_box_pack_start(GTK_BOX(hbox), back_cams[0], 0, 0, 0);
//gtk_box_pack_start(GTK_BOX(hbox), back_cams[1], 0, 0, 0);
//gtk_box_pack_start(GTK_BOX(hbox), back_cams[2], 0, 0, 0);
gtk_container_add(GTK_CONTAINER(window), vbox);
//ADD ELEMENTS TO GUI
//gtk_container_add(GTK_CONTAINER(window), image1);
//gtk_container_add(GTK_CONTAINER(window), image2);
//image2 = gtk_image_new_from_file("/media/pi/SD CARD/cam-1_0_b_back.jpg");
//gtk_container_add(GTK_CONTAINER(window), image2);
//SHOW GUI
gtk_widget_show_all(window);
gtk_main();
}
void set_image_scaled(GtkWidget* img, const char* path) {
pixbuf = gdk_pixbuf_new_from_file(path, &err);
g_assert_no_error(err);
pxbscaled = gdk_pixbuf_scale_simple(pixbuf, 500, 300, GDK_INTERP_BILINEAR);
gtk_image_set_from_pixbuf(GTK_IMAGE(img), pxbscaled);
g_object_unref(pixbuf);
g_object_unref(pxbscaled);
}
void* cam_main() {
while (running == 1) {
if (digitalRead(4) == 0)
{
printf("taking pics of %s item %i\n", (front == 1) ? "front" : "back", pic);
for (int i = 0; i < count; i++)
{
int fd, retval;
CameraFile *file;
CameraFilePath cfPath;
strcpy(cfPath.folder, "/");
strcpy(cfPath.name, "foo1.jpg");
printf("Capturing cam%i...\n", i + 1);
int res = gp_camera_capture(cams[i], GP_CAPTURE_IMAGE, &cfPath, context);
//printf(gp_port_result_as_string(res));
printf("capture result: %i\n", res);
//Camera won't take pic if busy and will continue to program end
char buf[256];
snprintf(buf, sizeof(buf), "%s/cam-%i_%i_%s.jpg", workingDir, i + 1, pic, (front == 1) ? "a_front" : "b_back"); //a_ to make front come before back otherwise systems will order incorrectly
fd = open(buf, O_CREAT | O_WRONLY, 0644);
retval = gp_file_new_from_fd(&file, fd);
retval = gp_camera_file_get(cams[i], cfPath.folder, cfPath.name, GP_FILE_TYPE_NORMAL, file, context);
retval = gp_camera_file_delete(cams[i], cfPath.folder, cfPath.name, context);
gp_file_free(file);
//debug
//if (front == 1 && i == 0)
//set_image_scaled(front_cams[0], buf);
if (front == 1)
set_image_scaled(front_cams[i], buf);
else
set_image_scaled(back_cams[i], buf);
}
if (front == 1)
front = 0;
else
{
front = 1;
pic += 1;
}
printf("pics taken...\n");
}
}
}
int main(int argc, char **argv)
{
//Kill any processes using cams
system("pkill -f gphoto2");
//main_gtk();
gtk_init(&argc, &argv);
//Wiring pi init
wiringPiSetupGpio();
//Init
context = gp_context_new();
detect_cams();
pthread_t logic_thread_handle, gui_thread_handle;
pthread_create(&logic_thread_handle, NULL, cam_main, NULL);
pthread_create(&gui_thread_handle, NULL, main_gtk, NULL);
pthread_join(gui_thread_handle, 0);
pthread_join(logic_thread_handle, 0);
//Deinit
for (int i = 0; i < count; i++)
{
gp_camera_exit(cams[i], context);
gp_camera_free(cams[i]);
}
return 0;
}
void detect_cams() {
//Detecting all cameras and loading them into mem
//Detecting all cameras
ret = gp_list_new(&list);
if (ret < GP_OK) return 1;
gp_list_reset(list);
count = gp_camera_autodetect(list, context);
if (count < 1)
{
printf("No cameras detected.\n");
return 1;
}
//Open all cameras
printf("Number of cameras: %d\n", count);
cams = calloc(sizeof (Camera*), count);
for (int i = 0; i < count; i++)
{
gp_list_get_name(list, i, &name);
gp_list_get_value(list, i, &value);
ret = open_cam(&cams[i], name, value, context);
if (ret < GP_OK)
fprintf(stderr, "Camera %s on port %s failed to open\n", name, value);
}
}
int open_cam(Camera ** camera, const char *model, const char *port, GPContext *context) {
GPPortInfoList *portinfolist = NULL;
CameraAbilitiesList *abilities = NULL;
int ret, m, p;
CameraAbilities a;
GPPortInfo pi;
ret = gp_camera_new (camera);
if (ret < GP_OK) return ret;
if (!abilities) {
/* Load all the camera drivers we have... */
ret = gp_abilities_list_new (&abilities);
if (ret < GP_OK) return ret;
ret = gp_abilities_list_load (abilities, context);
if (ret < GP_OK) return ret;
}
/* First lookup the model / driver */
m = gp_abilities_list_lookup_model (abilities, model);
if (m < GP_OK) return ret;
ret = gp_abilities_list_get_abilities (abilities, m, &a);
if (ret < GP_OK) return ret;
ret = gp_camera_set_abilities (*camera, a);
if (ret < GP_OK) return ret;
if (!portinfolist) {
/* Load all the port drivers we have... */
ret = gp_port_info_list_new (&portinfolist);
if (ret < GP_OK) return ret;
ret = gp_port_info_list_load (portinfolist);
if (ret < 0) return ret;
ret = gp_port_info_list_count (portinfolist);
if (ret < 0) return ret;
}
/* Then associate the camera with the specified port */
p = gp_port_info_list_lookup_path (portinfolist, port);
switch (p) {
case GP_ERROR_UNKNOWN_PORT:
fprintf (stderr, "The port you specified "
"('%s') can not be found. Please "
"specify one of the ports found by "
"'gphoto2 --list-ports' and make "
"sure the spelling is correct "
"(i.e. with prefix 'serial:' or 'usb:').",
port);
break;
default:
break;
}
if (p < GP_OK) return p;
ret = gp_port_info_list_get_info (portinfolist, p, &pi);
if (ret < GP_OK) return ret;
ret = gp_camera_set_port_info (*camera, pi);
if (ret < GP_OK) return ret;
return GP_OK;
}
You cannot use GTK from different threads; only the thread that calls gtk_init() and gtk_main() can operate on GTK (and GDK) API.
The appropriate way to use threads within a GTK application is to use a worker thread for your long-running, blocking code, and whenever you need to update the GUI, use g_main_context_invoke() with a NULL main context.
Alternatively, you can use GTask to create your own asynchronous task running in a thread, and update the GUI once the task terminates.
In your example code, you should only ever call set_image_scaled() through g_main_context_invoke(), and you should not put the GUI inside its own thread.
I use Windows 7 and Microsoft Visual Studio 2010.
This is my code below (I start notepad.exe and want to find focused sub-window handle:
STARTUPINFO si = { 0 };
PROCESS_INFORMATION pi = { 0 };
memset(&si, 0, sizeof(si));
memset(&pi, 0, sizeof(pi));
si.cb = sizeof(si);
BOOL bResult = CreateProcess("c:\\windows\\syswow64\\notepad.exe", NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
WaitForInputIdle(pi.hProcess, INFINITE);
HWND hWnd = FindWindow("Notepad", NULL);
DWORD dwTID;
dwTID = GetWindowThreadProcessId(hWnd, NULL);
GUITHREADINFO info = { sizeof(info) };
AttachThreadInput(GetCurrentThreadId(), dwTID, TRUE);
GetGUIThreadInfo(dwTID, &info);
AttachThreadInput(GetCurrentThreadId(), dwTID, FALSE);
FindWindow() returns correct hWnd; and GetWindowThreadProcessId() returns correct TID of window thread (have checked it in Spy++). Both AttachThreadInput() and GetGUIThreadInfo() return TRUE. But info contains only zeroes (except cbSize member which contains size of structure). If I use GetFocus() I still receive NULL.
What am I doing wrong?
I'm having a problem with the serial port code.
I just do:
opencomm();
send();
closecomm();
and the ClearCommError() (inside recv()) returns in
comstat.cbInQue the same amount that was sent.
So, if sizeof (sendbuff) is 100,
I get 100 in comstat.cbInQue.
After reading one byte with ReadFile, comstat.cbInQue decrements (after subsequent ClearCommError(), of course).
The values read are not the ones that were written.
There is no device connected to the port.
The strangest thing is this code used to work, but not anymore.
WORD sendbuff[128];
static HANDLE hComm;
static void opencomm (void)
{
static COMMTIMEOUTS timeouts = {0,0,0,0,0};
static DCB dcb = {
sizeof (DCB), // DCBlength
115200, // * BaudRate
1, // fBinary
0, // * fParity
0, // fOutxCtsFlow
0, // fOutxDsrFlow
0, // fDtrControl
0, // fDsrSensitivity
1, // fTXContinueOnXoff
0, // fOutX
0, // fInX
0, // fErrorChar
0, // fNull
0, // fRtsControl
0, // fAbortOnError
0, // fDummy2
0, // wReserved
8*k, // XonLim
2*k, // XoffLim
8, // * ByteSize
0, // * Parity
0, // * StopBits
0, // XonChar
1, // XoffChar
0, // ErrorChar
0, // EofChar
0, // EvtChar
0 // wReserved1
};
hComm = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hComm != INVALID_HANDLE_VALUE) {
SetupComm(hComm, 16*k, 16*k);
SetCommState(hComm, &dcb);
SetCommTimeouts(hComm, &timeouts);
}
}
static void closecomm (void)
{
CloseHandle(hComm);
}
static BYTE recv (void)
{
BYTE text;
DWORD temp;
COMSTAT comstat;
while (1) {
ClearCommError(hComm, &temp, &comstat);
if (comstat.cbInQue != 0) break;
Sleep(1);
}
ReadFile(hComm, &text, 1, &temp, NULL);
return text;
}
static void send (void)
{
DWORD temp;
// send to other comp
WriteFile(hComm, sendbuff, sizeof (sendbuff), &temp, NULL);
// check other comp done
if (recv() != 0xAA) {
Beep(1000, 100);
quit(); // comm error
}
}
It was the cable. Not properly shielded and too long.