diff --git a/main.cpp b/main.cpp index a49ee6e..1a3d12b 100644 --- a/main.cpp +++ b/main.cpp @@ -6,26 +6,33 @@ // Copyright (c) 2020 SwiftCoder. All rights reserved. // +// C++ #include #include #include #include -#include -#include -#include -#include #include -#include #include #include -#include "RectSaver.hpp" + +// POSIX +#include +#include + +// libraries +#include +#include +#include +#include +#include +#include const int WIDTH {1600}; const int HEIGHT {900}; sc::gui::Window* main_window {nullptr}; sc::gui::Image* main_image {nullptr}; -RectSaver* main_saver {nullptr}; +ScreensaverPlugin* main_saver {nullptr}; bool expired {true}; bool should_run {true}; @@ -39,6 +46,12 @@ void print_version() { std::cout << "screensaver version 1.0\n"; } +void list_plugins() { + for (const std::string& name : sc::plugin::names()) { + std::cout << name << '\n'; + } +} + void update_frame() { while (should_run) { expired = true; @@ -61,13 +74,18 @@ void draw() { int main(int argc, const char * argv[]) { try { + // gather plugins + sc::plugin::scan_plugins(sc::dirname(sc::tool_path(argv[0])) + "/plugins", "saver"); + std::unique_ptr saver; + int opt_char, opt_val; struct option long_options[] = { - {"help", no_argument, nullptr, 'h'}, + {"help", no_argument, nullptr, 'h'}, + {"list", no_argument, nullptr, 'l'}, {"version", no_argument, &opt_val, 1}, {nullptr, 0, nullptr, 0} }; - while ((opt_char = getopt_long(argc, const_cast(argv), "h", long_options, nullptr)) != -1) { + while ((opt_char = getopt_long(argc, const_cast(argv), "hl", long_options, nullptr)) != -1) { std::string arg {optarg ? optarg : ""}; switch (opt_char) { case 0: { @@ -82,20 +100,28 @@ int main(int argc, const char * argv[]) { case 'h': print_help(); return EXIT_SUCCESS; + case 'l': + list_plugins(); + return EXIT_SUCCESS; case '?': throw std::runtime_error("unrecognized option"); } } - // if (optind == argc) { - // // here when no file args - // } - // for (int i = optind; i < argc; ++i) { - // try { - // // process file argv[i] - // } catch (const std::runtime_error& ex) { - // std::cerr << "screensaver: " << ex.what() << '\n'; - // } - // } + if (optind == argc) { + // here when no file args + saver = sc::plugin::get("rects")(); + } + for (int i = optind; i < argc; ++i) { + try { + // process file argv[i] + saver = sc::plugin::get(argv[i])(); + break; // only first one used + } catch (const std::runtime_error& ex) { + std::cerr << "screensaver: " << ex.what() << '\n'; + } catch (const std::out_of_range& ex) { + std::cerr << "screensaver: no such screensaver module: " << argv[i] << '\n'; + } + } // RAII instances sc::gui::SDLWrapper sdl2; @@ -109,15 +135,23 @@ int main(int argc, const char * argv[]) { return quit; }, SDL_WINDOWEVENT_CLOSE); + // create an SDL drawing surface and connect it to cairo SDL_Surface* s {SDL_CreateRGBSurface(0, WIDTH, HEIGHT, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0)}; sc::gui::Image image {s}; main_image = ℑ cairo_surface_t* cs {cairo_image_surface_create_for_data(static_cast(s->pixels), CAIRO_FORMAT_RGB24, s->w, s->h, s->pitch)}; + std::unique_ptr cs_ {cs, cairo_surface_destroy}; cairo_t* cr {cairo_create(cs)}; + std::unique_ptr cr_ {cr, cairo_destroy}; - RectSaver saver {cr, {0, 0, WIDTH, HEIGHT}}; - main_saver = &saver; + // setup screen saver module + if (!saver) { + saver = sc::plugin::get("rects")(); + std::cerr << "screensaver: using standard 'rects' module\n"; + } + main_saver = saver.get(); + main_saver->setup(cr, {0, 0, WIDTH, HEIGHT}); // setup thread which periodically sets 'expired' std::thread frame_timer {update_frame}; @@ -125,9 +159,6 @@ int main(int argc, const char * argv[]) { sc::gui::app().add_run_loop_action(draw); sc::gui::app().run(); - cairo_surface_destroy(cs); - cairo_destroy(cr); - should_run = false; frame_timer.join();