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

Reply via email to