Hey all,
I'm working on a gphoto2 external.
I've gotten quite far, except now when I set a config option in the
camera PD gets a SIGHUP and the watchdog starts. I think this is due to
libgphoto doing some stuff in the background and messing with PD's
scheduler.
Once this call is made:
gp_ret = gp_camera_set_config (gphoto2->camera, config, NULL);
then no further lines are read, so I'm guessing PD bails before the
function returns.
This is simply a control object, it need not provide any sync with
audio/gem, just needs to send the messages (via libusb) in a reasonable
amount of time.
Anyone have a very simply pthreads example in a PD external?
I've attached the current state of my code for reference, in case
someone has a better idea.
Thanks,
B. Bogart
/* 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 <gphoto2/gphoto2-camera.h>
t_class *gphoto2_class;
typedef struct gphoto2_struct {
t_object x_obj;
t_outlet *outlet;
Camera *camera;
int connected;
} gphoto2_struct;
static void getConfig(gphoto2_struct *gphoto2, t_symbol *s) {
if (gphoto2->connected) {
int gp_ret;
const char *textVal;
const int *toggleVal;
CameraWidget *config = NULL;
CameraWidget *child = NULL;
CameraWidgetType type;
gp_ret = gp_camera_get_config (gphoto2->camera, &config, NULL); // get config from camera
if (gp_ret != 0) {error("gphoto2: ERROR: %s\n", gp_result_as_string(gp_ret));}
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;
}
}
/* Free memory
gp_widget_unref (config);
gp_widget_unref (child);*/
} else {
error("Not connected to camera.");
}
}
static void setConfig(gphoto2_struct *gphoto2, t_symbol *s, int argc, t_atom *argv) {
if (gphoto2->connected) {
int gp_ret, value;
t_symbol *key;
CameraWidget *config = NULL;
CameraWidget *child = NULL;
CameraWidgetType type;
key = atom_getsymbol( argv ); // config key
gp_ret = gp_camera_get_config (gphoto2->camera, &config, NULL); // get config from camera
if (gp_ret != 0) {error("gphoto2: ERROR: %s\n", gp_result_as_string(gp_ret));}
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_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:
value = atom_getint( argv+1 );
gp_ret = gp_widget_set_value (child, &value); // set widget value
if (gp_ret != 0) {error("gphoto2: ERROR: %s\n", gp_result_as_string(gp_ret));}
gp_ret = gp_camera_set_config (gphoto2->camera, config, NULL); // set new config
if (gp_ret != 0) {error("gphoto2: ERROR: %s\n", gp_result_as_string(gp_ret));}
post("value set");
//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;
}
}
/* Free memory
gp_widget_unref (config);
gp_widget_unref (child);*/
} else {
error("Not connected to camera.");
}
}
static void openCam(gphoto2_struct *gphoto2) {
int gp_ret;
gphoto2->connected = 0;
// new camera instance
gp_ret = gp_camera_new (&(gphoto2->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 (gphoto2->camera, NULL);
if (gp_ret != 0) {error("gphoto2: ERROR: %s\n", gp_result_as_string(gp_ret));}
if (gp_ret == 0) {
post("gphoto2: Connected to camera.");
gphoto2->connected = 1;
}
if (gp_ret == -105) {post("gphoto2: Are you sure the camera is supported, connected and powered on?");}
}
static void closeCam(gphoto2_struct *gphoto2) {
int gp_ret;
if (gphoto2->connected) {
gp_ret = gp_camera_unref (gphoto2->camera); // or gp_camera_exit() ?
if (gp_ret == 0) {
post("gphoto2: Disconnected from camera.");
gphoto2->connected = 0;
} else {
error("gphoto2: ERROR %s\n", gp_result_as_string(gp_ret));
}
} else {
error("gphoto2: Not connected to camera.");
}
}
static void *gphoto2_new(void) {
gphoto2_struct *gphoto2 = (gphoto2_struct *) pd_new(gphoto2_class);
outlet_new(&gphoto2->x_obj, NULL);
return (void *)gphoto2;
}
static void gphoto2_release(gphoto2_struct *gphoto2) {
if (gphoto2->connected) {
gp_camera_unref(gphoto2->camera);
} else {
error("gphoto2: Not connected to camera.");
}
}
void gphoto2_setup(void) {
gphoto2_class = class_new(gensym("gphoto2"), (t_newmethod) gphoto2_new, (t_method) gphoto2_release, sizeof(gphoto2_struct), 0, CLASS_DEFAULT, 0);
class_addmethod(gphoto2_class, (t_method) openCam, gensym("open"), 0);
class_addmethod(gphoto2_class, (t_method) closeCam, gensym("close"), 0);
class_addmethod(gphoto2_class, (t_method) getConfig, gensym("getconfig"), A_DEFSYMBOL, 0);
class_addmethod(gphoto2_class, (t_method) setConfig, gensym("setconfig"), A_GIMME, 0);
}
_______________________________________________
Pd-dev mailing list
[email protected]
http://lists.puredata.info/listinfo/pd-dev