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:
Andreas Frisch 2016-06-05 15:42:01 +02:00
parent 22d0223ae6
commit 0616c2ba21
5 changed files with 64 additions and 47 deletions

View file

@ -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?

View file

@ -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 ();

View file

@ -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);
} }
} }

View file

@ -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.