]> git.decadent.org.uk Git - videolink.git/blobdiff - webdvd.cpp
Cleaned up option processing.
[videolink.git] / webdvd.cpp
index 4d951ee9120f5502b0bec78b4aedcc92e2c16012..a6d456a8f0de6ed9ee20dba636c7b0d14d9c1a4b 100644 (file)
@@ -133,10 +133,12 @@ namespace
     class WebDvdWindow : public Gtk::Window
     {
     public:
-       WebDvdWindow(int width, int height);
-       void add_page(const std::string & uri);
+       WebDvdWindow(
+           const video::frame_params & frame_params,
+           const std::string & main_page_uri);
 
     private:
+       void add_page(const std::string & uri);
        void add_video(const std::string & uri);
        void load_next_page();
        void on_net_state_change(const char * uri, gint flags, guint status);
@@ -148,7 +150,7 @@ namespace
 
        enum ResourceType { page_resource, video_resource };
        typedef std::pair<ResourceType, int> ResourceEntry;
-       int width_, height_;
+       video::frame_params frame_params_;
        BrowserWidget browser_widget_;
        nsCOMPtr<nsIStyleSheet> stylesheet_;
        std::queue<std::string> page_queue_;
@@ -161,17 +163,22 @@ namespace
        std::auto_ptr<link_state> link_state_;
     };
 
-    WebDvdWindow::WebDvdWindow(int width, int height)
-           : width_(width), height_(height),
+    WebDvdWindow::WebDvdWindow(
+       const video::frame_params & frame_params,
+       const std::string & main_page_uri)
+           : frame_params_(frame_params),
              stylesheet_(load_css("file://" WEBDVD_LIB_DIR "/webdvd.css")),
              loading_(false),
              pending_req_count_(0)
     {
-       set_default_size(width, height);
+       set_default_size(frame_params_.width, frame_params_.height);
        add(browser_widget_);
        browser_widget_.show();
        browser_widget_.signal_net_state().connect(
            SigC::slot(*this, &WebDvdWindow::on_net_state_change));
+
+       add_page(main_page_uri);
+       load_next_page();
     }
 
     void WebDvdWindow::add_page(const std::string & uri)
@@ -181,8 +188,6 @@ namespace
            .second)
        {
            page_queue_.push(uri);
-           if (!loading_)
-               load_next_page();
        }
     }
 
@@ -306,7 +311,8 @@ namespace
        std::cout << "saving " << filename << std::endl;
        Gdk::Pixbuf::create(Glib::RefPtr<Gdk::Drawable>(window),
                            window->get_colormap(),
-                           0, 0, 0, 0, width_, height_)
+                           0, 0, 0, 0,
+                           frame_params_.width, frame_params_.height)
            ->save(filename, "png");
     }
 
@@ -352,10 +358,10 @@ namespace
        {
            state.reset(new link_state);
 
-           state->diff_pixbuf = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB,
-                                                    true, // has_alpha
-                                                    8, // bits_per_sample
-                                                    width_, height_);
+           state->diff_pixbuf = Gdk::Pixbuf::create(
+               Gdk::COLORSPACE_RGB,
+               true, 8, // has_alpha, bits_per_sample
+               frame_params_.width, frame_params_.height);
 
            char spumux_filename[20];
            std::sprintf(spumux_filename,
@@ -377,7 +383,9 @@ namespace
            state->link_changing = false;
        }
            
-       rectangle window_rect = { 0, 0, width_, height_ };
+       rectangle window_rect = {
+           0, 0, frame_params_.width, frame_params_.height
+       };
 
        for (/* no initialisation */;
             state->links_it != state->links_end;
@@ -755,38 +763,98 @@ namespace
        }
     }
 
+    const video::frame_params & lookup_frame_params(const char * str)
+    {
+       assert(str);
+       static const struct { const char * str; bool is_ntsc; }
+       known_strings[] = {
+           { "NTSC",  true },
+           { "ntsc",  true },
+           { "PAL",   false },
+           { "pal",   false },
+           // For DVD purposes, SECAM can be treated identically to PAL.
+           { "SECAM", false },
+           { "secam", false }
+       };
+       for (std::size_t i = 0;
+            i != sizeof(known_strings)/sizeof(known_strings[0]);
+            ++i)
+           if (std::strcmp(str, known_strings[i].str) == 0)
+               return known_strings[i].is_ntsc ?
+                   video::ntsc_params : video::pal_params;
+       throw std::runtime_error(
+           std::string("Invalid video standard: ").append(str));
+    }
+
 } // namespace
 
 int main(int argc, char ** argv)
 {
-    // Get dimensions
-    int width = video::pal_oscan_width, height = video::pal_oscan_height;
-    for (int i = 1; i < argc - 1; ++i)
-       if (std::strcmp(argv[i], "-geometry") == 0)
-       {
-           std::sscanf(argv[i + 1], "%dx%d", &width, &height);
-           break;
-       }
-    // A depth of 24 results in 8 bits each for RGB components, which
-    // translates into "enough" bits for YUV components.
-    const int depth = 24;
-
     try
     {
+       // Determine video frame parameters.
+       video::frame_params frame_params = video::pal_params;
+       for (int argi = 1; argi != argc; ++argi)
+       {
+           if (std::strcmp(argv[argi], "--") == 0)
+               break;
+           if (std::strcmp(argv[argi], "--video-std") == 0)
+           {
+               if (argi + 1 == argc)
+               {
+                   std::cerr << "Missing argument to --video-std\n";
+                   return EXIT_FAILURE;
+               }
+               frame_params = lookup_frame_params(argv[argi + 1]);
+               break;
+           }
+       }
+       
        // Spawn Xvfb and set env variables so that Xlib will use it
-       FrameBuffer fb(width, height, depth);
+       // Use 8 bits each for RGB components, which should translate into
+       // "enough" bits for YUV components.
+       FrameBuffer fb(frame_params.width, frame_params.height, 3 * 8);
        setenv("XAUTHORITY", fb.get_x_authority().c_str(), true);
        setenv("DISPLAY", fb.get_x_display().c_str(), true);
 
-       // Initialise Gtk and Mozilla
+       // Initialise Gtk
        Gtk::Main kit(argc, argv);
+           
+       // Check we have the right number of arguments.  We can't
+       // do this earlier because we need to let Gtk read and remove
+       // any of the many options it understands.
+       int argi = 1;
+       while (argi != argc)
+       {
+           if (std::strcmp(argv[argi], "--video-std") == 0)
+           {
+               argi += 2;
+           }
+           else if (std::strcmp(argv[argi], "--") == 0)
+           {
+               argi += 1;
+               break;
+           }
+           else if (argv[argi][0] == '-')
+           {
+               std::cerr << "Invalid option: " << argv[argi] << "\n";
+               return EXIT_FAILURE;
+           }
+           else
+               break;
+       }
+       if (argi != argc - 1)
+       {
+           std::cerr << "Usage: " << argv[0]
+                     << (" [gtk-options] [--video-std std-name]"
+                         "front-page-url\n");
+           return EXIT_FAILURE;
+       }
+
+       // Initialise Mozilla
        BrowserWidget::init();
 
-       WebDvdWindow window(width, height);
-       for (int argi = 1; argi < argc; ++argi)
-           window.add_page(argv[argi]);
-       if (argc < 2)
-           window.add_page("about:");
+       WebDvdWindow window(frame_params, argv[argi]);
        Gtk::Main::run(window);
     }
     catch (std::exception & e)