Thanks Claude!
I got lots of help from Matju on IRC so things are compiling.
I'm now getting a segfault when trying to access a member of the
structure in the thread function:
#0 0xf7d531cb in strlen () from /lib/i686/cmov/libc.so.6
#1 0xf7d1f648 in vfprintf () from /lib/i686/cmov/libc.so.6
#2 0xf7d43e04 in vsnprintf () from /lib/i686/cmov/libc.so.6
#3 0x080c68d6 in post (fmt=0xf7f7db5a "My symbol: %s")
at s_print.c:51
#4 0xf7f7d829 in mythread ()
from /home/bbogart/src/gphoto/src/pd-external/gphoto2.pd_linux
The way I'm trying to access the member is as follows:
post("My symbol: %s", ((struct floatArgStruct *)threadArgs)->s->s_name);
I've attached the full source.
All this typdef stuff is new to me, so I may have messed up something
obvious.
Thanks,
.b.
Claude Heiland-Allen wrote:
>> post("My symbol: %s", threadArgs.s->s_name); // line 92
>
> threadArgs is a pointer, '.' is only for structs/unions
>
> try '->' instead of '.' to both dereference pointer and access member
/* Gphoto2 PD External */
/* Copyright Ben Bogart, 2009 */
/* This program is distributed under the params of the GNU Public License */
///////////////////////////////////////////////////////////////////////////////////
/* This file is part of the Gphoto2 PD External. */
/* */
/* Gphoto2 PD External is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 2 of the License, or */
/* (at your option) any later version. */
/* */
/* The Gphoto2 PD External is distributed in the hope that they will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with the Chaos PD Externals; if not, write to the Free Software */
/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
///////////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <m_pd.h>
#include <fcntl.h>
#include <pthread.h>
#include <gphoto2/gphoto2-camera.h>
t_class *gphoto2_class;
typedef struct gphoto2_struct {
t_object x_obj;
t_outlet *outlet;
} gphoto2_struct;
// TODO change this to work on all funcs
typedef struct floatArgStruct {
gphoto2_struct *gphoto2;
t_symbol *s;
} floatArgStruct;
static void listConfig(gphoto2_struct *gphoto2) {
int gp_ret, numsections, numchildren, i, j;
Camera *camera;
CameraWidget *config = NULL;
CameraWidget *child = NULL;
CameraWidget *child2 = NULL;
CameraWidgetType type;
const char *name;
gp_ret = gp_camera_new (&camera);
if (gp_ret != 0) {error("gphoto2: ERROR: %s\n", gp_result_as_string(gp_ret)); gp_camera_unref(camera); return;}
// INIT camera (without context)
gp_ret = gp_camera_init (camera, NULL);
if (gp_ret != 0) {error("gphoto2: ERROR: %s\n", gp_result_as_string(gp_ret));}
if (gp_ret == -105) {post("gphoto2: Are you sure the camera is supported, connected and powered on?"); gp_camera_unref(camera); return;}
gp_ret = gp_camera_get_config (camera, &config, NULL); // get config from camera
if (gp_ret != 0) {error("gphoto2: ERROR: %s\n", gp_result_as_string(gp_ret)); gp_camera_unref(camera); return;}
numsections = gp_widget_count_children(config);
for (i=0; i<numsections; i++) {
gp_widget_get_child (config, i, &child);
gp_widget_get_name (child, &name);
gp_widget_get_type (child, &type);
if (type == GP_WIDGET_SECTION) {
post("gphoto2: Section: %s\n", name);
numchildren = gp_widget_count_children(child);
for (j=0; j<numchildren; j++) {
gp_widget_get_child (child, j, &child2);
gp_widget_get_name (child2, &name);
gp_widget_get_type (child2, &type);
post("gphoto2: Child: %s\n", name); // send through outlet?
}
}
}
gp_camera_unref(camera);
//widget unref?
}
void *mythread(void *threadArgs) {
int i;
post("thread start.");
post("My symbol: %s", ((struct floatArgStruct *)threadArgs)->s->s_name);
outlet_float(((struct floatArgStruct *)threadArgs)->gphoto2->x_obj.ob_outlet, 0.00001);
post("thread end.");
}
static void wrapGetConfig(gphoto2_struct *gphoto2, t_symbol *s) {
int ret;
pthread_t thread1;
// instance of structure
floatArgStruct *threadArgs = (floatArgStruct *)malloc(sizeof(floatArgStruct));
// packaging arguments into structure
threadArgs->gphoto2 = gphoto2;
threadArgs->s = s;
post("I'm about to start the thread.");
// Create thread
ret = pthread_create( &thread1, NULL, mythread, &threadArgs);
}
void *getConfig(gphoto2_struct *gphoto2, t_symbol *s) {
int gp_ret;
const char *textVal;
const int *toggleVal;
const float rangeVal;
float value;
Camera *camera;
CameraWidget *config = NULL;
CameraWidget *child = NULL;
CameraWidgetType type;
gp_ret = gp_camera_new (&camera);
if (gp_ret != 0) {error("gphoto2: ERROR: %s\n", gp_result_as_string(gp_ret)); gp_camera_unref(camera); return;}
// INIT camera (without context)
gp_ret = gp_camera_init (camera, NULL);
if (gp_ret != 0) {error("gphoto2: ERROR: %s\n", gp_result_as_string(gp_ret));}
if (gp_ret == -105) {post("gphoto2: Are you sure the camera is supported, connected and powered on?"); gp_camera_unref(camera); return;}
gp_ret = gp_camera_get_config (camera, &config, NULL); // get config from camera
if (gp_ret != 0) {error("gphoto2: ERROR: %s\n", gp_result_as_string(gp_ret)); gp_camera_unref(camera); return;}
gp_ret = gp_widget_get_child_by_name (config, s->s_name, &child); // get item from config
if (gp_ret != 0) {error("gphoto2: ERROR: %s\n", gp_result_as_string(gp_ret));}
/* post("types:");
post("GP_WIDGET_TOGGLE: %d", GP_WIDGET_TOGGLE);
post("GP_WIDGET_TEXT: %d", GP_WIDGET_TEXT);
post("GP_WIDGET_RANGE: %d", GP_WIDGET_RANGE);
post("GP_WIDGET_RADIO: %d", GP_WIDGET_RADIO);
post("GP_WIDGET_MENU: %d", GP_WIDGET_MENU);
post("GP_WIDGET_BUTTON: %d", GP_WIDGET_BUTTON);
post("GP_WIDGET_DATE: %d", GP_WIDGET_DATE);
post("GP_WIDGET_WINDOW: %d", GP_WIDGET_WINDOW);
post("GP_WIDGET_SECTION: %d", GP_WIDGET_SECTION);
*/
gp_ret = gp_widget_get_type (child, &type);
if (gp_ret != 0) {
error("gphoto2: ERROR: %s\n", gp_result_as_string(gp_ret));
error("gphoto2: Invalid config key.");
} else {
switch (type) {
case GP_WIDGET_TOGGLE:
gp_ret = gp_widget_get_value (child, &toggleVal); // get widget value
outlet_float(gphoto2->x_obj.ob_outlet, (int) toggleVal);
break;
case GP_WIDGET_TEXT:
gp_ret = gp_widget_get_value (child, &textVal);
outlet_symbol(gphoto2->x_obj.ob_outlet, gensym(textVal));
break;
case GP_WIDGET_RANGE:
gp_ret = gp_widget_get_value (child, &rangeVal);
if (gp_ret != 0) {error("gphoto2: ERROR: %s\n", gp_result_as_string(gp_ret));}
// TODO can't figure out how to output the value in this pointer.
//post("val %f",rangeVal);
outlet_float(gphoto2->x_obj.ob_outlet, rangeVal);
break;
}
}
// Free memory
gp_widget_unref (config);
gp_camera_unref (camera);
}
static void setConfig(gphoto2_struct *gphoto2, t_symbol *s, int argc, t_atom *argv) {
int gp_ret, intValue;
float floatValue;
t_symbol *key;
Camera *camera;
CameraWidget *config = NULL;
CameraWidget *child = NULL;
CameraWidgetType type;
key = atom_getsymbol( argv ); // config key
gp_ret = gp_camera_new (&camera);
if (gp_ret != 0) {error("gphoto2: ERROR: %s\n", gp_result_as_string(gp_ret));}
// INIT camera (without context)
gp_ret = gp_camera_init (camera, NULL);
if (gp_ret != 0) {error("gphoto2: ERROR: %s\n", gp_result_as_string(gp_ret));}
if (gp_ret == -105) {post("gphoto2: Are you sure the camera is supported, connected and powered on?"); gp_camera_unref(camera); return;}
gp_ret = gp_camera_get_config (camera, &config, NULL); // get config from camera
if (gp_ret != 0) {error("gphoto2: ERROR: %s\n", gp_result_as_string(gp_ret)); gp_camera_unref(camera); return;}
gp_ret = gp_widget_get_child_by_name (config, key->s_name, &child); // get item from config
if (gp_ret != 0) {error("gphoto2: ERROR: %s\n", gp_result_as_string(gp_ret)); gp_camera_unref(camera); return;}
gp_ret = gp_widget_get_type (child, &type);
if (gp_ret != 0) {
error("gphoto2: ERROR: %s\n", gp_result_as_string(gp_ret));
error("gphoto2: Invalid config key.");
} else {
switch (type) {
case GP_WIDGET_TOGGLE:
intValue = atom_getint( argv+1 );
gp_ret = gp_widget_set_value (child, &intValue); // set widget value
if (gp_ret != 0) {error("gphoto2: ERROR: %s\n", gp_result_as_string(gp_ret));}
gp_ret = gp_camera_set_config (camera, config, NULL); // set new config
if (gp_ret != 0) {error("gphoto2: ERROR: %s\n", gp_result_as_string(gp_ret));}
break;
case GP_WIDGET_RANGE:
floatValue = atom_getfloat( argv+1 );
gp_ret = gp_widget_set_value (child, &floatValue); // set widget value
if (gp_ret != 0) {error("gphoto2: ERROR: %s\n", gp_result_as_string(gp_ret));}
gp_ret = gp_camera_set_config (camera, config, NULL); // set new config
if (gp_ret != 0) {error("gphoto2: ERROR: %s\n", gp_result_as_string(gp_ret));}
break;
}
}
// Free memory
gp_widget_unref (config);
gp_camera_unref(camera);
}
static void captureImage(gphoto2_struct *gphoto2, t_symbol *s) {
int gp_ret, fd;
Camera *camera;
CameraFile *camerafile;
CameraFilePath camera_file_path;
gp_ret = gp_camera_new (&camera);
if (gp_ret != 0) {error("gphoto2: ERROR: %s\n", gp_result_as_string(gp_ret)); gp_camera_unref(camera); return;}
// INIT camera (without context)
gp_ret = gp_camera_init (camera, NULL);
if (gp_ret != 0) {error("gphoto2: ERROR: %s\n", gp_result_as_string(gp_ret));}
if (gp_ret == -105) {post("gphoto2: Are you sure the camera is supported, connected and powered on?"); gp_camera_unref(camera); return;}
gp_ret = gp_camera_capture(camera, GP_CAPTURE_IMAGE, &camera_file_path, NULL); // Capture w/out context?
if (gp_ret != 0) {error("gphoto2: ERROR: %s\n", gp_result_as_string(gp_ret)); gp_camera_unref(camera); return;}
// post("arg: %s",s->s_name);
//printf("Pathname on the camera: %s/%s\n", camera_file_path.folder, camera_file_path.name);
fd = open(s->s_name, O_CREAT | O_WRONLY, 0644); // create file descriptor
gp_ret = gp_file_new_from_fd(&camerafile, fd); // create gphoto file from descriptor
if (gp_ret != 0) {error("gphoto2: ERROR: %s\n", gp_result_as_string(gp_ret)); gp_camera_unref(camera); return;}
gp_ret = gp_camera_file_get(camera, camera_file_path.folder, camera_file_path.name,
GP_FILE_TYPE_NORMAL, camerafile, NULL); // get file from camera
if (gp_ret != 0) {error("gphoto2: ERROR: %s\n", gp_result_as_string(gp_ret)); gp_camera_unref(camera); return;}
gp_ret = gp_camera_file_delete(camera, camera_file_path.folder, camera_file_path.name, NULL);
if (gp_ret != 0) {error("gphoto2: ERROR: %s\n", gp_result_as_string(gp_ret)); gp_camera_unref(camera); return;}
// Free memory
gp_camera_unref(camera);
}
/*static void debug(gphoto2_struct *gphoto2, t_symbol *s, int argc, t_atom *argv) {
int ret;
pthread_t thread1;
post("I'm about to start the thread.");
// Create thread
ret = pthread_create( &thread1, NULL, mythread, (void *)args);
post("I'm about to wait for the thread");
// wait for thread
//pthread_join( thread1, NULL);
//post("I'm done waiting for the thread.");
}*/
static void *gphoto2_new(void) {
gphoto2_struct *gphoto2 = (gphoto2_struct *) pd_new(gphoto2_class);
outlet_new(&gphoto2->x_obj, NULL);
return (void *)gphoto2;
}
void gphoto2_setup(void) {
gphoto2_class = class_new(gensym("gphoto2"), (t_newmethod) gphoto2_new, 0, sizeof(gphoto2_struct), 0, CLASS_DEFAULT, 0);
class_addmethod(gphoto2_class, (t_method) wrapGetConfig, gensym("debug"), A_DEFSYMBOL, 0);
class_addmethod(gphoto2_class, (t_method) getConfig, gensym("getconfig"), A_DEFSYMBOL, 0);
class_addmethod(gphoto2_class, (t_method) captureImage, gensym("capture"), A_DEFSYMBOL, 0);
class_addmethod(gphoto2_class, (t_method) setConfig, gensym("setconfig"), A_GIMME, 0);
class_addmethod(gphoto2_class, (t_method) listConfig, gensym("listconfig"), 0);
}
_______________________________________________
Pd-dev mailing list
[email protected]
http://lists.puredata.info/listinfo/pd-dev