make things configurable

This commit is contained in:
Andreas Frisch 2016-05-09 15:50:05 +02:00
parent cafda04bae
commit 971acbbb83
3 changed files with 158 additions and 121 deletions

View file

@ -1,4 +1,22 @@
[Status Strings] [general]
countdown = 5
countdown_audio_file = beep.m4a
overlay_image = overlay_print_rainbows.png
[printer]
backend = mitsu9550
dpi = 346
width = 2076
height = 1384
icc_profile = CP955_F.icc
[camera]
preview_width = 640
preview_height = 424
cam_reeinit_before_snapshot = 1
cam_reeinit_after_snapshot = 1
[strings]
No camera connected! = Keine Kamera verbunden! No camera connected! = Keine Kamera verbunden!
Taking photo... = fotografiere... Taking photo... = fotografiere...
Touch screen to take a photo! = Bildschirm berühren zum Fotografieren! Touch screen to take a photo! = Bildschirm berühren zum Fotografieren!
@ -6,12 +24,10 @@ Processing photo... = verarbeite Foto...
Print Photo? Touch background to cancel! = Foto Drucken? Zum Abbrechen Hintergrund berühren Print Photo? Touch background to cancel! = Foto Drucken? Zum Abbrechen Hintergrund berühren
Taking photo in %d seconds... = Aufnahme in %d Sekunden... Taking photo in %d seconds... = Aufnahme in %d Sekunden...
SAY CHEESE! = BITTE LÄCHELN :) SAY CHEESE! = BITTE LÄCHELN :)
[Printer String]
Printer %s online. %i prints (%s) remaining = Drucker %s bereit. %i Abzüge (%s) übrig Printer %s online. %i prints (%s) remaining = Drucker %s bereit. %i Abzüge (%s) übrig
Can't parse printer backend output = Fehler beim Verarbeiten der Ausgabe vom Drucker-Backend Can't parse printer backend output = Fehler beim Verarbeiten der Ausgabe vom Drucker-Backend
Printer %s off-line = Drucker %s ist nicht verfügbar Printer %s off-line = Drucker %s ist nicht verfügbar
Can't spawn %s = Fehler beim Starten von %s Can't spawn %s = Fehler beim Starten von %s
Can't print, no printer connected! = Kann nicht Drucken weil kein Drucker verbunden ist! Can't print, no printer connected! = Kann nicht Drucken weil kein Drucker verbunden ist!
Can't print, out of paper! = Kann nicht Drucken weil kein Papier übrig ist! Can't print, out of paper! = Kann nicht Drucken weil kein Papier übrig ist!
No printer configured! = Kein Drucker konfiguriert!

View file

@ -29,6 +29,9 @@
#include "photobooth.h" #include "photobooth.h"
#include "photoboothwin.h" #include "photoboothwin.h"
#define G_SETTINGS_ENABLE_BACKEND
#include <gio/gsettingsbackend.h>
#define photo_booth_parent_class parent_class #define photo_booth_parent_class parent_class
typedef struct _PhotoBoothPrivate PhotoBoothPrivate; typedef struct _PhotoBoothPrivate PhotoBoothPrivate;
@ -44,36 +47,35 @@ struct _PhotoBoothPrivate
gulong photo_block_id; gulong photo_block_id;
guint32 countdown; guint32 countdown;
gchar *overlay_image;
gchar *printer_backend; gchar *printer_backend;
gint print_dpi, print_width, print_height;
gchar *print_icc_profile;
gint prints_remaining; gint prints_remaining;
GstBuffer *print_buffer; GstBuffer *print_buffer;
GtkPrintSettings *printer_settings; GtkPrintSettings *printer_settings;
GMutex processing_mutex; GMutex processing_mutex;
gint preview_fps, preview_width, preview_height;
gboolean cam_reeinit_before_snapshot, cam_reeinit_after_snapshot;
gchar *cam_icc_profile;
GstElement *audio_pipeline; GstElement *audio_pipeline;
GstElement *audio_playbin; GstElement *audio_playbin;
gchar *countdown_audio_uri;
}; };
#define DEFAULT_AUDIOFILE_COUNTDOWN "/net/home/fraxinas/microcontroller/photobooth/beep.m4a" #define MOVIEPIPE "moviepipe.mjpg"
#define DEFAULT_CONFIG "default.ini"
#define PREVIEW_FPS 24
#define DEFAULT_COUNTDOWN 5 #define DEFAULT_COUNTDOWN 5
#define DEFAULT_PRINTER_BACKEND "mitsu9550"
#define PRINT_DPI 346 #define PRINT_DPI 346
#define PRINT_WIDTH 2076 #define PRINT_WIDTH 2076
#define PRINT_HEIGHT 1384 #define PRINT_HEIGHT 1384
#define PREVIEW_WIDTH 640 #define PREVIEW_WIDTH 640
#define PREVIEW_HEIGHT 424 #define PREVIEW_HEIGHT 424
#define MOVIEPIPE "moviepipe.mjpg" #define PT_PER_IN 72
#define CAM_REINIT_BEFORE_SNAPSHOT 1
#define CAM_REINIT_AFTER_SNAPSHOT 1
enum
{
ARG_0,
ARG_COUNTDOWN,
ARG_PRINTER_BACKEND,
ARG_PRINTS_REMAINING,
};
G_DEFINE_TYPE_WITH_PRIVATE (PhotoBooth, photo_booth, GTK_TYPE_APPLICATION); G_DEFINE_TYPE_WITH_PRIVATE (PhotoBooth, photo_booth, GTK_TYPE_APPLICATION);
@ -83,8 +85,6 @@ GST_DEBUG_CATEGORY_STATIC (photo_booth_debug);
/* GObject / GApplication */ /* GObject / GApplication */
static void photo_booth_activate (GApplication *app); static void photo_booth_activate (GApplication *app);
static void photo_booth_open (GApplication *app, GFile **files, gint n_files, const gchar *hint); static void photo_booth_open (GApplication *app, GFile **files, gint n_files, const gchar *hint);
static void photo_booth_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
static void photo_booth_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
static void photo_booth_dispose (GObject *object); static void photo_booth_dispose (GObject *object);
static void photo_booth_finalize (GObject *object); static void photo_booth_finalize (GObject *object);
PhotoBooth *photo_booth_new (void); PhotoBooth *photo_booth_new (void);
@ -92,7 +92,6 @@ void photo_booth_background_clicked (GtkWidget *widget, GdkEventButton *event, P
void photo_booth_button_yes_clicked (GtkButton *button, PhotoBoothWindow *win); void photo_booth_button_yes_clicked (GtkButton *button, PhotoBoothWindow *win);
/* general private functions */ /* general private functions */
static void photo_booth_load_strings ();
const gchar* photo_booth_state_get_name (PhotoboothState state); const gchar* photo_booth_state_get_name (PhotoboothState state);
static void photo_booth_change_state (PhotoBooth *pb, PhotoboothState state); static void photo_booth_change_state (PhotoBooth *pb, PhotoboothState state);
static void photo_booth_quit_signal (PhotoBooth *pb); static void photo_booth_quit_signal (PhotoBooth *pb);
@ -145,23 +144,8 @@ static void photo_booth_class_init (PhotoBoothClass *klass)
gobject_class->finalize = photo_booth_finalize; gobject_class->finalize = photo_booth_finalize;
gobject_class->dispose = photo_booth_dispose; gobject_class->dispose = photo_booth_dispose;
gobject_class->set_property = photo_booth_set_property;
gobject_class->get_property = photo_booth_get_property;
gapplication_class->activate = photo_booth_activate; gapplication_class->activate = photo_booth_activate;
gapplication_class->open = photo_booth_open; gapplication_class->open = photo_booth_open;
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_COUNTDOWN,
g_param_spec_uint ("countdown", "Shutter delay (s)",
"Specify shutter actuation delay countdown in seconds", 0, 60, DEFAULT_COUNTDOWN,
G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PRINTER_BACKEND,
g_param_spec_string ("printer-backend", "Gutenprint backend",
"Specify which Gutenprint backend to use", DEFAULT_PRINTER_BACKEND,
G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PRINTS_REMAINING,
g_param_spec_int ("prints-remaining", "Print media remaining",
"Show remaining prints on media roll (-1 = Unknown)", -1, 1000, -1,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
} }
static void photo_booth_init (PhotoBooth *pb) static void photo_booth_init (PhotoBooth *pb)
@ -203,10 +187,23 @@ static void photo_booth_init (PhotoBooth *pb)
} }
priv->capture_thread = NULL; priv->capture_thread = NULL;
priv->countdown = DEFAULT_COUNTDOWN;
priv->preview_fps = PREVIEW_FPS;
priv->preview_width = PREVIEW_WIDTH;
priv->preview_height = PREVIEW_HEIGHT;
priv->print_dpi = PRINT_DPI;
priv->print_width = PRINT_WIDTH;
priv->print_height = PRINT_HEIGHT;
priv->print_buffer = NULL; priv->print_buffer = NULL;
priv->print_icc_profile = NULL;
priv->cam_icc_profile = NULL;
priv->printer_backend = NULL;
priv->printer_settings = NULL; priv->printer_settings = NULL;
priv->overlay_image = NULL;
G_strings_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
g_mutex_init (&priv->processing_mutex); g_mutex_init (&priv->processing_mutex);
photo_booth_load_strings();
} }
static void photo_booth_change_state (PhotoBooth *pb, PhotoboothState newstate) static void photo_booth_change_state (PhotoBooth *pb, PhotoboothState newstate)
@ -266,43 +263,91 @@ static void photo_booth_dispose (GObject *object)
g_free (priv->printer_backend); g_free (priv->printer_backend);
if (priv->printer_settings != NULL) if (priv->printer_settings != NULL)
g_object_unref (priv->printer_settings); g_object_unref (priv->printer_settings);
g_free (priv->countdown_audio_uri);
g_free (priv->print_icc_profile);
g_free (priv->cam_icc_profile);
g_free (priv->overlay_image);
g_hash_table_destroy (G_strings_table);
g_mutex_clear (&priv->processing_mutex); g_mutex_clear (&priv->processing_mutex);
G_OBJECT_CLASS (photo_booth_parent_class)->dispose (object); G_OBJECT_CLASS (photo_booth_parent_class)->dispose (object);
} }
static void photo_booth_load_strings () void photo_booth_load_settings (PhotoBooth *pb, const gchar *filename)
{ {
GKeyFile* gkf; GKeyFile* gkf;
GError *error = NULL; GError *error = NULL;
guint group, keyidx; guint keyidx;
gsize num_groups, num_keys; gsize num_keys;
gchar **groups, **keys, *val; gchar **keys, *val;
gchar *key; gchar *key;
gchar *value; gchar *value;
PhotoBoothPrivate *priv = photo_booth_get_instance_private (pb);
GST_DEBUG_OBJECT (pb, "loading settings from file %s", filename);
G_strings_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
gkf = g_key_file_new(); gkf = g_key_file_new();
if (g_key_file_load_from_file(gkf, STRINGS_FILE, G_KEY_FILE_NONE, &error)) if (g_key_file_load_from_file (gkf, filename, G_KEY_FILE_NONE, &error))
{ {
groups = g_key_file_get_groups(gkf, &num_groups); if (g_key_file_has_group (gkf, "strings"))
for (group = 0; group < num_groups; group++)
{ {
GST_INFO("group %u/%u: \t%s", group, num_groups - 1, groups[group]); keys = g_key_file_get_keys (gkf, "strings", &num_keys, &error);
keys = g_key_file_get_keys (gkf, groups[group], &num_keys, &error);
for (keyidx = 0; keyidx < num_keys; keyidx++) for (keyidx = 0; keyidx < num_keys; keyidx++)
{ {
val = g_key_file_get_value(gkf, groups[group], keys[keyidx], &error); val = g_key_file_get_value(gkf, "strings", keys[keyidx], &error);
key = g_strdup(keys[keyidx]); key = g_strdup(keys[keyidx]);
value = g_strdup(val); value = g_strdup(val);
g_hash_table_insert (G_strings_table, key, value); g_hash_table_insert (G_strings_table, key, value);
GST_LOG ("key %u/%u:\t'%s' => '%s'", keyidx, num_keys-1, key, value); GST_LOG ("key %u/%u:\t'%s' => '%s'", keyidx, num_keys-1, key, value);
} }
if (error)
{
GST_INFO ( "can't read string: %s", error->message);
g_error_free (error);
}
}
if (g_key_file_has_group (gkf, "general"))
{
priv->countdown = g_key_file_get_integer (gkf, "general", "countdown", NULL);
gchar *audiofile = g_key_file_get_string (gkf, "general", "countdown_audio_file", NULL);
if (audiofile)
{
gchar *audioabsfilename;
if (audiofile[0] != '/')
{
gchar *cur = g_get_current_dir ();
audioabsfilename = g_strdup_printf ("%s/%s", cur, audiofile);
}
else
audioabsfilename = g_strdup (audiofile);
priv->countdown_audio_uri = g_filename_to_uri (audioabsfilename, NULL, NULL);
g_free (audiofile);
g_free (audioabsfilename);
}
priv->overlay_image = g_key_file_get_string (gkf, "general", "overlay_image", NULL);
GST_INFO ( "overlay_image: %s", priv->overlay_image);
}
if (g_key_file_has_group (gkf, "printer"))
{
priv->printer_backend = g_key_file_get_string (gkf, "printer", "backend", NULL);
priv->print_dpi = g_key_file_get_integer (gkf, "printer", "dpi", NULL);
priv->print_width = g_key_file_get_integer (gkf, "printer", "width", NULL);
priv->print_height = g_key_file_get_integer (gkf, "printer", "height", NULL);
priv->print_icc_profile = g_key_file_get_string (gkf, "printer", "icc_profile", NULL);
}
if (g_key_file_has_group (gkf, "camera"))
{
priv->preview_fps = g_key_file_get_integer (gkf, "camera", "fps", NULL);
priv->preview_width = g_key_file_get_integer (gkf, "camera", "preview_width", NULL);
priv->preview_height = g_key_file_get_integer (gkf, "camera", "preview_height", NULL);
priv->cam_reeinit_before_snapshot = g_key_file_get_boolean (gkf, "camera", "cam_reeinit_before_snapshot", NULL);
priv->cam_reeinit_after_snapshot = g_key_file_get_boolean (gkf, "camera", "cam_reeinit_after_snapshot", NULL);
priv->cam_icc_profile = g_key_file_get_string (gkf, "camera", "icc_profile", NULL);
} }
} }
if (error) if (error)
{ {
GST_INFO ( "can't read strings lookup file %s: %s", STRINGS_FILE, error->message); GST_INFO ( "can't open settings file %s: %s", filename, error->message);
g_error_free (error); g_error_free (error);
} }
} }
@ -384,45 +429,6 @@ static void photo_booth_window_destroyed_signal (PhotoBoothWindow *win, PhotoBoo
g_application_quit (G_APPLICATION (pb)); g_application_quit (G_APPLICATION (pb));
} }
static void photo_booth_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec)
{
PhotoBooth *pb = PHOTO_BOOTH (object);
PhotoBoothPrivate *priv = photo_booth_get_instance_private (pb);
switch (prop_id) {
case ARG_COUNTDOWN:
priv->countdown = g_value_get_uint (value);
break;
case ARG_PRINTER_BACKEND:
priv->printer_backend = g_strdup (g_value_get_string (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void photo_booth_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec)
{
PhotoBooth *pb = PHOTO_BOOTH (object);
PhotoBoothPrivate *priv = photo_booth_get_instance_private (pb);
switch (prop_id) {
case ARG_COUNTDOWN:
g_value_set_uint (value, priv->countdown);
break;
case ARG_PRINTER_BACKEND:
g_value_set_string (value, priv->printer_backend);
break;
case ARG_PRINTS_REMAINING:
g_value_set_int (value, priv->prints_remaining);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void photo_booth_capture_thread_func (PhotoBooth *pb) static void photo_booth_capture_thread_func (PhotoBooth *pb)
{ {
PhotoboothCaptureThreadState state = CAPTURE_INIT; PhotoboothCaptureThreadState state = CAPTURE_INIT;
@ -508,10 +514,11 @@ static void photo_booth_capture_thread_func (PhotoBooth *pb)
{ {
gtk_label_set_text (priv->win->status, _("Focussing...")); gtk_label_set_text (priv->win->status, _("Focussing..."));
// photo_booth_focus (pb->cam_info); // photo_booth_focus (pb->cam_info);
#if CAM_REINIT_BEFORE_SNAPSHOT if (priv->cam_reeinit_before_snapshot)
photo_booth_cam_close (&pb->cam_info); {
photo_booth_cam_init (&pb->cam_info); photo_booth_cam_close (&pb->cam_info);
#endif photo_booth_cam_init (&pb->cam_info);
}
} }
else if (ret == 0 && state == CAPTURE_PHOTO) else if (ret == 0 && state == CAPTURE_PHOTO)
{ {
@ -522,10 +529,11 @@ static void photo_booth_capture_thread_func (PhotoBooth *pb)
if (ret) if (ret)
{ {
g_main_context_invoke (NULL, (GSourceFunc) photo_booth_snapshot_taken, pb); g_main_context_invoke (NULL, (GSourceFunc) photo_booth_snapshot_taken, pb);
#if CAM_REINIT_AFTER_SNAPSHOT if (priv->cam_reeinit_after_snapshot)
photo_booth_cam_close (&pb->cam_info); {
photo_booth_cam_init (&pb->cam_info); photo_booth_cam_close (&pb->cam_info);
#endif 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!"));
@ -586,11 +594,14 @@ static void photo_booth_capture_thread_func (PhotoBooth *pb)
static GstElement *build_video_bin (PhotoBooth *pb) static GstElement *build_video_bin (PhotoBooth *pb)
{ {
PhotoBoothPrivate *priv;
GstElement *video_bin; GstElement *video_bin;
GstElement *mjpeg_source, *mjpeg_decoder, *mjpeg_filter, *video_filter, *video_scale, *video_convert, *video_overlay; GstElement *mjpeg_source, *mjpeg_decoder, *mjpeg_filter, *video_filter, *video_scale, *video_convert, *video_overlay;
GstCaps *caps; GstCaps *caps;
GstPad *ghost, *pad; GstPad *ghost, *pad;
priv = photo_booth_get_instance_private (pb);
video_bin = gst_element_factory_make ("bin", "video-bin"); video_bin = gst_element_factory_make ("bin", "video-bin");
mjpeg_source = gst_element_factory_make ("fdsrc", "mjpeg-fdsrc"); mjpeg_source = gst_element_factory_make ("fdsrc", "mjpeg-fdsrc");
g_object_set (mjpeg_source, "fd", pb->video_fd, NULL); g_object_set (mjpeg_source, "fd", pb->video_fd, NULL);
@ -598,7 +609,7 @@ static GstElement *build_video_bin (PhotoBooth *pb)
g_object_set (mjpeg_source, "blocksize", 65536, NULL); g_object_set (mjpeg_source, "blocksize", 65536, NULL);
mjpeg_filter = gst_element_factory_make ("capsfilter", "mjpeg-capsfilter"); mjpeg_filter = gst_element_factory_make ("capsfilter", "mjpeg-capsfilter");
caps = gst_caps_new_simple ("image/jpeg", "width", G_TYPE_INT, PREVIEW_WIDTH, "height", G_TYPE_INT, PREVIEW_HEIGHT, "framerate", GST_TYPE_FRACTION, PREVIEW_FPS, 1, "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1, NULL); caps = gst_caps_new_simple ("image/jpeg", "width", G_TYPE_INT, priv->preview_width, "height", G_TYPE_INT, priv->preview_height, "framerate", GST_TYPE_FRACTION, PREVIEW_FPS, 1, "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1, NULL);
g_object_set (G_OBJECT (mjpeg_filter), "caps", caps, NULL); g_object_set (G_OBJECT (mjpeg_filter), "caps", caps, NULL);
gst_caps_unref (caps); gst_caps_unref (caps);
@ -606,12 +617,13 @@ static GstElement *build_video_bin (PhotoBooth *pb)
video_scale = gst_element_factory_make ("videoscale", "mjpeg-videoscale"); video_scale = gst_element_factory_make ("videoscale", "mjpeg-videoscale");
video_convert = gst_element_factory_make ("videoconvert", "mjpeg-videoconvert"); video_convert = gst_element_factory_make ("videoconvert", "mjpeg-videoconvert");
video_filter = gst_element_factory_make ("capsfilter", "video-capsfilter"); video_filter = gst_element_factory_make ("capsfilter", "video-capsfilter");
caps = gst_caps_new_simple ("video/x-raw", "width", G_TYPE_INT, PREVIEW_WIDTH, "height", G_TYPE_INT, PREVIEW_HEIGHT, NULL); caps = gst_caps_new_simple ("video/x-raw", "width", G_TYPE_INT, priv->preview_width, "height", G_TYPE_INT, priv->preview_height, NULL);
g_object_set (G_OBJECT (video_filter), "caps", caps, NULL); g_object_set (G_OBJECT (video_filter), "caps", caps, NULL);
gst_caps_unref (caps); gst_caps_unref (caps);
video_overlay = gst_element_factory_make ("gdkpixbufoverlay", "video-overlay"); video_overlay = gst_element_factory_make ("gdkpixbufoverlay", "video-overlay");
g_object_set (video_overlay, "location", "overlay_print.png", NULL); if (priv->overlay_image)
g_object_set (video_overlay, "location", priv->overlay_image, NULL);
if (!(mjpeg_source && mjpeg_filter && mjpeg_decoder && video_scale && video_convert && video_filter && video_overlay)) if (!(mjpeg_source && mjpeg_filter && mjpeg_decoder && video_scale && video_convert && video_filter && video_overlay))
{ {
@ -638,11 +650,14 @@ static GstElement *build_video_bin (PhotoBooth *pb)
static GstElement *build_photo_bin (PhotoBooth *pb) static GstElement *build_photo_bin (PhotoBooth *pb)
{ {
PhotoBoothPrivate *priv;
GstElement *photo_bin; GstElement *photo_bin;
GstElement *photo_source, *photo_decoder, *photo_freeze, *photo_scale, *photo_filter, *photo_overlay, *photo_convert, *photo_gamma, *photo_tee; GstElement *photo_source, *photo_decoder, *photo_freeze, *photo_scale, *photo_filter, *photo_overlay, *photo_convert, *photo_gamma, *photo_tee;
GstCaps *caps; GstCaps *caps;
GstPad *ghost, *pad; GstPad *ghost, *pad;
priv = photo_booth_get_instance_private (pb);
photo_bin = gst_element_factory_make ("bin", "photo-bin"); photo_bin = gst_element_factory_make ("bin", "photo-bin");
photo_source = gst_element_factory_make ("appsrc", "photo-appsrc"); photo_source = gst_element_factory_make ("appsrc", "photo-appsrc");
photo_decoder = gst_element_factory_make ("jpegdec", "photo-decoder"); photo_decoder = gst_element_factory_make ("jpegdec", "photo-decoder");
@ -650,14 +665,15 @@ static GstElement *build_photo_bin (PhotoBooth *pb)
photo_scale = gst_element_factory_make ("videoscale", "photo-scale"); photo_scale = gst_element_factory_make ("videoscale", "photo-scale");
photo_filter = gst_element_factory_make ("capsfilter", "photo-capsfilter"); photo_filter = gst_element_factory_make ("capsfilter", "photo-capsfilter");
caps = gst_caps_new_simple ("video/x-raw", "width", G_TYPE_INT, PRINT_WIDTH, "height", G_TYPE_INT, PRINT_HEIGHT, "framerate", GST_TYPE_FRACTION, 10, 1, NULL); caps = gst_caps_new_simple ("video/x-raw", "width", G_TYPE_INT, priv->print_width, "height", G_TYPE_INT, priv->print_height, "framerate", GST_TYPE_FRACTION, 10, 1, NULL);
g_object_set (G_OBJECT (photo_filter), "caps", caps, NULL); g_object_set (G_OBJECT (photo_filter), "caps", caps, NULL);
gst_caps_unref (caps); gst_caps_unref (caps);
photo_overlay = gst_element_factory_make ("gdkpixbufoverlay", "photo-overlay"); photo_overlay = gst_element_factory_make ("gdkpixbufoverlay", "photo-overlay");
g_object_set (photo_overlay, "location", "overlay_print.png", NULL); if (priv->overlay_image)
g_object_set (photo_overlay, "overlay-width", PRINT_WIDTH, NULL); g_object_set (photo_overlay, "location", priv->overlay_image, NULL);
g_object_set (photo_overlay, "overlay-height", PRINT_HEIGHT, NULL); g_object_set (photo_overlay, "overlay-width", priv->print_width, NULL);
g_object_set (photo_overlay, "overlay-height", priv->print_height, NULL);
photo_convert = gst_element_factory_make ("videoconvert", "photo-convert"); photo_convert = gst_element_factory_make ("videoconvert", "photo-convert");
photo_gamma = gst_element_factory_make ("gamma", "photo-gamma"); photo_gamma = gst_element_factory_make ("gamma", "photo-gamma");
@ -911,7 +927,11 @@ static gboolean photo_booth_get_printer_status (PhotoBooth *pb)
gint remain = -1; gint remain = -1;
gint ret = 0; gint ret = 0;
if (g_spawn_sync (NULL, argv, envp, G_SPAWN_DEFAULT, NULL, NULL, NULL, &output, &ret, &error)) if (!priv->printer_backend)
{
label_string = g_strdup_printf(_("No printer configured!"));
}
else if (g_spawn_sync (NULL, argv, envp, G_SPAWN_DEFAULT, NULL, NULL, NULL, &output, &ret, &error))
{ {
GMatchInfo *match_info; GMatchInfo *match_info;
GRegex *regex; GRegex *regex;
@ -968,7 +988,6 @@ static gboolean photo_booth_get_printer_status (PhotoBooth *pb)
static void photo_booth_snapshot_start (PhotoBooth *pb) static void photo_booth_snapshot_start (PhotoBooth *pb)
{ {
PhotoBoothPrivate *priv; PhotoBoothPrivate *priv;
gchar* uri;
guint pretrigger_delay = 1; guint pretrigger_delay = 1;
guint snapshot_delay = 2; guint snapshot_delay = 2;
@ -984,11 +1003,11 @@ static void photo_booth_snapshot_start (PhotoBooth *pb)
g_timeout_add (pretrigger_delay, (GSourceFunc) photo_booth_snapshot_prepare, pb); g_timeout_add (pretrigger_delay, (GSourceFunc) photo_booth_snapshot_prepare, pb);
g_timeout_add (snapshot_delay, (GSourceFunc) photo_booth_snapshot_trigger, pb); g_timeout_add (snapshot_delay, (GSourceFunc) photo_booth_snapshot_trigger, pb);
uri = g_filename_to_uri (DEFAULT_AUDIOFILE_COUNTDOWN, NULL, NULL); if (priv->countdown_audio_uri)
GST_DEBUG_OBJECT (pb, "audio uri: %s", uri); {
g_object_set (priv->audio_playbin, "uri", uri, NULL); g_object_set (priv->audio_playbin, "uri", priv->countdown_audio_uri, NULL);
g_free (uri); gst_element_set_state (priv->audio_pipeline, GST_STATE_PLAYING);
gst_element_set_state (priv->audio_pipeline, GST_STATE_PLAYING); }
} }
static gboolean photo_booth_snapshot_prepare (PhotoBooth *pb) static gboolean photo_booth_snapshot_prepare (PhotoBooth *pb)
@ -1196,9 +1215,6 @@ static GstPadProbeReturn photo_booth_catch_photo_buffer (GstPad * pad, GstPadPro
return ret; return ret;
} }
#define ICC_INPUT_TEMPLATE "CNXD-sRGB.icc"
#define ICC_DEST_TEMPLATE "CP955_F.icc"
static gboolean photo_booth_process_photo_plug_elements (PhotoBooth *pb) static gboolean photo_booth_process_photo_plug_elements (PhotoBooth *pb)
{ {
PhotoBoothPrivate *priv; PhotoBoothPrivate *priv;
@ -1229,8 +1245,10 @@ static gboolean photo_booth_process_photo_plug_elements (PhotoBooth *pb)
{ {
g_object_set (G_OBJECT (lcms), "intent", 0, NULL); g_object_set (G_OBJECT (lcms), "intent", 0, NULL);
g_object_set (G_OBJECT (lcms), "lookup", 2, NULL); g_object_set (G_OBJECT (lcms), "lookup", 2, NULL);
g_object_set (G_OBJECT (lcms), "input-profile", ICC_INPUT_TEMPLATE, NULL); if (priv->cam_icc_profile)
g_object_set (G_OBJECT (lcms), "dest-profile", ICC_DEST_TEMPLATE, NULL); g_object_set (G_OBJECT (lcms), "input-profile", priv->cam_icc_profile, NULL);
if (priv->print_icc_profile)
g_object_set (G_OBJECT (lcms), "dest-profile", priv->print_icc_profile, NULL);
g_object_set (G_OBJECT (lcms), "preserve-black", TRUE, NULL); g_object_set (G_OBJECT (lcms), "preserve-black", TRUE, NULL);
gst_bin_add (GST_BIN (pb->photo_bin), lcms); gst_bin_add (GST_BIN (pb->photo_bin), lcms);
} }
@ -1455,13 +1473,13 @@ static void photo_booth_draw_page (GtkPrintOperation *operation, GtkPrintContext
guint8 *h = map.data; guint8 *h = map.data;
guint l = map.size; guint l = map.size;
int stride = cairo_format_stride_for_width (CAIRO_FORMAT_RGB24, PRINT_WIDTH); int stride = cairo_format_stride_for_width (CAIRO_FORMAT_RGB24, priv->print_width);
cairo_surface_t *cairosurface = cairo_image_surface_create_for_data (map.data, CAIRO_FORMAT_RGB24, PRINT_WIDTH, PRINT_HEIGHT, stride); cairo_surface_t *cairosurface = cairo_image_surface_create_for_data (map.data, CAIRO_FORMAT_RGB24, priv->print_width, priv->print_height, stride);
cairo_t *cr = gtk_print_context_get_cairo_context (context); cairo_t *cr = gtk_print_context_get_cairo_context (context);
cairo_matrix_t m; cairo_matrix_t m;
cairo_get_matrix(cr, &m); cairo_get_matrix(cr, &m);
float scale = (float) PT_PER_IN / (float) PRINT_DPI; float scale = (float) PT_PER_IN / (float) priv->print_dpi;
cairo_scale(cr, scale, scale); cairo_scale(cr, scale, scale);
cairo_set_source_surface(cr, cairosurface, 16.0, 16.0); // FIXME offsets? cairo_set_source_surface(cr, cairosurface, 16.0, 16.0); // FIXME offsets?
cairo_paint(cr); cairo_paint(cr);
@ -1535,6 +1553,11 @@ int main (int argc, char *argv[])
gst_init (0, NULL); gst_init (0, NULL);
pb = photo_booth_new (); pb = photo_booth_new ();
if (argc == 2)
photo_booth_load_settings (pb, argv[1]);
else
photo_booth_load_settings (pb, DEFAULT_CONFIG);
g_unix_signal_add (SIGINT, (GSourceFunc) photo_booth_quit_signal, pb); g_unix_signal_add (SIGINT, (GSourceFunc) photo_booth_quit_signal, pb);
ret = g_application_run (G_APPLICATION (pb), argc, argv); ret = g_application_run (G_APPLICATION (pb), argc, argv);

View file

@ -51,9 +51,6 @@ G_STMT_START { \
G_BEGIN_DECLS G_BEGIN_DECLS
#define PREVIEW_FPS 24
#define PT_PER_IN 72
struct _CameraInfo { struct _CameraInfo {
Camera *camera; Camera *camera;
GPContext *context; GPContext *context;
@ -85,7 +82,6 @@ typedef enum
PB_STATE_PRINTING PB_STATE_PRINTING
} PhotoboothState; } PhotoboothState;
#define STRINGS_FILE "strings.ini"
GHashTable *G_strings_table; GHashTable *G_strings_table;
#define _(key) (g_hash_table_contains (G_strings_table, key) ? g_hash_table_lookup (G_strings_table, key) : key) #define _(key) (g_hash_table_contains (G_strings_table, key) ? g_hash_table_lookup (G_strings_table, key) : key)
@ -123,6 +119,8 @@ struct _PhotoBoothClass
}; };
GType photo_booth_get_type (void); GType photo_booth_get_type (void);
PhotoBooth *photo_booth_new (void);
void photo_booth_load_settings (PhotoBooth *pb, const gchar *filename);
G_END_DECLS G_END_DECLS