diff --git a/Makefile b/Makefile index bdd334c..1127d48 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ APP = simpleskycam -include Makefile.rules -OBJECTS = gui.oo main.oo video.oo videoframe.oo videodev.oo filter.oo detect.oo +OBJECTS = gui.oo main.oo video.oo videoframe.oo videodev.oo filter.oo detect.oo json.oo configuration.oo DISTNAME=simpleskycam-$(VERSION) ifeq ($(TARGET),) diff --git a/gui.cc b/gui.cc index 0b8ffd6..8f58edf 100644 --- a/gui.cc +++ b/gui.cc @@ -15,6 +15,7 @@ #include "video.h" #include "filter.h" #include "detect.h" +#include "configuration.h" extern GtkBuilder *_builder_; // work around for threads extern Filter filter; @@ -31,6 +32,7 @@ GdkPixbuf *detect_pixbuf = NULL; GtkWidget *image_da = NULL; GdkPixbuf *image_pixbuf = NULL; std::string filename = ""; +extern Configuration config; ////////////////////////////////////////////////////////////////////////////////////////////////// // @@ -38,6 +40,7 @@ std::string filename = ""; // gboolean cb_window_delete_event (GtkWidget *widget, GdkEvent *event, gpointer data) { + config.SaveDefault(); gtk_main_quit(); return FALSE; }; @@ -66,7 +69,11 @@ void cb_window_show (GtkWidget *widget, gpointer data) { gtk_entry_set_text(GTK_ENTRY(h),"300"); detect.SetObjectSize(300, 300); + cb_video_btnrefreshlist (NULL, NULL); + config.LoadDefault(); + // + // update the input video controls every 2 seconds. g_timeout_add(2000, videoctrl_update, NULL); }; @@ -85,7 +92,6 @@ void displayerror (std::string error) { }; - // // callback from filter thread. Data will point to the output VideoFrame. // Access to this data must be Locked before use. @@ -243,8 +249,8 @@ void cb_image_btnsave (GtkWidget *widget, gpointer data) { chooser = GTK_FILE_CHOOSER (dialog); filter = gtk_file_filter_new(); - gtk_file_filter_add_pattern(filter, "*.modbus"); - gtk_file_filter_set_name(filter, "Test Modbus Config"); + gtk_file_filter_add_pattern(filter, "*.png"); + gtk_file_filter_set_name(filter, "PNG File"); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter); filter = gtk_file_filter_new(); gtk_file_filter_add_pattern(filter, "*.*"); diff --git a/gui.h b/gui.h index c89e9b3..0afff5e 100644 --- a/gui.h +++ b/gui.h @@ -57,6 +57,9 @@ G_MODULE_EXPORT void cb_vidctrl_entry_change (GtkWidget *widget, gpointer data); G_MODULE_EXPORT void cb_vidctrl_scale_change (GtkRange *range, gpointer data); gboolean videoctrl_update(gpointer data); +G_MODULE_EXPORT void cb_video_pre_click (GtkWidget *widget, gpointer data); +G_MODULE_EXPORT void cb_video_pre_pressed (GtkWidget *widget, gpointer data); +gboolean video_pre_long(gpointer data); // // thread new inframe diff --git a/main.cc b/main.cc index 9b80b7d..d04364d 100644 --- a/main.cc +++ b/main.cc @@ -7,18 +7,19 @@ #include #include "config.h" +#include "configuration.h" #include "gui.h" #include "filter.h" #include "detect.h" -////////////////////////////////////////////////////////////////////////////////////////////////// -// -// global variables -// +/************************************************************************** + * global variables + **************************************************************************/ GtkBuilder *_builder_ = NULL; // work around for the thread situation Filter filter; Detect detect; +Configuration config; int main (int argc, char **argv) { GtkBuilder *builder; diff --git a/simpleskycam.ui b/simpleskycam.ui index 8d4a2b3..0291e9e 100644 --- a/simpleskycam.ui +++ b/simpleskycam.ui @@ -242,7 +242,85 @@ - + + True + False + + + 4 + True + True + True + + + + + + False + True + end + 0 + + + + + 3 + True + True + True + + + + + + False + True + end + 1 + + + + + 2 + True + True + True + + + + + + False + True + end + 2 + + + + + 1 + True + True + True + + + + + + False + True + end + 3 + + + + + False + True + 4 + end + 5 + diff --git a/video.cc b/video.cc index a75aa91..ef27d28 100644 --- a/video.cc +++ b/video.cc @@ -8,10 +8,12 @@ #include #include #include +#include #include "gui.h" #include "video.h" #include "filter.h" #include "detect.h" +#include "configuration.h" VideoDev videodev; GtkWidget *video_da = NULL; @@ -20,7 +22,7 @@ extern GtkBuilder *_builder_; // work around for threads extern Detect detect; extern int video_enterdata; extern position_2d video_enterdata_pos; - +extern Configuration config; gboolean videoctrl_update(gpointer data) { GtkWidget *grid = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "vidctrl-grid")); @@ -188,8 +190,9 @@ void cb_videoda_draw(GtkWidget *area, cairo_t *cr, int w, int h, gpointer data) -// -// refresh the possible devices +/* + * refresh the possible devices + */ void cb_video_btnrefreshlist (GtkWidget *widget, gpointer data) { GtkWidget *cbox = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "cb-videodev")); GtkListStore *model = GTK_LIST_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(cbox))); @@ -216,10 +219,11 @@ void cb_video_btnrefreshlist (GtkWidget *widget, gpointer data) { }; -// -// start recording from the videodev (will start a new thread) -// load list of controls from the video device and create the GtkGrid -// with all elements. Also connect the signals to the callback functions. +/* + * start recording from the videodev (will start a new thread) + * load list of controls from the video device and create the GtkGrid + * with all elements. Also connect the signals to the callback functions. + */ void cb_video_btnrec (GtkWidget *widget, gpointer data) { std::list list; std::list::iterator iter; @@ -290,8 +294,9 @@ void cb_video_btnrec (GtkWidget *widget, gpointer data) { }; -// -// stop recording from the videodev (will stop the running thread) +/* + * stop recording from the videodev (will stop the running thread) + */ void cb_video_btnstop (GtkWidget *widget, gpointer data) { GtkWidget *btnstart = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "btn-video-rec")); GtkWidget *btnstop = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "btn-video-stop")); @@ -304,9 +309,10 @@ void cb_video_btnstop (GtkWidget *widget, gpointer data) { }; -// -// callback from videodev thread. data will point to the latest VideoFrame. -// Access to this data must be Locked before use. +/* + * callback from videodev thread. data will point to the latest VideoFrame. + * Access to this data must be Locked before use. + */ gboolean cb_thread_video (gpointer data) { GtkWidget *btnstart; GtkWidget *btnstop; @@ -357,15 +363,17 @@ gboolean cb_thread_video (gpointer data) { }; -// -// set ctrl on the device +/* + * set ctrl on the device + */ void videoctrl_set(std::string name, int value) { videodev.SetCtrlValue(name, value); } -// -// callback video control scale change +/* + * callback video control scale change + */ void cb_vidctrl_scale_change (GtkRange *range, gpointer data) { GtkWidget *grid = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "vidctrl-grid")); GtkWidget *scale = NULL; @@ -382,8 +390,9 @@ void cb_vidctrl_scale_change (GtkRange *range, gpointer data) { }; -// -// callback video control entry change +/* + * callback video control entry change + */ void cb_vidctrl_entry_change (GtkWidget *widget, gpointer data) { GtkWidget *grid = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "vidctrl-grid")); GtkWidget *label = NULL; @@ -445,4 +454,97 @@ void cb_videoda_btnrelease (GtkWidget *widget, GdkEvent *event, gpointer data) { }; +/* + * cb_video_pre_click/cb_video_pre_pressed, are needed to detect is we press + * the button longer as two seconds. If it is, all settings will be saved. + */ +#define BTNDOWN_TIME 1.0 +struct { + int idx; + struct timeval tv; + guint timer; +} presetbtn; +void cb_video_pre_click (GtkWidget *widget, gpointer data) { + float pushtime = get_cycletime(&presetbtn.tv); + std::string s; + int idx; + GtkWidget *btn; + + if (pushtime > BTNDOWN_TIME && presetbtn.idx >= 0 && presetbtn.idx < BTN_PRESET_MAX) { + // + // save the settings + // + list ctrls = videodev.GetCtrlsMinMaxValue(); + config.SetPresetButton(presetbtn.idx, &ctrls); + + // + // reset button label + // + for (idx = 0; idx < BTN_PRESET_MAX; idx++) { + s = "btn-video-pre"+std::to_string(idx+1); + if ((btn = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), s.c_str()))) != NULL) { + gtk_button_set_label(GTK_BUTTON(btn), std::to_string(idx+1).c_str()); + } + } + } + else if (presetbtn.idx >= 0 && presetbtn.idx < BTN_PRESET_MAX) { + // + // callup settings + // + int i, retry = 5, again = 1; + list ctrls = config.GetPresetButton(presetbtn.idx); + list::iterator iter; + presetbtn.idx = -1; + + for (retry = 5; retry > 0 && again; retry--) { + again = 0; + for (iter = ctrls.begin(); iter != ctrls.end(); iter++) { + videodev.SetCtrlValue(iter->name, iter->value); + usleep(10000); + videodev.GetCtrlMinMaxValue(iter->name, NULL, NULL, &i); + if (i != iter->value) again = 1; + } + } + } +}; + + +/* + * should determine the pressed button and save it together with the current + * time in structure presetbtn. + */ +void cb_video_pre_pressed (GtkWidget *widget, gpointer data) { + int idx = -1; + std::string s; + GtkWidget *btn; + + for (idx = 0; idx < BTN_PRESET_MAX; idx++) { + s = "btn-video-pre"+std::to_string(idx+1); + if ((btn = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), s.c_str()))) == widget) { + if (presetbtn.timer <= 0) + presetbtn.timer = g_timeout_add((int)(BTNDOWN_TIME*1000.0), video_pre_long, NULL); + break; + } + } + + presetbtn.idx = idx; + gettimeofday (&presetbtn.tv, NULL); +}; + + +/* + * gnome timer callback if any presetbutton was pressed down + * in case the button is still pressed, we write SAVED in the buttons label. + */ +gboolean video_pre_long(gpointer data) { + std::string s = "btn-video-pre"+std::to_string(presetbtn.idx+1); + GtkWidget *btn = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), s.c_str())); + + if (btn && presetbtn.idx >= 0 && presetbtn.idx < BTN_PRESET_MAX) + gtk_button_set_label(GTK_BUTTON(btn), "Saved"); + + presetbtn.timer = 0; + return FALSE; +}; + diff --git a/video.h b/video.h index f47b022..18792a5 100644 --- a/video.h +++ b/video.h @@ -14,7 +14,7 @@ #include #include - +#include "json.h" #include "gui.h" #include "config.h" #include "videoframe.h" @@ -119,6 +119,7 @@ public: int GetDeviceList(std::list *list); int GetCtrlList(std::list *list); int GetCtrlMinMaxValue(std::string name, int *min, int *max, int *value); + list GetCtrlsMinMaxValue(); int SetCtrlValue(std::string name, int value); int IsRunning() { return running; }; @@ -127,6 +128,8 @@ public: void LockMutex() { g_mutex_lock(&mutex); }; void UnLockMutex() { g_mutex_unlock(&mutex); }; + + std::string GetDevice() { return conf_device; }; }; diff --git a/videodev.cc b/videodev.cc index fd6f946..2a65321 100644 --- a/videodev.cc +++ b/videodev.cc @@ -400,8 +400,9 @@ int VideoDev::Grab(VideoFrame *vf) { return VDEV_STATUS_OK; } -// -// Open Device +/* + * Open Device + */ int VideoDev::OpenInit() { int i; struct v4l2_capability vcap; @@ -468,8 +469,8 @@ int VideoDev::OpenInit() { fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmt.fmt.pix.width = 1920; fmt.fmt.pix.height = 1080; -// fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB32; - fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG; + fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB32; +// fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG; fmt.fmt.pix.field = V4L2_FIELD_NONE; if (-1 == xioctl (fd, VIDIOC_S_FMT, &fmt)) { @@ -502,8 +503,9 @@ int VideoDev::OpenInit() { }; -// -// set video control identified by id +/* + * set video control identified by id + */ int VideoDev::SetDevCtrl(unsigned int id, int value) { struct v4l2_control ctrl; @@ -518,8 +520,9 @@ int VideoDev::SetDevCtrl(unsigned int id, int value) { }; -// -// get video control identified by id +/* + * get video control identified by id + */ int VideoDev::GetDevCtrl(unsigned int id, int *value) { struct v4l2_control ctrl; @@ -535,8 +538,9 @@ int VideoDev::GetDevCtrl(unsigned int id, int *value) { -// -// prepare memory mapped buffers +/* + * prepare memory mapped buffers + */ int VideoDev::InitMMap() { struct v4l2_requestbuffers bufreq; struct v4l2_buffer bufinfo; @@ -590,8 +594,9 @@ int VideoDev::InitMMap() { } -// -// send the start capture signal to the cam +/* + * send the start capture signal to the cam + */ int VideoDev::CaptureStart() { enum v4l2_buf_type type; @@ -694,10 +699,10 @@ int VideoDev::UnInit() { }; -// -// Close Device -// Free videobuffer -// +/* + * Close Device + * Free videobuffer + */ int VideoDev::Close() { printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); @@ -716,9 +721,9 @@ int VideoDev::Close() { }; -// -// try to send ioctl command as long as EINTR is valid. But abort after 2 seconds. -// +/* + * try to send ioctl command as long as EINTR is valid. But abort after 2 seconds. + */ int VideoDev::xioctl(int fd, int request, void *arg) { int r; int errnoioctl; @@ -738,9 +743,9 @@ int VideoDev::xioctl(int fd, int request, void *arg) { }; -// -// converts the video from input type to RGB24 type - 24Bit -// +/* + * converts the video from input type to RGB24 type - 24Bit + */ int VideoDev::Convert (VideoFrame *dest, unsigned char *ptrsrc, int srcsize, uint32_t pixelformat, int srcw, int srch) { int xs, ys; int xd, yd; @@ -921,3 +926,9 @@ int VideoDev::Convert (VideoFrame *dest, unsigned char *ptrsrc, int srcsize, uin }; +list VideoDev::GetCtrlsMinMaxValue() { + return vidctrls; +}; + + +