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 Pd-dev@iem.at http://lists.puredata.info/listinfo/pd-dev