diff --git a/.obs-manager.hpp.kate-swp b/.obs-manager.hpp.kate-swp deleted file mode 100644 index fd3ae3f..0000000 Binary files a/.obs-manager.hpp.kate-swp and /dev/null differ diff --git a/Makefile b/Makefile index fc02f7c..9d926dc 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,12 @@ CC = g++ CFLAGS = -g -Wall -std=c++17 -GCFLAGS = `pkg-config --cflags --libs gtkmm-3.0` -lobs +GCFLAGS = `pkg-config --cflags --libs gtkmm-3.0` -lobs -lv4l2 +OBJFILES = main.o obs-manager.o recording-window.o settings-manager.o settings-window.o TARGET = screenrecorder -$(TARGET): main.o obs-manager.o recording-window.o settings-window.o - $(CC) $(CFLAGS) -o $(TARGET) main.o obs-manager.o recording-window.o settings-window.o $(GCFLAGS) +$(TARGET): $(OBJFILES) + $(CC) $(CFLAGS) -o $(TARGET) $(OBJFILES) $(GCFLAGS) main.o: $(CC) $(CFLAGS) -c main.cpp $(GCFLAGS) @@ -16,8 +17,11 @@ obs-manager.o: obs-manager.cpp obs-manager.hpp recording-window.o: recording-window.cpp recording-window.hpp $(CC) $(CFLAGS) -c recording-window.cpp $(GCFLAGS) +settings-manager.o: settings-manager.cpp settings-manager.hpp + $(CC) $(CFLAGS) -c settings-manager.cpp $(GCFLAGS) + settings-window.o: settings-window.cpp settings-window.hpp $(CC) $(CFLAGS) -c settings-window.cpp $(GCFLAGS) clean: - rm $(TARGET) main.o obs-manager.o recording-window.o settings-window.o + rm $(TARGET) $(OBJFILES) diff --git a/README.md b/README.md index c511cbe..963dd29 100644 --- a/README.md +++ b/README.md @@ -2,4 +2,4 @@ ## Dependencies -`apt install libobs-dev libgtkmm-3.0-dev` +`apt install libobs-dev libgtkmm-3.0-dev libv4l-dev` diff --git a/config.cfg b/config.cfg new file mode 100644 index 0000000..faf4905 --- /dev/null +++ b/config.cfg @@ -0,0 +1,6 @@ +outputdir=/home/parallels/Projects/Progrium/screen-recorder +pluginsdir=/usr/lib/x86_64-linux-gnu/obs-plugins/ +desktopenabled=true +videoenabled=true +videodevice=/dev/video3 +audioenabled=false diff --git a/obs-manager.cpp b/obs-manager.cpp index fa4d4d8..3b9a9fe 100644 --- a/obs-manager.cpp +++ b/obs-manager.cpp @@ -1,6 +1,8 @@ #include "obs-manager.hpp" +#include "settings-manager.hpp" #include #include +#include #include using namespace Glib; @@ -45,9 +47,19 @@ void OBSManager::Initialize() throw std::runtime_error("Failed to create display"); } -ustring OBSManager::GetPluginDir() +void OBSManager::LoadSettings(SettingsManager *settings) { - return pluginDir; + string pluginsDir = settings->Get("pluginsdir"); + if (pluginsDir == "") + pluginsDir = "/usr/lib/x86_64-linux-gnu/obs-plugins/"; + + PluginsDir = pluginsDir; + + string outputDir = settings->Get("outputdir"); + if (outputDir == "") + outputDir = std::filesystem::current_path(); + + OutputDir = outputDir; } void OBSManager::loadPlugin(ustring name) @@ -55,7 +67,7 @@ void OBSManager::loadPlugin(ustring name) obs_module_t *module; ustring path; - path.append(pluginDir); + path.append(PluginsDir); path.append(name); int res = obs_open_module(&module, path.c_str(), nullptr); diff --git a/obs-manager.hpp b/obs-manager.hpp index fbcb6e6..2c0c69a 100644 --- a/obs-manager.hpp +++ b/obs-manager.hpp @@ -1,6 +1,7 @@ #ifndef SCREEN_RECORDER_OBS_MANAGER_HPP #define SCREEN_RECORDER_OBS_MANAGER_HPP +#include "settings-manager.hpp" #include #include #include @@ -15,15 +16,16 @@ public: ustring GetVersion(); void Initialize(); void Cleanup(); - ustring GetPluginDir(); + void LoadSettings(SettingsManager *settings); + std::string PluginsDir; + std::string OutputDir; private: - ustring pluginDir = "/usr/lib/x86_64-linux-gnu/obs-plugins/"; - std::list plugins; - bool isInitialized = false; obs_display_t *display = nullptr; + // Plugins + std::list plugins; void loadPlugin(ustring name); void loadPlugins(); }; diff --git a/recording-window.cpp b/recording-window.cpp index fb57f52..dffdb8a 100644 --- a/recording-window.cpp +++ b/recording-window.cpp @@ -1,5 +1,6 @@ #include "recording-window.hpp" #include "obs-manager.hpp" +#include "settings-manager.hpp" #include #include @@ -34,8 +35,10 @@ RecordingWindow::RecordingWindow(OBSManager *obs) string version; version.append("OBS Version: "); version.append(obs->GetVersion()); - mLabelVersion.set_text(version); + + auto settings = new SettingsManager(); + obs->LoadSettings(settings); } RecordingWindow::~RecordingWindow() diff --git a/recording-window.hpp b/recording-window.hpp index 594ef06..ebf6d05 100644 --- a/recording-window.hpp +++ b/recording-window.hpp @@ -10,7 +10,7 @@ class RecordingWindow : public Gtk::Window public: RecordingWindow(OBSManager *obs); virtual ~RecordingWindow(); -protected: +private: void onStartClicked(); void onSettingsClicked(); Gtk::Box mBoxMain; diff --git a/screenrecorder b/screenrecorder deleted file mode 100755 index f886fcb..0000000 Binary files a/screenrecorder and /dev/null differ diff --git a/settings-manager.cpp b/settings-manager.cpp new file mode 100644 index 0000000..652ec56 --- /dev/null +++ b/settings-manager.cpp @@ -0,0 +1,108 @@ +#include "settings-manager.hpp" +#include +#include + +using namespace std; + +SettingsManager::SettingsManager() +{ + settings = list(); + readAll(); +} + +SettingsManager::~SettingsManager() +{ +} + +void SettingsManager::Update(string key, string value) +{ + cout << "Update: key: " << key << "; value: " << value << endl; + for (auto entry : settings) + { + if (entry->key == key) + { + entry->value = value; + return; + } + } + + settings.push_back(new SettingsEntry{ + .key = key, + .value = value, + }); +} + +void SettingsManager::UpdateBool(string key, bool value) +{ + if (value) + Update(key, "true"); + else + Update(key, "false"); +} + +void SettingsManager::Save(string key, string value) +{ + Update(key, value); + SaveAll(); +} + +void SettingsManager::SaveAll() +{ + saveAll(); +} + +string SettingsManager::Get(string key) +{ + for (auto entry : settings) + { + if (entry->key == key) + { + return entry->value; + } + } + + return ""; +} + +bool SettingsManager::GetBool(string key) +{ + if (Get(key) == "true") + return true; + + return false; +} + +void SettingsManager::readAll() +{ + settings.clear(); + + ifstream fin; + string line; + fin.open("./config.cfg", ios::in); + + while (getline(fin, line)) + { + if (line.find("=") != -1) + { + settings.push_back(new SettingsEntry{ + .key = line.substr(0, line.find("=")), + .value = line.substr(line.find("=")+1, line.length()), + }); + } + } +} + +void SettingsManager::saveAll() +{ + ofstream fout; + fout.open("./config.cfg", ios::trunc); + + for (auto entry : settings) + { + cout << "Saving: key: " << entry->key << "; value: " << entry->value << endl; + fout << entry->key << "=" << entry->value << endl; + } +} + + + diff --git a/settings-manager.hpp b/settings-manager.hpp new file mode 100644 index 0000000..2db1a34 --- /dev/null +++ b/settings-manager.hpp @@ -0,0 +1,33 @@ +#ifndef SCREEN_RECORDER_SETTINGS_MANAGER_HPP +#define SCREEN_RECORDER_SETTINGS_MANAGER_HPP + +#include +#include + +using namespace std; + +class SettingsEntry +{ +public: + string key; + string value; +}; + +class SettingsManager +{ +public: + SettingsManager(); + virtual ~SettingsManager(); + void Update(string key, string value); + void UpdateBool(string key, bool value); + void Save(string key, string value); + void SaveAll(); + string Get(string key); + bool GetBool(string key); +private: + list settings; + void readAll(); + void saveAll(); +}; + +#endif diff --git a/settings-window.cpp b/settings-window.cpp index 319acd3..f71353d 100644 --- a/settings-window.cpp +++ b/settings-window.cpp @@ -1,4 +1,12 @@ #include "settings-window.hpp" +#include "settings-manager.hpp" +#include +#include +#include +#include +#include +#include +using namespace std; SettingsWindow::SettingsWindow(OBSManager* obs) : mBox(Gtk::Orientation::ORIENTATION_VERTICAL, 2), @@ -7,6 +15,10 @@ SettingsWindow::SettingsWindow(OBSManager* obs) mLabelPluginDir("Plugin Dir: "), mBoxOutputDir(Gtk::Orientation::ORIENTATION_HORIZONTAL, 2), mLabelOutputDir("Saved Files Dir: "), + mCheckButtonDesktop("Enable desktop recording"), + mBoxWebcam(Gtk::Orientation::ORIENTATION_VERTICAL, 2), + mCheckButtonWebcam("Enable webcam recording"), + mCheckButtonAudio("Enable audio recording"), mButtonClose("Close"), mButtonSave("Save") { @@ -16,6 +28,11 @@ SettingsWindow::SettingsWindow(OBSManager* obs) set_modal(true); set_type_hint(Gdk::WindowTypeHint::WINDOW_TYPE_HINT_DIALOG); + settings = new SettingsManager(); + obs->LoadSettings(settings); + + populateVideoDevices(); + signal_key_press_event().connect( sigc::mem_fun(*this, &SettingsWindow::onKeyPressed)); @@ -27,27 +44,52 @@ SettingsWindow::SettingsWindow(OBSManager* obs) mBoxSettings.set_border_width(10); mEntryPluginDir.set_hexpand(true); - mEntryPluginDir.set_text(obs->GetPluginDir().c_str()); + mEntryPluginDir.set_text(obs->PluginsDir.c_str()); mBoxPluginDir.set_border_width(10); mBoxPluginDir.add(mLabelPluginDir); mBoxPluginDir.add(mEntryPluginDir); mEntryOutputDir.set_hexpand(true); + mEntryOutputDir.set_text(obs->OutputDir.c_str()); mBoxOutputDir.set_border_width(10); mBoxOutputDir.add(mLabelOutputDir); mBoxOutputDir.add(mEntryOutputDir); + mFrameDesktop.set_label("Desktop"); + mFrameDesktop.set_border_width(10); + mCheckButtonDesktop.set_border_width(10); + mCheckButtonDesktop.set_active(settings->GetBool("desktopenabled")); + mFrameDesktop.add(mCheckButtonDesktop); + + mComboBoxVideoDevice.set_border_width(10); + mFrameWebcam.set_label("Webcam"); + mFrameWebcam.set_border_width(10); + mBoxWebcam.set_border_width(10); + mCheckButtonWebcam.set_active(settings->GetBool("videoenabled")); + mBoxWebcam.add(mCheckButtonWebcam); + mBoxWebcam.add(mComboBoxVideoDevice); + mFrameWebcam.add(mBoxWebcam); + + mFrameAudio.set_label("Microphone"); + mFrameAudio.set_border_width(10); + mCheckButtonAudio.set_border_width(10); + mCheckButtonAudio.set_active(settings->GetBool("audioenabled")); + mFrameAudio.add(mCheckButtonAudio); + mBoxSettings.add(mBoxPluginDir); mBoxSettings.add(mBoxOutputDir); + mBoxSettings.add(mFrameDesktop); + mBoxSettings.add(mFrameWebcam); + mBoxSettings.add(mFrameAudio); mFrameSettings.set_label("Settings"); mFrameSettings.set_border_width(10); mFrameSettings.add(mBoxSettings); - mActionBar.pack_end(mButtonClose); mActionBar.pack_end(mButtonSave); + mActionBar.pack_end(mButtonClose); mBox.add(mFrameSettings); mBox.add(mActionBar); @@ -78,5 +120,58 @@ void SettingsWindow::onClosePressed() void SettingsWindow::onSavePressed() { + settings->Update("pluginsdir", mEntryPluginDir.get_text()); + settings->Update("outputdir", mEntryOutputDir.get_text()); + settings->UpdateBool("desktopenabled", mCheckButtonDesktop.get_active()); + settings->UpdateBool("videoenabled", mCheckButtonWebcam.get_active()); + settings->Update("videodevice", mComboBoxVideoDevice.get_active_id()); + settings->UpdateBool("audioenabled", mCheckButtonAudio.get_active()); + settings->SaveAll(); +} + +void SettingsWindow::populateVideoDevices() +{ + auto settings = new SettingsManager(); + struct v4l2_capability cap; + struct dirent *dp; + + auto dirp = opendir("/sys/class/video4linux"); + if (!dirp) + throw runtime_error("Failed to get video devices"); + + while ((dp = readdir(dirp)) != nullptr) + { + int fd; + if (dp->d_type == DT_DIR) + continue; + + auto name = string(dp->d_name); + if (name.find("video") == -1) + continue; + + auto device = "/dev/" + name; + + if ((fd = v4l2_open(device.c_str(), O_RDWR | O_NONBLOCK)) == -1) + { + cout << "Failed to open device: " << device << endl; + continue; + } + + if (v4l2_ioctl(fd, VIDIOC_QUERYCAP, &cap) == -1) + { + cout << "Failed to query device: " << device << endl; + v4l2_close(fd); + continue; + } + + auto n = string(reinterpret_cast(cap.card)); + n += " (" + device + ")"; + + mComboBoxVideoDevice.append(device, n); + if (settings->Get("videodevice") == device) + mComboBoxVideoDevice.set_active_id(device); + + v4l2_close(fd); + } } diff --git a/settings-window.hpp b/settings-window.hpp index fff2e4e..7533222 100644 --- a/settings-window.hpp +++ b/settings-window.hpp @@ -3,6 +3,7 @@ #include #include "obs-manager.hpp" +#include "settings-manager.hpp" class SettingsWindow : public Gtk::Window { @@ -10,6 +11,8 @@ public: SettingsWindow(OBSManager *obs); virtual ~SettingsWindow(); private: + SettingsManager *settings; + Gtk::Box mBox; Gtk::Frame mFrameSettings; Gtk::Box mBoxSettings; @@ -20,10 +23,22 @@ private: Gtk::Label mLabelOutputDir; Gtk::Entry mEntryOutputDir; + Gtk::Frame mFrameDesktop; + Gtk::CheckButton mCheckButtonDesktop; + + Gtk::Frame mFrameWebcam; + Gtk::Box mBoxWebcam; + Gtk::CheckButton mCheckButtonWebcam; + Gtk::ComboBoxText mComboBoxVideoDevice; + + Gtk::Frame mFrameAudio; + Gtk::CheckButton mCheckButtonAudio; + Gtk::ActionBar mActionBar; Gtk::Button mButtonClose; Gtk::Button mButtonSave; + void populateVideoDevices(); bool onKeyPressed(GdkEventKey* event); void onClosePressed(); void onSavePressed();