diff --git a/default.ini b/default.ini index 7032134..a617c16 100644 --- a/default.ini +++ b/default.ini @@ -45,6 +45,7 @@ Taking photo in %d seconds... = Aufnahme in %d Sekunden... SAY CHEESE! = BITTE LÄCHELN :) Focussing... = stelle scharf... Taking photo... = fotografiere... +Taking photo failed! = Fotografieren fehlgeschlagen! Processing photo... = verarbeite Foto... Print Photo? = Foto Drucken? Upload photo? = Foto auf unsere Facebook-Seite hochladen? diff --git a/photobooth.c b/photobooth.c index e2bbeb0..1cd4025 100644 --- a/photobooth.c +++ b/photobooth.c @@ -27,6 +27,7 @@ #include #include #include +#include // #ifdef HAVE_LIBCANBERRA #include // #endif @@ -542,6 +543,23 @@ static GstPadProbeReturn _gst_video_probecb (GstPad * pad, GstPadProbeInfo * inf 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) { 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); if (state == CAPTURE_FAILED) + { + photo_booth_focus (pb->cam_info); photo_booth_window_set_spinner (priv->win, FALSE); + } state = CAPTURE_VIDEO; 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) { g_main_context_invoke (NULL, (GSourceFunc) photo_booth_snapshot_taken, pb); - if (priv->cam_reeinit_after_snapshot) - { - photo_booth_cam_close (&pb->cam_info); - photo_booth_cam_init (&pb->cam_info); - } + state = CAPTURE_PAUSED; } else { gtk_label_set_text (priv->win->status, _("Taking photo failed!")); + _play_event_sound (priv, ERROR_SOUND); GST_ERROR_OBJECT (pb, "Taking photo failed!"); photo_booth_cam_close (&pb->cam_info); photo_booth_change_state (pb, PB_STATE_NONE); @@ -1196,23 +1214,6 @@ static gboolean photo_booth_screensaver_stop (PhotoBooth *pb) 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) { PhotoBooth *pb = PHOTO_BOOTH_FROM_WINDOW (win); @@ -1389,7 +1390,6 @@ static gboolean photo_booth_snapshot_trigger (PhotoBooth *pb) { PhotoBoothPrivate *priv; GstPad *pad; - gboolean ret; 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"); @@ -1400,23 +1400,7 @@ static gboolean photo_booth_snapshot_trigger (PhotoBooth *pb) SEND_COMMAND (pb, CONTROL_PHOTO); - gst_element_set_state (pb->video_bin, GST_STATE_READY); - 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); + GST_DEBUG_OBJECT (pb, "preparing for snapshot..."); return FALSE; } @@ -1509,6 +1493,24 @@ static gboolean photo_booth_snapshot_taken (PhotoBooth *pb) GstBuffer *buffer; GstFlowReturn flowret; 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++; 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_object_unref (appsrc); - SEND_COMMAND (pb, CONTROL_PAUSE); - gst_element_set_state (pb->photo_bin, GST_STATE_PLAYING); 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); @@ -1543,6 +1543,11 @@ static GstPadProbeReturn photo_booth_catch_photo_buffer (GstPad * pad, GstPadPro switch (priv->state) { 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); GST_DEBUG_OBJECT (pb, "first buffer caught -> display in sink, invoke processing"); 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) { 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"); } 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)); } g_object_unref (printop); @@ -2052,6 +2058,7 @@ int main (int argc, char *argv[]) PhotoBooth *pb; int ret; + XInitThreads(); gst_init (0, NULL); pb = photo_booth_new (); diff --git a/photoboothled.c b/photoboothled.c index c1c220b..3872dc7 100644 --- a/photoboothled.c +++ b/photoboothled.c @@ -114,8 +114,10 @@ void photo_booth_led_black (PhotoBoothLed *led) { if (led->fd > 0) { - char cmd = LED_BLACK; 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); } } @@ -144,10 +146,16 @@ void photo_booth_led_printer (PhotoBoothLed *led, gint copies) { 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); write (led->fd, &cmd, strlen(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); } } diff --git a/photoboothled.h b/photoboothled.h index 3feabb9..40c2922 100644 --- a/photoboothled.h +++ b/photoboothled.h @@ -19,7 +19,8 @@ #include #include -#define LED_BLACK 'b' +#define LED_RING_BLACK 'b' +#define LED_STRIP_BLACK 'B' #define LED_COUNTDOWN 'c' #define LED_FLASH 'f' #define LED_PRINT 'p' diff --git a/sketchup/photobooth.skp b/sketchup/photobooth.skp index 764dc11..d7f2f98 100644 Binary files a/sketchup/photobooth.skp and b/sketchup/photobooth.skp differ