bug fixes: init x11 threading, fix printer led, don't switch from video to photo bins until photo successfully taken, fix out-of-focus error handling
This commit is contained in:
parent
22d0223ae6
commit
0616c2ba21
5 changed files with 64 additions and 47 deletions
|
@ -45,6 +45,7 @@ Taking photo in %d seconds... = Aufnahme in %d Sekunden...
|
||||||
SAY CHEESE! = BITTE LÄCHELN :)
|
SAY CHEESE! = BITTE LÄCHELN :)
|
||||||
Focussing... = stelle scharf...
|
Focussing... = stelle scharf...
|
||||||
Taking photo... = fotografiere...
|
Taking photo... = fotografiere...
|
||||||
|
Taking photo failed! = Fotografieren fehlgeschlagen!
|
||||||
Processing photo... = verarbeite Foto...
|
Processing photo... = verarbeite Foto...
|
||||||
Print Photo? = Foto Drucken?
|
Print Photo? = Foto Drucken?
|
||||||
Upload photo? = Foto auf unsere Facebook-Seite hochladen?
|
Upload photo? = Foto auf unsere Facebook-Seite hochladen?
|
||||||
|
|
95
photobooth.c
95
photobooth.c
|
@ -27,6 +27,7 @@
|
||||||
#include <gst/video/gstvideosink.h>
|
#include <gst/video/gstvideosink.h>
|
||||||
#include <gst/app/app.h>
|
#include <gst/app/app.h>
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
#include <X11/Xlib.h>
|
||||||
// #ifdef HAVE_LIBCANBERRA
|
// #ifdef HAVE_LIBCANBERRA
|
||||||
#include <canberra-gtk.h>
|
#include <canberra-gtk.h>
|
||||||
// #endif
|
// #endif
|
||||||
|
@ -542,6 +543,23 @@ static GstPadProbeReturn _gst_video_probecb (GstPad * pad, GstPadProbeInfo * inf
|
||||||
return GST_PAD_PROBE_DROP;
|
return GST_PAD_PROBE_DROP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _play_event_sound (PhotoBoothPrivate *priv, sound_t sound)
|
||||||
|
{
|
||||||
|
gchar *soundfile = NULL;
|
||||||
|
switch (sound) {
|
||||||
|
case ACK_SOUND:
|
||||||
|
soundfile = priv->ack_sound;
|
||||||
|
break;
|
||||||
|
case ERROR_SOUND:
|
||||||
|
soundfile = priv->error_sound;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (soundfile)
|
||||||
|
ca_context_play (ca_gtk_context_get(), 0, CA_PROP_MEDIA_FILENAME, soundfile, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean photo_booth_cam_init (CameraInfo **cam_info)
|
static gboolean photo_booth_cam_init (CameraInfo **cam_info)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
|
@ -640,7 +658,10 @@ static void photo_booth_capture_thread_func (PhotoBooth *pb)
|
||||||
{
|
{
|
||||||
GST_INFO_OBJECT (pb, "photo_booth_cam_inited @ %p", pb->cam_info);
|
GST_INFO_OBJECT (pb, "photo_booth_cam_inited @ %p", pb->cam_info);
|
||||||
if (state == CAPTURE_FAILED)
|
if (state == CAPTURE_FAILED)
|
||||||
|
{
|
||||||
|
photo_booth_focus (pb->cam_info);
|
||||||
photo_booth_window_set_spinner (priv->win, FALSE);
|
photo_booth_window_set_spinner (priv->win, FALSE);
|
||||||
|
}
|
||||||
state = CAPTURE_VIDEO;
|
state = CAPTURE_VIDEO;
|
||||||
g_main_context_invoke (NULL, (GSourceFunc) photo_booth_preview, pb);
|
g_main_context_invoke (NULL, (GSourceFunc) photo_booth_preview, pb);
|
||||||
}
|
}
|
||||||
|
@ -714,14 +735,11 @@ static void photo_booth_capture_thread_func (PhotoBooth *pb)
|
||||||
if (ret && pb->cam_info->size)
|
if (ret && pb->cam_info->size)
|
||||||
{
|
{
|
||||||
g_main_context_invoke (NULL, (GSourceFunc) photo_booth_snapshot_taken, pb);
|
g_main_context_invoke (NULL, (GSourceFunc) photo_booth_snapshot_taken, pb);
|
||||||
if (priv->cam_reeinit_after_snapshot)
|
state = CAPTURE_PAUSED;
|
||||||
{
|
|
||||||
photo_booth_cam_close (&pb->cam_info);
|
|
||||||
photo_booth_cam_init (&pb->cam_info);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
gtk_label_set_text (priv->win->status, _("Taking photo failed!"));
|
gtk_label_set_text (priv->win->status, _("Taking photo failed!"));
|
||||||
|
_play_event_sound (priv, ERROR_SOUND);
|
||||||
GST_ERROR_OBJECT (pb, "Taking photo failed!");
|
GST_ERROR_OBJECT (pb, "Taking photo failed!");
|
||||||
photo_booth_cam_close (&pb->cam_info);
|
photo_booth_cam_close (&pb->cam_info);
|
||||||
photo_booth_change_state (pb, PB_STATE_NONE);
|
photo_booth_change_state (pb, PB_STATE_NONE);
|
||||||
|
@ -1196,23 +1214,6 @@ static gboolean photo_booth_screensaver_stop (PhotoBooth *pb)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _play_event_sound (PhotoBoothPrivate *priv, sound_t sound)
|
|
||||||
{
|
|
||||||
gchar *soundfile = NULL;
|
|
||||||
switch (sound) {
|
|
||||||
case ACK_SOUND:
|
|
||||||
soundfile = priv->ack_sound;
|
|
||||||
break;
|
|
||||||
case ERROR_SOUND:
|
|
||||||
soundfile = priv->error_sound;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (soundfile)
|
|
||||||
ca_context_play (ca_gtk_context_get(), 0, CA_PROP_MEDIA_FILENAME, soundfile, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void photo_booth_background_clicked (GtkWidget *widget, GdkEventButton *event, PhotoBoothWindow *win)
|
void photo_booth_background_clicked (GtkWidget *widget, GdkEventButton *event, PhotoBoothWindow *win)
|
||||||
{
|
{
|
||||||
PhotoBooth *pb = PHOTO_BOOTH_FROM_WINDOW (win);
|
PhotoBooth *pb = PHOTO_BOOTH_FROM_WINDOW (win);
|
||||||
|
@ -1389,7 +1390,6 @@ static gboolean photo_booth_snapshot_trigger (PhotoBooth *pb)
|
||||||
{
|
{
|
||||||
PhotoBoothPrivate *priv;
|
PhotoBoothPrivate *priv;
|
||||||
GstPad *pad;
|
GstPad *pad;
|
||||||
gboolean ret;
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (pb, "photo_booth_snapshot_trigger");
|
GST_DEBUG_OBJECT (pb, "photo_booth_snapshot_trigger");
|
||||||
GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (pb->pipeline), GST_DEBUG_GRAPH_SHOW_ALL, "photo_booth_snapshot_trigger");
|
GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (pb->pipeline), GST_DEBUG_GRAPH_SHOW_ALL, "photo_booth_snapshot_trigger");
|
||||||
|
@ -1400,23 +1400,7 @@ static gboolean photo_booth_snapshot_trigger (PhotoBooth *pb)
|
||||||
|
|
||||||
SEND_COMMAND (pb, CONTROL_PHOTO);
|
SEND_COMMAND (pb, CONTROL_PHOTO);
|
||||||
|
|
||||||
gst_element_set_state (pb->video_bin, GST_STATE_READY);
|
GST_DEBUG_OBJECT (pb, "preparing for snapshot...");
|
||||||
GST_DEBUG_OBJECT (pb, "preparing for snapshot! halt video_bin...");
|
|
||||||
pad = gst_element_get_static_pad (pb->video_bin, "src");
|
|
||||||
priv->video_block_id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_DATA_DOWNSTREAM, _gst_video_probecb, pb, NULL);
|
|
||||||
gst_object_unref (pad);
|
|
||||||
gst_element_unlink (pb->video_bin, pb->video_sink);
|
|
||||||
|
|
||||||
if (priv->photo_block_id)
|
|
||||||
{
|
|
||||||
GST_DEBUG_OBJECT (pb, "preparing for snapshot! unblock photo_bin...");
|
|
||||||
pad = gst_element_get_static_pad (pb->photo_bin, "src");
|
|
||||||
gst_pad_remove_probe (pad, priv->photo_block_id);
|
|
||||||
gst_object_unref (pad);
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = gst_element_link (pb->photo_bin, pb->video_sink);
|
|
||||||
gst_element_set_state (pb->photo_bin, GST_STATE_PLAYING);
|
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -1509,6 +1493,24 @@ static gboolean photo_booth_snapshot_taken (PhotoBooth *pb)
|
||||||
GstBuffer *buffer;
|
GstBuffer *buffer;
|
||||||
GstFlowReturn flowret;
|
GstFlowReturn flowret;
|
||||||
GstPad *pad;
|
GstPad *pad;
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
gst_element_set_state (pb->video_bin, GST_STATE_READY);
|
||||||
|
pad = gst_element_get_static_pad (pb->video_bin, "src");
|
||||||
|
priv->video_block_id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_DATA_DOWNSTREAM, _gst_video_probecb, pb, NULL);
|
||||||
|
gst_object_unref (pad);
|
||||||
|
gst_element_unlink (pb->video_bin, pb->video_sink);
|
||||||
|
|
||||||
|
if (priv->photo_block_id)
|
||||||
|
{
|
||||||
|
GST_DEBUG_OBJECT (pb, "preparing for snapshot! unblock photo_bin...");
|
||||||
|
pad = gst_element_get_static_pad (pb->photo_bin, "src");
|
||||||
|
gst_pad_remove_probe (pad, priv->photo_block_id);
|
||||||
|
gst_object_unref (pad);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = gst_element_link (pb->photo_bin, pb->video_sink);
|
||||||
|
gst_element_set_state (pb->photo_bin, GST_STATE_PLAYING);
|
||||||
|
|
||||||
priv->photos_taken++;
|
priv->photos_taken++;
|
||||||
GST_DEBUG_OBJECT (pb, "photo_booth_snapshot_taken size=%lu photos_taken=%i", pb->cam_info->size, priv->photos_taken);
|
GST_DEBUG_OBJECT (pb, "photo_booth_snapshot_taken size=%lu photos_taken=%i", pb->cam_info->size, priv->photos_taken);
|
||||||
|
@ -1522,8 +1524,6 @@ static gboolean photo_booth_snapshot_taken (PhotoBooth *pb)
|
||||||
GST_ERROR_OBJECT (appsrc, "couldn't push %" GST_PTR_FORMAT " to appsrc", buffer);
|
GST_ERROR_OBJECT (appsrc, "couldn't push %" GST_PTR_FORMAT " to appsrc", buffer);
|
||||||
gst_object_unref (appsrc);
|
gst_object_unref (appsrc);
|
||||||
|
|
||||||
SEND_COMMAND (pb, CONTROL_PAUSE);
|
|
||||||
|
|
||||||
gst_element_set_state (pb->photo_bin, GST_STATE_PLAYING);
|
gst_element_set_state (pb->photo_bin, GST_STATE_PLAYING);
|
||||||
pad = gst_element_get_static_pad (pb->photo_bin, "src");
|
pad = gst_element_get_static_pad (pb->photo_bin, "src");
|
||||||
priv->photo_block_id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER, photo_booth_catch_photo_buffer, pb, NULL);
|
priv->photo_block_id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER, photo_booth_catch_photo_buffer, pb, NULL);
|
||||||
|
@ -1543,6 +1543,11 @@ static GstPadProbeReturn photo_booth_catch_photo_buffer (GstPad * pad, GstPadPro
|
||||||
switch (priv->state) {
|
switch (priv->state) {
|
||||||
case PB_STATE_TAKING_PHOTO:
|
case PB_STATE_TAKING_PHOTO:
|
||||||
{
|
{
|
||||||
|
if (priv->cam_reeinit_after_snapshot)
|
||||||
|
{
|
||||||
|
photo_booth_cam_close (&pb->cam_info);
|
||||||
|
photo_booth_cam_init (&pb->cam_info);
|
||||||
|
}
|
||||||
photo_booth_change_state (pb, PB_STATE_PROCESS_PHOTO);
|
photo_booth_change_state (pb, PB_STATE_PROCESS_PHOTO);
|
||||||
GST_DEBUG_OBJECT (pb, "first buffer caught -> display in sink, invoke processing");
|
GST_DEBUG_OBJECT (pb, "first buffer caught -> display in sink, invoke processing");
|
||||||
gtk_widget_show (GTK_WIDGET (priv->win->button_print));
|
gtk_widget_show (GTK_WIDGET (priv->win->button_print));
|
||||||
|
@ -1854,12 +1859,13 @@ static void photo_booth_print (PhotoBooth *pb)
|
||||||
else if (res == GTK_PRINT_OPERATION_RESULT_CANCEL)
|
else if (res == GTK_PRINT_OPERATION_RESULT_CANCEL)
|
||||||
{
|
{
|
||||||
gtk_label_set_text (priv->win->status, _("Printing cancelled"));
|
gtk_label_set_text (priv->win->status, _("Printing cancelled"));
|
||||||
|
g_object_unref (priv->printer_settings);
|
||||||
|
priv->printer_settings = NULL;
|
||||||
GST_INFO_OBJECT (pb, "print cancelled");
|
GST_INFO_OBJECT (pb, "print cancelled");
|
||||||
}
|
}
|
||||||
else if (res == GTK_PRINT_OPERATION_RESULT_APPLY)
|
else if (res == GTK_PRINT_OPERATION_RESULT_APPLY)
|
||||||
{
|
{
|
||||||
if (priv->printer_settings != NULL)
|
g_object_unref (priv->printer_settings);
|
||||||
g_object_unref (priv->printer_settings);
|
|
||||||
priv->printer_settings = g_object_ref (gtk_print_operation_get_print_settings (printop));
|
priv->printer_settings = g_object_ref (gtk_print_operation_get_print_settings (printop));
|
||||||
}
|
}
|
||||||
g_object_unref (printop);
|
g_object_unref (printop);
|
||||||
|
@ -2052,6 +2058,7 @@ int main (int argc, char *argv[])
|
||||||
PhotoBooth *pb;
|
PhotoBooth *pb;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
XInitThreads();
|
||||||
gst_init (0, NULL);
|
gst_init (0, NULL);
|
||||||
|
|
||||||
pb = photo_booth_new ();
|
pb = photo_booth_new ();
|
||||||
|
|
|
@ -114,8 +114,10 @@ void photo_booth_led_black (PhotoBoothLed *led)
|
||||||
{
|
{
|
||||||
if (led->fd > 0)
|
if (led->fd > 0)
|
||||||
{
|
{
|
||||||
char cmd = LED_BLACK;
|
|
||||||
GST_DEBUG_OBJECT(led, "turning off leds");
|
GST_DEBUG_OBJECT(led, "turning off leds");
|
||||||
|
char cmd = LED_RING_BLACK;
|
||||||
|
write (led->fd, &cmd, 1);
|
||||||
|
cmd = LED_STRIP_BLACK;
|
||||||
write (led->fd, &cmd, 1);
|
write (led->fd, &cmd, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -144,10 +146,16 @@ void photo_booth_led_printer (PhotoBoothLed *led, gint copies)
|
||||||
{
|
{
|
||||||
if (led->fd > 0)
|
if (led->fd > 0)
|
||||||
{
|
{
|
||||||
char *cmd = g_strdup_printf ("%c%d", LED_PRINT, copies);
|
/* char *cmd = g_strdup_printf ("%c%d", LED_PRINT, copies);
|
||||||
GST_DEBUG_OBJECT(led, "turning on printer leds '%s'", cmd);
|
GST_DEBUG_OBJECT(led, "turning on printer leds '%s'", cmd);
|
||||||
write (led->fd, &cmd, strlen(cmd));
|
write (led->fd, &cmd, strlen(cmd));
|
||||||
g_free (cmd);
|
g_free (cmd);
|
||||||
|
* arduino doesn't process this correctly */
|
||||||
|
char cmd = LED_PRINT;
|
||||||
|
write (led->fd, &cmd, 1);
|
||||||
|
cmd = copies+0x30; //!HACK won't work for >9 copies
|
||||||
|
write (led->fd, &cmd, 1);
|
||||||
|
GST_DEBUG_OBJECT(led, "printing %c%i", cmd, copies);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,8 @@
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
|
||||||
#define LED_BLACK 'b'
|
#define LED_RING_BLACK 'b'
|
||||||
|
#define LED_STRIP_BLACK 'B'
|
||||||
#define LED_COUNTDOWN 'c'
|
#define LED_COUNTDOWN 'c'
|
||||||
#define LED_FLASH 'f'
|
#define LED_FLASH 'f'
|
||||||
#define LED_PRINT 'p'
|
#define LED_PRINT 'p'
|
||||||
|
|
Binary file not shown.
Loading…
Add table
Reference in a new issue