diff --git a/Makefile b/Makefile index 5a5fc60..3d728c3 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,10 @@ CC ?= gcc PKGCONFIG = $(shell which pkg-config) -CFLAGS = $(shell $(PKGCONFIG) --cflags gtk+-3.0 gstreamer-1.0 gstreamer-video-1.0 gstreamer-app-1.0 libgphoto2 libcurl) -Wl,--export-dynamic -rdynamic -g -LIBS = $(shell $(PKGCONFIG) --libs gtk+-3.0 gstreamer-1.0 gstreamer-video-1.0 gstreamer-app-1.0 libgphoto2 gmodule-export-2.0 libcurl) +CFLAGS = $(shell $(PKGCONFIG) --cflags gtk+-3.0 gstreamer-1.0 gstreamer-video-1.0 gstreamer-app-1.0 libgphoto2 libcurl x11) -Wl,--export-dynamic -rdynamic -g +LIBS = $(shell $(PKGCONFIG) --libs gtk+-3.0 gstreamer-1.0 gstreamer-video-1.0 gstreamer-app-1.0 libgphoto2 gmodule-export-2.0 libcurl x11) GLIB_COMPILE_RESOURCES = $(shell $(PKGCONFIG) --variable=glib_compile_resources gio-2.0) -SRC = photobooth.c photoboothwin.c focus.c +SRC = photobooth.c photoboothwin.c focus.c photoboothled.c BUILT_SRC = resources.c OBJS = $(BUILT_SRC:.c=.o) $(SRC:.c=.o) diff --git a/default.ini b/default.ini index ae2fa8b..038ffa6 100644 --- a/default.ini +++ b/default.ini @@ -1,5 +1,5 @@ [general] -countdown = 5 +countdown = 6 countdown_audio_file = beep.m4a template = photobooth.ui stylesheet = photobooth.css @@ -7,7 +7,7 @@ overlay_image = overlay_print_rainbows.png save_path_template = /home/fraxinas/Desktop/photobooth_%04d.jpg #screensaver_timeout -1 = disable -screensaver_timeout = 7 +screensaver_timeout = 30 #screensaver_file can be image, video, audio (or freezes preview if omitted) screensaver_file = /home/fraxinas/Desktop/Troye Sivan - Youth (1080p AAC).mkv diff --git a/photobooth.c b/photobooth.c index 631a305..0f92103 100644 --- a/photobooth.c +++ b/photobooth.c @@ -29,6 +29,7 @@ #include #include "photobooth.h" #include "photoboothwin.h" +#include "photoboothled.h" #define G_SETTINGS_ENABLE_BACKEND #include @@ -82,6 +83,8 @@ struct _PhotoBoothPrivate gint facebook_put_timeout; GThread *upload_thread; GMutex upload_mutex; + + PhotoBoothLed *led; }; #define MOVIEPIPE "moviepipe.mjpg" @@ -243,6 +246,8 @@ static void photo_booth_init (PhotoBooth *pb) priv->facebook_put_uri = NULL; priv->upload_thread = NULL; + priv->led = photo_booth_led_new (); + G_stylesheet_filename = NULL; G_template_filename = NULL; @@ -304,6 +309,7 @@ static void photo_booth_finalize (GObject *object) } if (priv->upload_thread) g_thread_join (priv->upload_thread); + g_object_unref (priv->led); } static void photo_booth_dispose (GObject *object) @@ -679,8 +685,10 @@ static void photo_booth_capture_thread_func (PhotoBooth *pb) if (pb->cam_info) { gtk_label_set_text (priv->win->status, _("Taking photo...")); + photo_booth_led_flash (priv->led); ret = photo_booth_take_photo (pb->cam_info); - if (ret) + photo_booth_led_black (priv->led); + if (ret && pb->cam_info->size) { g_main_context_invoke (NULL, (GSourceFunc) photo_booth_snapshot_taken, pb); if (priv->cam_reeinit_after_snapshot) @@ -1310,6 +1318,7 @@ static void photo_booth_snapshot_start (PhotoBooth *pb) g_object_set (priv->audio_playbin, "uri", priv->countdown_audio_uri, NULL); gst_element_set_state (priv->audio_pipeline, GST_STATE_PLAYING); } + photo_booth_led_countdown (priv->led, priv->countdown); } static gboolean photo_booth_snapshot_prepare (PhotoBooth *pb) diff --git a/photoboothled.c b/photoboothled.c new file mode 100644 index 0000000..24ca052 --- /dev/null +++ b/photoboothled.c @@ -0,0 +1,145 @@ +/* +* led.c +* Copyright 2016 Andreas Frisch +* +* This program is licensed under the Creative Commons +* Attribution-NonCommercial-ShareAlike 3.0 Unported +* License. To view a copy of this license, visit +* http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to +* Creative Commons,559 Nathan Abbott Way,Stanford,California 94305,USA. +* +* This program is NOT free software. It is open source, you are allowed +* to modify it (if you keep the license), but it may not be commercially +* distributed other than under the conditions noted above. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include "photobooth.h" +#include "photoboothled.h" + +G_DEFINE_TYPE (PhotoBoothLed, photo_booth_led, G_TYPE_OBJECT); + +GST_DEBUG_CATEGORY_STATIC (photo_booth_led_debug); +#define GST_CAT_DEFAULT photo_booth_led_debug + +static void photo_booth_led_finalize (GObject *object); + +static void photo_booth_led_class_init (PhotoBoothLedClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + GST_DEBUG_CATEGORY_INIT (photo_booth_led_debug, "photoboothled", GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_BLUE, "PhotoBoothLed"); + + gobject_class->finalize = photo_booth_led_finalize; +} + +static void photo_booth_led_init (PhotoBoothLed *led) +{ + led->fd = -1; + for (int i=0; i < 10; i++) + { + gchar *devicename = g_strdup_printf ("%s%d", LED_DEVICENAME, i); + GST_INFO_OBJECT (led, "trying to open device %s... ", devicename); + gboolean exists = g_file_test ((const char*) devicename, G_FILE_TEST_EXISTS); + if (exists) + { + led->fd = open(devicename, O_RDWR | O_NOCTTY); + if (led->fd == -1) + GST_WARNING_OBJECT (led, "couldn't open %s: %s (%i)", devicename, strerror(errno), errno); + else + { + GST_INFO_OBJECT (led, "successfully opened %s", devicename); + g_free (devicename); + break; + } + } + g_free (devicename); + } + + if (led->fd > 0) + { + struct termios tty; + if (tcgetattr (led->fd, &tty) == 0) { + cfsetospeed(&tty, B115200); + cfsetispeed(&tty, B115200); + tty.c_cflag &= ~PARENB; + tty.c_cflag &= ~CSTOPB; + tty.c_cflag &= ~CSIZE; + tty.c_cflag |= CS8; + tty.c_cflag &= ~CRTSCTS; + tty.c_cflag |= CLOCAL | CREAD; + tty.c_iflag |= IGNPAR | IGNCR; + tty.c_iflag &= ~(IXON | IXOFF | IXANY); + tty.c_lflag |= ICANON; + tty.c_oflag &= ~OPOST; + tcsetattr(led->fd, TCSANOW, &tty); + char tempbuf[32]; + int n = read (led->fd, tempbuf, sizeof(tempbuf)-1); + GST_WARNING_OBJECT(led, "read %i bytes: '%s'", n, tempbuf); + if (g_ascii_strncasecmp ("Photobooth-LED ready", tempbuf, 20) == 0) + { + GST_WARNING_OBJECT (led, "initialized!"); + photo_booth_led_black (led); + } + else + { + GST_WARNING_OBJECT (led, "wrong device!"); + close (led->fd); + led->fd = -1; + } + } else { + GST_WARNING_OBJECT(led, "tcgetatt() error %s (%i)", strerror(errno), errno); + } + } +} + +static void photo_booth_led_finalize (GObject *object) +{ + PhotoBoothLed *led = PHOTO_BOOTH_LED (object); + if (led->fd > 0) + { + photo_booth_led_black (led); + close (led->fd); + } +} + +void photo_booth_led_black (PhotoBoothLed *led) +{ + if (led->fd > 0) + { + char cmd = LED_BLACK; + GST_INFO_OBJECT(led, "turning off leds"); + write (led->fd, &cmd, 1); + } +} + +void photo_booth_led_countdown (PhotoBoothLed *led, gint seconds) +{ + if (led->fd > 0) + { + char cmd = LED_COUNTDOWN; + GST_INFO_OBJECT(led, "countdown %i seconds", seconds); + write (led->fd, &cmd, 1); + } +} + +void photo_booth_led_flash (PhotoBoothLed *led) +{ + if (led->fd > 0) + { + char cmd = LED_FLASH; + GST_INFO_OBJECT(led, "flashing leds"); + write (led->fd, &cmd, 1); + } +} + +PhotoBoothLed * photo_booth_led_new () +{ + return g_object_new (PHOTO_BOOTH_LED_TYPE, NULL); +} diff --git a/photoboothled.h b/photoboothled.h new file mode 100644 index 0000000..93df161 --- /dev/null +++ b/photoboothled.h @@ -0,0 +1,56 @@ +/* + * GStreamer led.h + * Copyright 2016 Andreas Frisch + * + * This program is licensed under the Creative Commons + * Attribution-NonCommercial-ShareAlike 3.0 Unported + * License. To view a copy of this license, visit + * http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to + * Creative Commons,559 Nathan Abbott Way,Stanford,California 94305,USA. + * + * This program is NOT free software. It is open source, you are allowed + * to modify it (if you keep the license), but it may not be commercially + * distributed other than under the conditions noted above. + */ + +#ifndef __PHOTO_BOOTH_LED_H__ +#define __PHOTO_BOOTH_LED_H__ + +#include + +#define LED_BLACK 'b' +#define LED_COUNTDOWN 'c' +#define LED_FLASH 'f' +#define LED_DEVICENAME "/dev/ttyACM" + +G_BEGIN_DECLS + +#define PHOTO_BOOTH_LED_TYPE (photo_booth_led_get_type ()) +#define PHOTO_BOOTH_LED(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),PHOTO_BOOTH_LED_TYPE,PhotoBoothLed)) +#define PHOTO_BOOTH_LED_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PHOTO_BOOTH_LED_TYPE,PhotoBoothLedClass)) +#define IS_PHOTO_BOOTH_LED(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),PHOTO_BOOTH_LED_TYPE)) +#define IS_PHOTO_BOOTH_LED_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PHOTO_BOOTH_LED_TYPE)) + +typedef struct _PhotoBoothLed PhotoBoothLed; +typedef struct _PhotoBoothLedClass PhotoBoothLedClass; + +struct _PhotoBoothLed +{ + GObject parent; + int fd; +}; + +struct _PhotoBoothLedClass +{ + GtkApplicationClass parent_class; +}; + +GType photo_booth_led_get_type (void); +PhotoBoothLed *photo_booth_led_new (void); +void photo_booth_led_black (PhotoBoothLed *led); +void photo_booth_led_countdown (PhotoBoothLed *led, gint seconds); +void photo_booth_led_flash (PhotoBoothLed *led); + +G_END_DECLS + +#endif /* __PHOTO_BOOTH_LED_H__ */ diff --git a/sketchup/photobooth.skp b/sketchup/photobooth.skp index 7522c1c..764dc11 100644 Binary files a/sketchup/photobooth.skp and b/sketchup/photobooth.skp differ