diff --git a/configuration.cc b/configuration.cc new file mode 100644 index 0000000..f34b0f8 --- /dev/null +++ b/configuration.cc @@ -0,0 +1,196 @@ + +#include "configuration.h" +#include "video.h" +#include "gui.h" + +#include + +extern VideoDev videodev; +extern GtkBuilder *_builder_; // work around for threads + + +Configuration::Configuration() { +}; + + +Configuration::~Configuration() { +}; + + +std::string Configuration::GetDefaultFileName() { + std::string fn = ""; + char *hd = NULL; + + if ((hd = getenv ("HOME")) == NULL) { + // no homedir defined? + return ""; + } + fn = hd; + fn = fn + "/" + CONFIGURATION_DEFAULTFILE; + + return fn; +}; + + +void Configuration::SaveDefault() { + std::string fn = GetDefaultFileName(); + if (fn.length() < 1) { + printf ("%s:%d %s could not read HOME environment variable\n", __FILE__, __LINE__, __FUNCTION__); + return; + } + SaveConfig (fn); +}; + + +void Configuration::LoadDefault() { + std::string fn = GetDefaultFileName(); + if (fn.length() < 1) { + printf ("%s:%d %s could not read HOME environment variable\n", __FILE__, __LINE__, __FUNCTION__); + return; + } + LoadConfig (fn); +}; + + +/* + * collect all the settings, and push them into the JSONparse object + * save the json string. + */ +void Configuration::SaveConfig(std::string filename) { + JSONParse jp; + string vstr; + int i; + GtkWidget *cb; + GtkWidget *cbe; + + // + // Add resolution, format and video device to config json element + cb = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "cb-videores")); + cbe = gtk_bin_get_child(GTK_BIN(cb)); + jp.AddObject("video_resolution", (string) gtk_entry_get_text(GTK_ENTRY(cbe))); + cb = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "cb-videofmt")); + cbe = gtk_bin_get_child(GTK_BIN(cb)); + jp.AddObject("video_format", (string) gtk_entry_get_text(GTK_ENTRY(cbe))); + jp.AddObject("device", videodev.GetDevice()); + + // + // save button config + for (i = 0; i < BTN_PRESET_MAX; i++) { + JSONElement je; + je.type = JSON_T_ARRAY; + je.name = "presetbtn"+ std::to_string(i); + list::iterator vciter; + JSONParse jpbtn; + jpbtn.Clear(); + + // convert VideoDevCtrl to JSON + for (vciter = presetbtn[i].begin(); vciter != presetbtn[i].end(); vciter++) { + jpbtn.Clear(); + jpbtn.AddObject("name", vciter->name); + jpbtn.AddObject("id", (signed int) vciter->id); + jpbtn.AddObject("max", vciter->max); + jpbtn.AddObject("min", vciter->min); + jpbtn.AddObject("value", vciter->value); + + if (je.value.length()>0) je.value += "," + jpbtn.ToString(); + else je.value = jpbtn.ToString(); + } + jp.AddObject(je); + } + + // + // save config + if (jp.SaveToFile(filename)) { + printf ("%s:%d %s could not save to file [%s] Error: %s\n", __FILE__, __LINE__, __FUNCTION__, + filename.c_str(), strerror(errno)); + } +}; + + +void Configuration::LoadConfig(std::string filename) { + JSONParse jp; + string vstr; + float vf; + int vi; + int i; + JSONElement je; + + if (jp.LoadFromFile(filename)) { + printf ("%s:%d %s could not load from file [%s] Error: %s\n", __FILE__, __LINE__, __FUNCTION__, + filename.c_str(), strerror(errno)); + } + else { + printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); + // config in jp loaded, setup all the GUI fields + + // + // set resolution and video stream mode + // + if (jp.GetValue("video_resolution", &vstr)) { + GtkWidget *cbox = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "cb-videores")); + GtkWidget *cbdevice = gtk_bin_get_child(GTK_BIN(cbox)); + gtk_entry_set_text(GTK_ENTRY(cbdevice), vstr.c_str()); + } + if (jp.GetValue("video_format", &vstr)) { + GtkWidget *cbox = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "cb-videofmt")); + GtkWidget *cbdevice = gtk_bin_get_child(GTK_BIN(cbox)); + gtk_entry_set_text(GTK_ENTRY(cbdevice), vstr.c_str()); + } + + + // + // start streaming if a device was selected. + // + if (jp.GetValue("device", &vstr)) { + GtkWidget *cbox = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "cb-videodev")); + GtkWidget *cbdevice = gtk_bin_get_child(GTK_BIN(cbox)); + gtk_entry_set_text(GTK_ENTRY(cbdevice), vstr.c_str()); + cb_video_btnrec (NULL, NULL); + } + + // + // load the button config + // + for (i = 0; i < BTN_PRESET_MAX; i++) { + VideoDevCtrl ctrl; + JSONParse jpbtn, jpctrl; + list je; + list::iterator iter; + int ctrli; + long int id; + + // + // load all controls from JSONParse object + presetbtn[i].clear(); + ctrli = 0; + while (jp.GetObjectIdx("presetbtn"+ std::to_string(i), ctrli, &jpctrl)) { + jpctrl.GetValue("name", &ctrl.name); + jpctrl.GetValueInt64("id", &id); + ctrl.id = id; + jpctrl.GetValueInt("min", &ctrl.min); + jpctrl.GetValueInt("max", &ctrl.max); + jpctrl.GetValueInt("value", &ctrl.value); + presetbtn[i].push_back(ctrl); + ctrli++; + } + } + } +}; + + +/* + * presetbtn[btn] + */ +void Configuration::SetPresetButton (int btn, list *parameters) { + if (btn < 0 || btn >= BTN_PRESET_MAX) return; + presetbtn[btn] = *parameters; +}; + + +list Configuration::GetPresetButton (int btn) { + list emptylist; + if (btn >= 0 && btn < BTN_PRESET_MAX) return presetbtn[btn]; + return emptylist; +}; + + diff --git a/configuration.h b/configuration.h new file mode 100644 index 0000000..ebfda6c --- /dev/null +++ b/configuration.h @@ -0,0 +1,36 @@ + +#ifndef _CONFIGURATION_H_ +#define _CONFIGURATION_H_ + +/* + * all read and saved data will have to be in a + */ + +#include +#include +#include "video.h" +#include "json.h" + +#define CONFIGURATION_DEFAULTFILE ".simpleskycam.config" +#define BTN_PRESET_MAX 4 // number of preset buttons + +class Configuration { +private: + JSONParse config; + std::string GetDefaultFileName(); + list presetbtn[BTN_PRESET_MAX]; +public: + Configuration(); + ~Configuration(); + + void LoadDefault(); + void SaveDefault(); + + void LoadConfig(std::string filename); + void SaveConfig(std::string filename); + + void SetPresetButton (int btn, list *parameters); + list GetPresetButton (int btn); +}; + +#endif diff --git a/json.cc b/json.cc new file mode 100644 index 0000000..25c37cd --- /dev/null +++ b/json.cc @@ -0,0 +1,528 @@ + +#include +#include +#include +#include +#include + +#include "json.h" + +/*********************************************************************** + *********************************************************************** + * + * JSONParse + * + *********************************************************************** + *********************************************************************** + */ + +enum { + STEP_NONE = 0, + STEP_STARTNAME, + STEP_NAME, + STEP_STARTVALUE, + STEP_VALUE, + STEP_END +}; + + +/* + * clear out all data + */ +void JSONParse::Clear() { + jsondata = ""; + names.clear(); +} + +/* + * read every element and keep only this in memory. + */ +int JSONParse::Set(string json) { + int i; + int step; + int level; + bool ignorenext; + + JSONElement jelement; + + Clear(); + + // find start and read until end + for (step = STEP_NONE, i = 0, ignorenext = false; i < json.length(); i++) { + // need to copy next character +// debug (0, "JSONParse: step:%d i:%d name:'%s' value:'%s'", step, i, jelement.name.c_str(), jelement.value.c_str()); + if (ignorenext) { + ignorenext = false; + if (step == STEP_NAME) jelement.name += json[i]; + if (step == STEP_VALUE) jelement.value += json[i]; + } + + // searching for startname + else if (step == STEP_NONE) { + if (json[i] == '{') { + step = STEP_STARTNAME; + continue; + } + } + + // searching for startname + else if (step == STEP_STARTNAME) { + if (json[i] == '"') { + step = STEP_NAME; + continue; + } + } + + // copy name + else if (step == STEP_NAME) { + if (json[i] == '"') { + step = STEP_STARTVALUE; + continue; + } + else { + jelement.name += json[i]; + continue; + } + } + + // searching for startvalue + else if (step == STEP_STARTVALUE) { + if (json[i] == '"') { + step = STEP_VALUE; + jelement.type = JSON_T_STRING; + continue; + } + if (json[i] == '{') { + step = STEP_VALUE; + level = 0; + jelement.type = JSON_T_OBJECT; + jelement.value = "{"; + continue; + } + if (json[i] == '[') { + step = STEP_VALUE; + level = 0; + jelement.type = JSON_T_ARRAY; + jelement.value = "["; + continue; + } + if ((json[i] >= '0' && json[i] <= '9') || + (json[i] == '+' || json[i] == '-')) { + step = STEP_VALUE; + level = 0; + jelement.type = JSON_T_NUMBER; + jelement.value = json[i]; + continue; + } + } + + // copy value + else if (step == STEP_VALUE) { + if (jelement.type == JSON_T_STRING) { + if (json[i] == '"') step = STEP_END; + else jelement.value += json[i]; + continue; + } + else if (jelement.type == JSON_T_OBJECT) { + if (json[i] == '}' && level == 0) { + jelement.value += json[i]; + step = STEP_END; + } + else { + if (json[i] == '{') level++; // increase level + if (json[i] == '}') level--; // decrease level + jelement.value += json[i]; + } + continue; + } + else if (jelement.type == JSON_T_ARRAY) { + if (json[i] == ']' && level == 0) { + jelement.value += json[i]; + step = STEP_END; + } + else { + if (json[i] == '[') level++; // increase level + if (json[i] == ']') level--; // decrease level + jelement.value += json[i]; + } + continue; + } + else if (jelement.type == JSON_T_NUMBER) { + if ((json[i] < '0' || json[i] > '9') && json[i] != '.' && + json[i] != '+' && json[i] != 'e' && json[i] != 'E') step = STEP_END; + else { + jelement.value += json[i]; + continue; + } + } + } + + // another element? + if (step == STEP_END) { + if (json[i] == ',') { +// debug (0, "* JSON.Set Add name:%s", jelement.name.c_str()); + if (jelement.type != JSON_T_NONE) { +// debug (0, "%s:%d json add element type:%d", __FILE__, __LINE__, jelement.type); + names.push_back (jelement); + } + jelement.Clear(); + step = STEP_STARTNAME; + } + continue; + } + } +// debug (0, "* JSON.Set Add name:%s", jelement.name.c_str()); + if (jelement.type != JSON_T_NONE) { +// debug (0, "%s:%d json add element type:%d", __FILE__, __LINE__, jelement.type); + names.push_back (jelement); + } + + return 0; +}; + + +int JSONParse::GetValue(string varname, string *dest) { + list::iterator iter; + + if (dest == NULL) return 0; + *dest = ""; + + for (iter = names.begin(); iter != names.end(); iter++) { + if (varname.compare(iter->name) == 0) { + *dest = iter->value; + return 1; + } + } + + return 0; +}; + + +int JSONParse::GetValueInt(string varname, int *dest) { + string s; + int res = GetValue(varname, &s); + if (res) { + *dest = atoi (s.c_str()); + return 1; + } + return 0; +}; + + +int JSONParse::GetValueInt64(string varname, int64_t *dest) { + string s; + int res = GetValue(varname, &s); + if (res) { + *dest = atol (s.c_str()); + return 1; + } + return 0; +}; + + +int JSONParse::GetObject(string varname, JSONParse *dest) { + list::iterator iter; + + if (dest == NULL) return 0; + + for (iter = names.begin(); iter != names.end(); iter++) { + if (varname.compare(iter->name) == 0) { + dest->Set(iter->value); + return 1; + } + } + + return 0; +}; + + +#define MAXRECURSIVE 255 +int JSONParse::GetIdx(string src, int idx, string *dest) { + char recursive[MAXRECURSIVE]; + int i = 0, rcnt = 0, cnt = 0; + + (*dest) = ""; +// printf("\n***************************************idx:%d\n", idx); + + for (i = 0; i < MAXRECURSIVE; i++) recursive[i] = 0; + for (i = 0; i < src.length() && rcnt < MAXRECURSIVE && cnt <= idx; i++) { +// printf ("i:%d rcnt:%d['%c'] cnt:%d char:'%c' ous:'%s'\n", +// i, rcnt, recursive[rcnt], cnt, src[i], dest->c_str()); + if (src[i] == '[') { + recursive[rcnt++] = src[i]; + continue; + } + else if (src[i] == '{' && recursive[rcnt] != '"') recursive[++rcnt] = src[i]; + else if (src[i] == '}' && recursive[rcnt] == '{') rcnt--; + else if (src[i] == '"' && recursive[rcnt] == '"') rcnt--; + else if (src[i] == '"') recursive[++rcnt] = src[i]; + else if (src[i] == ',' && rcnt == 1) { + cnt++; + continue; + } + else if (src[i] == ']' && rcnt == 1) { + continue; + } + + if (rcnt > 0 && cnt == idx) { + (*dest) += src[i]; + if (src[i] == '\\') (*dest) += src[i]; + } + else { + if (src[i] == '\\')i++; + } + } + +// printf("\n***************************************idx:%d cnt:%d\n", idx, cnt); +// printf("in:'%s'\n***\nout:'%s'\n\n*****\n", src.c_str(), dest->c_str()); + + // + // final checks + if (cnt == 0 && idx == 0 && // empty source/array? + dest->size() == 0) return 0; // + if (cnt >= idx) return 1; // found the right element + return 0; // element not found +} +#undef MAXRECURSIVE + +int JSONParse::GetValueIdx(string varname, int idx, string *dest) { + list::iterator iter; + + if (dest == NULL) return 0; + + for (iter = names.begin(); iter != names.end(); iter++) { + if (varname.compare(iter->name) == 0) { + return GetIdx(iter->value, idx, dest); + } + } + + return 0; +}; + +int JSONParse::GetObjectIdx(string varname, int idx, JSONParse *dest) { + list::iterator iter; + string deststr; + int ret = 0; + + if (dest == NULL) return 0; + + for (iter = names.begin(); iter != names.end(); iter++) { + if (varname.compare(iter->name) == 0) { + ret = GetIdx(iter->value, idx, &deststr); + if (ret == 1) dest->Set(deststr); + return ret; + } + } + + return 0; +}; + +list JSONParse::GetElements() { + list l; + list::iterator iter; + + l.clear(); + for (iter = names.begin(); iter != names.end(); iter++) { + l.push_back(*iter); + } + + return l; +}; + + +void JSONParse::AddObject (JSONElement element) { + names.push_back (element); +}; + + +void JSONParse::AddObject (string name, JSONParse jp) { + JSONElement je; + je.SetObject(name, jp.ToString()); + names.push_back(je); +}; + + +void JSONParse::AddObject (string name, int val) { + JSONElement je; + je.Set(name, val); + names.push_back(je); +}; + + +void JSONParse::AddObject (string name, int64_t val) { + JSONElement je; + je.Set(name, val); + names.push_back(je); +}; + + +void JSONParse::AddObject (string name, string val) { + JSONElement je; + je.Set(name, val); + names.push_back(je); +}; + + +void JSONParse::AddObject (string name, double val) { + JSONElement je; + je.Set(name, val); + names.push_back(je); +}; + + +string JSONParse::ToString() { + list::iterator iter; + string output; + int level, i; + + output = "{"; + + for (level = 1, iter = names.begin(); iter != names.end(); iter++) { + if (iter != names.begin()) output += ","; + output += "\n"; + for (i = 0; i < 4*level; i++) output += " "; + output += iter->GetString(); + } + + output += "\n}\n"; + + return output; +}; + + + +/* + * Load/Save elements to a file. + * Return Value: -1 .. on Error, errno will be set + * 0 .. on Success + */ +int JSONParse::LoadFromFile(string filename) { + ifstream in(filename); + string tmp, input; + + if (!in) return -1; + + input = ""; + while (!in.eof()) { + if (input.length() > 0) input += ("\n" + tmp); + else input = tmp; + in >> tmp; + } + Set(input); + + in.close(); + + return 0; +}; + +int JSONParse::SaveToFile(string filename) { + ofstream out(filename); + + if (!out) return -1; + + out << ToString(); + out.close(); + + return 0; +}; + + + + +/*********************************************************************** + *********************************************************************** + * + * JSONElement + * + *********************************************************************** + *********************************************************************** + */ + + +void JSONElement::Set (string n, double v) { + name = n; + value = to_string(v); + type = JSON_T_NUMBER; +}; + + +void JSONElement::Set (string n, int v) { + name = n; + value = to_string(v); + type = JSON_T_NUMBER; +}; + + +void JSONElement::Set (string n, int64_t v) { + name = n; + value = to_string(v); + type = JSON_T_NUMBER; +}; + + +void JSONElement::Set (string n, string v) { + name = n; + value = v; + type = JSON_T_STRING; +}; + + +void JSONElement::SetArray (string n, list *l) { + list::iterator iter; + + name = n; + value = "["; + type = JSON_T_STRING; + + for (iter = l->begin(); iter != l->end(); iter++) { + if (iter != l->begin()) value += ","; + value += iter->GetString(); + } + value += "]"; +}; + + +void JSONElement::SetObject (string n, string s) { + name = n; + value = s; + type = JSON_T_OBJECT; +}; + + +string JSONElement::GetString () { + string output = ""; + string filename = __FILE__; + + switch (type) { + case(JSON_T_NUMBER): + output += "\"" + name + "\" : " + value; + break; + case(JSON_T_STRING): + if (value.length()==0) { + output += "\"" + name + "\" : \"\""; + } + else if (value[0] != '"') { + output += "\"" + name + "\" : \"" + value + "\""; + } + else output += "\"" + name + "\" : " + value; + break; + case(JSON_T_OBJECT): + output += "\"" + name + "\" : " + value; + break; + case(JSON_T_ARRAY): + if (value.length()==0) { + output += "\"" + name + "\" : []"; + } + else if (value[0] != '[') { + output += "\"" + name + "\" : [" + value + "]"; + } + else output += "\"" + name + "\" : " + value; + break; + default: + output += "\"error\" : \""+ filename + ":" + to_string(__LINE__) + " JSONElement unknown type error\"("+to_string(type)+")"; + break; + } + + return output; +}; + diff --git a/json.h b/json.h new file mode 100644 index 0000000..a235a32 --- /dev/null +++ b/json.h @@ -0,0 +1,79 @@ + +// +// +// + +#ifndef _JSON_H_ +#define _JSON_H_ + +#include +#include +#include + +using namespace std; + +enum { + JSON_T_NONE, + JSON_T_STRING, + JSON_T_NUMBER, + JSON_T_OBJECT, + JSON_T_ARRAY +}; + +class JSONElement { +public: + int type; + string name; + string value; + + JSONElement() { Clear(); }; + ~JSONElement() {}; + + void Clear() { type = JSON_T_NONE; name = ""; value = ""; }; + void Set (string n, double v); + void Set (string n, int v); + void Set (string n, int64_t v); + void Set (string n, string v); + void SetArray (string n, list *l); + void SetObject (string n, string s); + string GetString(); +}; + +class JSONParse { +private: + string jsondata; + list names; + +public: + JSONParse() { Set("{}"); }; + JSONParse(string json) { Set(json); }; + ~JSONParse() {}; + + void Clear(); + int Set(string json); + + int GetValue(string varname, string *dest); + int GetValueInt(string varname, int *dest); + int GetValueInt64(string varname, int64_t *dest); + int GetObject(string varname, JSONParse *dest); + + int GetIdx(string src, int idx, string *dest); + int GetValueIdx(string varname, int idx, string *dest); + int GetObjectIdx(string varname, int idx, JSONParse *dest); + + list GetElements(); + + void AddObject (JSONElement element); + void AddObject (string name, int val); + void AddObject (string name, int64_t val); + void AddObject (string name, string val); + void AddObject (string name, double val); + void AddObject (string name, JSONParse jp); + + int LoadFromFile(string filename); + int SaveToFile(string filename); + + string ToString(); +}; + +#endif // _JSON_H_