diff --git a/CMakeLists.txt b/CMakeLists.txt index 6ee8acb..7aeec68 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,8 +10,12 @@ pkg_check_modules(GTKMM gtkmm-2.4>=2.4) pkg_check_modules(CAIROMM cairomm-1.0>=1.0) SET(SOURCES + src/config.cpp + src/config.h src/gui.cpp src/gui.h + src/inifile.cpp + src/inifile.h src/jack.cpp src/jack.h src/jsweeper.cpp diff --git a/src/config.cpp b/src/config.cpp new file mode 100644 index 0000000..0864b70 --- /dev/null +++ b/src/config.cpp @@ -0,0 +1,58 @@ +#include +#include +#include "glib.h" +#include "glib/gstdio.h" +#include "config.h" +#include "portmanager.h" + +#define PACKAGE_NAME "jsweeper" +#define CONFIG_FILENAME "jsweeper.ini" + +void Config::Read() +{ + std::string path = Glib::build_filename(Glib::get_user_config_dir(), PACKAGE_NAME); + g_mkdir_with_parents(path.c_str(), S_IRWXU | S_IRWXG | S_IRWXO); + m_filename = Glib::build_filename(path, CONFIG_FILENAME); + + ini.LoadFromDisk(m_filename); + + IniGroup *group = ini.GetGroup("gui"); + CellPadding = group->GetValue("cellpadding", 3); + FontSize = group->GetValue("fontsize", 10); + FontFace = group->GetValue("fontface", std::string("Sans")); + + ExpandClients = group->GetValue("expandclients", true); + ExpandGroups = group->GetValue("expandgroups", false); + + pm.AliasClear(); + + group = ini.GetGroup("aliases"); + IniItemList::iterator it; + for (it = group->items.begin(); it != group->items.end(); ++it) { + IniItem *item = *it; + pm.AliasAdd(item->name, item->value); + } +} + +void Config::Write() +{ + IniGroup *group = ini.GetGroup("gui"); + group->SetValue("cellpadding", CellPadding); + group->SetValue("fontsize", FontSize); + group->SetValue("fontface", FontFace); + + group->SetValue("expandclients", ExpandClients); + group->SetValue("expandgroups", ExpandGroups); + + ini.RemoveGroup("aliases"); + group = ini.GetGroup("aliases"); + + const AliasList &list = pm.AliasGetList(); + AliasList::const_iterator it; + for (it = list.begin(); it != list.end(); ++it) { + const Alias &a = *it; + group->SetValue(a.name, a.alias); + } + + ini.SaveToDisk(m_filename); +} diff --git a/src/config.h b/src/config.h new file mode 100644 index 0000000..5d6891d --- /dev/null +++ b/src/config.h @@ -0,0 +1,21 @@ +#include "inifile.h" + +class Config +{ +private: + IniFile ini; + std::string m_filename; + +public: + void Read(); + void Write(); + + int CellPadding; + int FontSize; + std::string FontFace; + + bool ExpandClients; + bool ExpandGroups; +}; + +extern Config cfg; diff --git a/src/gui.cpp b/src/gui.cpp index 2b56a14..afd6ad5 100644 --- a/src/gui.cpp +++ b/src/gui.cpp @@ -4,12 +4,13 @@ #include "jack.h" #include "portmanager.h" #include "gui.h" +#include "config.h" const Rect Rect::None = Rect(0, 0, -1, -1); Matrix::Matrix() : - m_client_width(0), m_client_height(0), m_port_width(0), m_port_height(0), m_separation(0), m_padding(3), - m_font_size(10), m_typeface("Liberation Sans Bold") + m_client_width(0), m_client_height(0), m_port_width(0), m_port_height(0), m_separation(0), m_padding(cfg.CellPadding), + m_font_size(cfg.FontSize), m_typeface(cfg.FontFace) { set_size_request(0, 0); show(); diff --git a/src/inifile.cpp b/src/inifile.cpp new file mode 100644 index 0000000..b84f407 --- /dev/null +++ b/src/inifile.cpp @@ -0,0 +1,181 @@ + +#include +#include +#include +#include "inifile.h" + +// trim from start +static inline std::string <rim(std::string &s) +{ + s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(std::isspace)))); + return s; +} + +// trim from end +static inline std::string &rtrim(std::string &s) +{ + s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun(std::isspace))).base(), s.end()); + return s; +} + +// trim from both ends +static inline std::string &trim(std::string &s) +{ + return ltrim(rtrim(s)); +} + + +IniItem::IniItem(std::string _name) +{ + name = _name; + value = ""; +} + +IniItem::IniItem(std::string _name, std::string _value) +{ + name = _name; + value = _value; +} + +void IniItem::SetValue(std::string _value) +{ + value = _value; +} + +IniGroup::IniGroup(std::string _name) +{ + name = _name; +} + +IniGroup::~IniGroup() +{ + IniItemList::iterator it; + for (it = items.begin(); it != items.end(); ++it) { + IniItem *item = *it; + delete item; + } +} + +IniItem *IniGroup::GetItem(std::string name) +{ + IniItemList::iterator it; + for (it = items.begin(); it != items.end(); ++it) { + IniItem *item = *it; + if (item->name == name) return item; + } + + items.push_back(new IniItem(name)); + return items.back(); +} + +IniItem *IniGroup::GetItem(std::string name, std::string default_value) +{ + IniItemList::iterator it; + for (it = items.begin(); it != items.end(); ++it) { + IniItem *item = *it; + if (item->name == name) return item; + } + + items.push_back(new IniItem(name, default_value)); + return items.back(); +} + +IniFile::~IniFile() +{ + IniGroupList::iterator it; + for (it = groups.begin(); it != groups.end(); ++it) { + IniGroup *group = *it; + delete group; + } +} + +IniGroup *IniFile::GetGroup(std::string name) +{ + IniGroupList::iterator it; + for (it = groups.begin(); it != groups.end(); ++it) { + IniGroup *group = *it; + if (group->name == name) return group; + } + + groups.push_back(new IniGroup(name)); + return groups.back(); +} + +void IniFile::RemoveGroup(std::string name) +{ + IniGroupList::iterator it; + for (it = groups.begin(); it != groups.end();) { + IniGroup *group = *it; + if (group->name == name) { + delete group; + it = groups.erase(it); + } else { + ++it; + } + } +} + +void IniFile::LoadFromDisk(std::string filename) +{ + // Clear all information first... + IniGroupList::iterator it; + for (it = groups.begin(); it != groups.end(); ++it) { + IniGroup *group = *it; + delete group; + } + + std::ifstream file; + file.open(filename.c_str()); + + IniGroup *group = NULL; + while (file.good()) { + char tmp[1024]; + file.getline(tmp, sizeof tmp); + std::string line = tmp; + + // Blank line + if (line.length() == 0) continue; + // Comment + if (line[0] == '#' || line[0] == ';') continue; + // Group header + if (line[0] == '[' && line[line.length() - 1] == ']') { + group = GetGroup(line.substr(1, line.length() - 2)); + } else { + if (group == NULL) continue; + + size_t loc = line.find('='); + if (loc != std::string::npos) { + std::string name = line.substr(0, loc); + std::string value = line.substr(loc + 1); + group->SetValue(trim(name), trim(value)); + } + } + } + + file.close(); +} + +void IniFile::SaveToDisk(std::string filename) +{ + std::ofstream file; + file.open(filename.c_str()); + + IniGroupList::iterator it; + for (it = groups.begin(); it != groups.end(); ++it) { + IniGroup *group = *it; + + file << std::endl; + file << "[" << group->name << "]" << std::endl; + + IniItemList::iterator it2; + for (it2 = group->items.begin(); it2 != group->items.end(); ++it2) { + IniItem *item = *it2; + + file << item->name << " = " << item->value << std::endl; + } + + file << std::endl; + } + + file.close(); +} diff --git a/src/inifile.h b/src/inifile.h new file mode 100644 index 0000000..aa5907a --- /dev/null +++ b/src/inifile.h @@ -0,0 +1,92 @@ +#ifndef INIFILE_H +#define INIFILE_H + +#include +#include +#include + +template +std::string ss_conv_from(T value) +{ + std::ostringstream temp_ss; + temp_ss << value; + return temp_ss.str(); +} + +template +T ss_conv_to(std::string value) +{ + std::istringstream temp_ss(value); + T tmp; + temp_ss >> tmp; + return tmp; +} + +struct IniItem +{ + std::string name; + std::string value; + + IniItem(std::string name); + IniItem(std::string name, std::string value); + + void SetValue(std::string value); +}; + +typedef std::list IniItemList; + +struct IniGroup +{ + std::string name; + IniItemList items; + + IniGroup(std::string name); + ~IniGroup(); + + IniItem *GetItem(std::string name); + IniItem *GetItem(std::string name, std::string default_value); + + std::string GetValue(std::string name, std::string default_value) + { + IniItem *item = GetItem(name, default_value); + return item->value; + } + + void SetValue(std::string name, std::string value) + { + IniItem *item = GetItem(name); + item->value = value; + } + + template + T GetValue(std::string name, T default_value) + { + std::string value = ss_conv_from(default_value); + IniItem *item = GetItem(name, value); + return ss_conv_to(item->value); + } + + template + void SetValue(std::string name, T value) + { + IniItem *item = GetItem(name); + item->value = ss_conv_from(value); + } +}; + +typedef std::list IniGroupList; + +struct IniFile +{ + IniGroupList groups; + + ~IniFile(); + + IniGroup *GetGroup(std::string name); + void RemoveGroup(std::string name); + + void LoadFromDisk(std::string filename); + void SaveToDisk(std::string filename); +}; + +#endif // INIFILE_H diff --git a/src/jsweeper.cpp b/src/jsweeper.cpp index 3d23da0..ad058e4 100644 --- a/src/jsweeper.cpp +++ b/src/jsweeper.cpp @@ -1,22 +1,28 @@ #include "jack.h" #include "portmanager.h" #include "gui.h" +#include "config.h" PortManager pm; JackDriver jack; +Config cfg; int main(int argc, char **argv) { Gtk::Main kit(argc, argv); - pm.AliasLoad("hurr.jsa"); + cfg.Read(); + +// pm.AliasLoad("hurr.jsa"); jack.Connect(); Gui *g = new Gui(); kit.run(*g); - delete g; + jack.Disconnect(); + + cfg.Write(); return 0; } diff --git a/src/portmanager.cpp b/src/portmanager.cpp index a514994..37ca217 100644 --- a/src/portmanager.cpp +++ b/src/portmanager.cpp @@ -3,6 +3,7 @@ #include #include "jack.h" #include "portmanager.h" +#include "config.h" void PortManager::Add(jack_port_t *port) { @@ -150,7 +151,7 @@ Client *PortManager::FindOrMakeClient(std::string name, bool is_input, bool is_m c->m_name = name; c->m_is_input = is_input; c->m_is_midi = is_midi; - c->m_expanded = true; + c->m_expanded = cfg.ExpandClients; m_clients.push_back(c); @@ -168,7 +169,7 @@ PortGroup *PortManager::FindOrMakeGroup(Client *client, JackPortFlags flags, std PortGroup *pg = new PortGroup(); pg->m_name = name; pg->m_flags = flags; - pg->m_expanded = false; + pg->m_expanded = cfg.ExpandGroups; client->m_groups.push_back(pg); @@ -306,6 +307,20 @@ void PortManager::AliasBay(jack_port_t *port, int num_aliases, char *aliases[2]) } } +void PortManager::AliasClear() +{ + m_aliases.clear(); +} + +void PortManager::AliasAdd(std::string source, std::string target) +{ + Alias a; + a.name = source; + a.alias = target; + m_aliases.push_back(a); +} + +/* void PortManager::AliasLoad(std::string filename) { std::ifstream file; @@ -321,3 +336,4 @@ void PortManager::AliasLoad(std::string filename) m_aliases.push_back(a); } } +*/ diff --git a/src/portmanager.h b/src/portmanager.h index e7cc9f7..57f39af 100644 --- a/src/portmanager.h +++ b/src/portmanager.h @@ -38,7 +38,10 @@ public: void ToggleConnect(PortGroup *a, PortGroup *b); void AliasBay(jack_port_t *port, int num_aliases, char *aliases[2]); - void AliasLoad(std::string filename); + void AliasClear(); + void AliasAdd(std::string source, std::string target); + + const AliasList &AliasGetList() const { return m_aliases; } }; extern PortManager pm;