]> git.decadent.org.uk Git - videolink.git/blobdiff - videolink.cpp
Release versions 1.2.11 and 1.2.11-1
[videolink.git] / videolink.cpp
index 112125ad2b27e47c2ab8e8ef1d3e08b76fb080cc..a15bbea1bfe125a2cf9c67e152935203a1e3e2a3 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2005-6 Ben Hutchings <ben@decadent.org.uk>.
+// Copyright 2005-8 Ben Hutchings <ben@decadent.org.uk>.
 // See the file "COPYING" for licence details.
 
 #include <cassert>
 #include <gtkmm/main.h>
 #include <gtkmm/window.h>
 
-#include <imglib2/ImageErrors.h>
+#include "videolink.hpp"
+#include "wchar_t_short.h"
+#include <ImageErrors.h>
+#if MOZ_VERSION_GE(1,9,0)
+#include <nsWeakPtr.h>
+/* For some reason <nsWeakPtr.h> no longer defines this */
+typedef nsCOMPtr<nsIWeakReference> nsWeakPtr;
+#endif
 #include <nsGUIEvent.h>
 #include <nsIBoxObject.h>
 #include <nsIContent.h>
 #include <nsIURI.h> // required before nsILink.h
 #include <nsILink.h>
 #include <nsIPrefBranch.h>
-#include <nsPresContext.h>
 #include <nsIPrefService.h>
 #include <nsIPresShell.h>
 #include <nsServiceManagerUtils.h>
 #include <nsIWebBrowser.h>
+#ifdef MOZILLA_INTERNAL_API
 #include <nsString.h>
+#else
+#include <nsStringAPI.h>
+#endif
+#include "wchar_t_default.h"
 
 #include "browser_widget.hpp"
 #include "child_iterator.hpp"
 #include "dvd.hpp"
+#include "event_state_manager.hpp"
 #include "generate_dvd.hpp"
 #include "geometry.hpp"
 #include "link_iterator.hpp"
@@ -69,14 +81,17 @@ using xpcom_support::check;
 
 namespace
 {
-    rectangle get_elem_rect(nsIDOMNSDocument * ns_doc,
-                           nsIDOMElement * elem)
+#if MOZ_VERSION_GE(2,0,-1)
+    rectangle get_elem_rect(nsIDocument * doc, nsIDOMElement * elem)
+#else
+    rectangle get_elem_rect(nsIDOMNSDocument * doc, nsIDOMElement * elem)
+#endif
     {
        rectangle result;
 
        // Start with this element's bounding box
        nsCOMPtr<nsIBoxObject> box;
-       check(ns_doc->GetBoxObjectFor(elem, getter_AddRefs(box)));
+       check(doc->GetBoxObjectFor(elem, getter_AddRefs(box)));
        int width, height;
        check(box->GetScreenX(&result.left));
        check(box->GetScreenY(&result.top));
@@ -95,7 +110,7 @@ namespace
            {
                nsCOMPtr<nsIDOMElement> child_elem(
                    do_QueryInterface(child_node));
-               result |= get_elem_rect(ns_doc, child_elem);
+               result |= get_elem_rect(doc, child_elem);
            }
        }
 
@@ -146,10 +161,6 @@ namespace
     protected:
        video::frame_params frame_params_;
        browser_widget browser_widget_;
-
-    private:
-       bool on_idle();
-       virtual void do_late_initialisation() = 0;
     };
 
     base_window::base_window(const video::frame_params & frame_params)
@@ -160,15 +171,6 @@ namespace
 
        add(browser_widget_);
        browser_widget_.show();
-
-       Glib::signal_idle().connect(
-           sigc::mem_fun(this, &base_window::on_idle));
-    }
-
-    bool base_window::on_idle()
-    {
-       do_late_initialisation();
-       return false; // don't call again thankyou
     }
 
     class preview_window : public base_window
@@ -178,7 +180,7 @@ namespace
                       const std::string & main_page_uri);
 
     private:
-       virtual void do_late_initialisation();
+       bool on_idle();
        bool on_key_press(GdkEventKey *);
 
        std::string main_page_uri_;
@@ -189,13 +191,16 @@ namespace
        : base_window(frame_params),
          main_page_uri_(main_page_uri)
     {
+       Glib::signal_idle().connect(
+           sigc::mem_fun(this, &preview_window::on_idle));
        signal_key_press_event().connect(
            sigc::mem_fun(this, &preview_window::on_key_press));
     }
 
-    void preview_window::do_late_initialisation()
+    bool preview_window::on_idle()
     {
        browser_widget_.load_uri(main_page_uri_);
+       return false; // don't call again
     }
 
     bool preview_window::on_key_press(GdkEventKey * event)
@@ -230,15 +235,12 @@ namespace
        dvd_generator::pgc_ref add_title(const std::string & uri,
                                         video_format format);
        void load_next_page();
-       void do_late_initialisation();
+       bool on_idle();
        void on_net_state_change(const char * uri, gint flags, guint status);
        bool browser_is_busy() const
            {
                return pending_window_update_ || pending_req_count_;
            }
-       // Try to do as much processing as possible.  Quit if done;
-       // report and quit if an exception occurs.
-       void try_process();
        // Do as much processing as possible.  Return a flag indicating
        // whether to call again once the browser is idle.
        bool process();
@@ -250,12 +252,17 @@ namespace
        bool process_links(
            page_state * state,
            nsIDOMDocument * basic_doc,
-           nsIPresShell * pres_shell,
-           nsPresContext * pres_context,
+           nsIDocShell * doc_shell,
            nsIDOMWindow * dom_window);
 
        std::string output_dir_;
 
+       enum {
+           state_initial,
+           state_processing,
+           state_finished
+       } state_;
+
        dvd_generator generator_;
        typedef std::map<std::string, dvd_generator::pgc_ref>
            resource_map_type;
@@ -265,8 +272,6 @@ namespace
        bool pending_window_update_;
        int pending_req_count_;
        std::auto_ptr<page_state> page_state_;
-
-       bool finished_;
     };
 
     conversion_window::conversion_window(
@@ -276,11 +281,13 @@ namespace
        dvd_generator::mpeg_encoder encoder)
        : base_window(frame_params),
          output_dir_(output_dir),
+         state_(state_initial),
          generator_(frame_params, encoder),
          pending_window_update_(false),
-         pending_req_count_(0),
-         finished_(false)
+         pending_req_count_(0)
     {
+       Glib::signal_idle().connect(
+           sigc::mem_fun(this, &conversion_window::on_idle));
        browser_widget_.signal_net_state().connect(
            sigc::mem_fun(this, &conversion_window::on_net_state_change));
 
@@ -289,7 +296,7 @@ namespace
 
     bool conversion_window::is_finished() const
     {
-       return finished_;
+       return state_ == state_finished;
     }
 
     dvd_generator::pgc_ref conversion_window::add_menu(const std::string & uri)
@@ -351,16 +358,6 @@ namespace
        browser_widget_.load_uri(uri);
     }
 
-    void conversion_window::do_late_initialisation()
-    {
-       // Put pointer in the top-left so that no links appear in
-       // the hover state when we take a screenshot.
-       warp_pointer(get_window(),
-                    -frame_params_.width, -frame_params_.height);
-       
-       load_next_page();
-    }
-
     void conversion_window::on_net_state_change(const char * uri,
                                                gint flags, guint status)
     {
@@ -426,14 +423,13 @@ namespace
        {
            // Check whether the load was successful, ignoring this
            // pseudo-error.
+#ifdef NS_IMAGELIB_ERROR_LOAD_ABORTED
            if (status != NS_IMAGELIB_ERROR_LOAD_ABORTED)
+#endif
                check(status);
 
            pending_window_update_ = false;
        }
-
-       if (!browser_is_busy())
-           try_process();
     }
 
     struct conversion_window::page_state
@@ -460,48 +456,65 @@ namespace
        bool link_changing;
     };
 
-    void conversion_window::try_process()
+    bool conversion_window::on_idle()
     {
-       try
+       if (state_ == state_initial)
        {
-           if (!process())
-           {
-               finished_ = true;
-               Gtk::Main::quit();
-           }
+           // Put pointer in the top-left so that no links appear in
+           // the hover state when we take a screenshot.
+           warp_pointer(get_window(),
+                        -frame_params_.width, -frame_params_.height);
+
+           load_next_page();
+
+           state_ = state_processing;
        }
-       catch (...)
+       else if (state_ == state_processing && !browser_is_busy())
        {
-           // Print context of exception.
-           if (!page_queue_.empty())
-           {
-               std::cerr << "ERROR: While processing page <"
-                         << page_queue_.front() << ">:\n";
-               if (page_state_.get() && !page_state_->link_target.empty())
-                   std::cerr << "ERROR: While processing link to <"
-                             << page_state_->link_target << ">:\n";
-           }
-
-           // Print exception message.
            try
            {
-               throw;
-           }
-           catch (std::exception & e)
-           {
-               std::cerr << "ERROR: " << e.what() << "\n";
-           }
-           catch (Glib::Exception & e)
-           {
-               std::cerr << "ERROR: " << e.what() << "\n";
+               if (!process())
+               {
+                   state_ = state_finished;
+                   Gtk::Main::quit();
+               }
            }
            catch (...)
            {
-               std::cerr << "ERROR: Unknown exception\n";
-           }
+               // Print context of exception.
+               if (!page_queue_.empty())
+               {
+                   std::cerr << "ERROR: While processing page <"
+                             << page_queue_.front() << ">:\n";
+                   if (page_state_.get() && !page_state_->link_target.empty())
+                       std::cerr << "ERROR: While processing link to <"
+                                 << page_state_->link_target << ">:\n";
+               }
 
-           Gtk::Main::quit();
+               // Print exception message.
+               try
+               {
+                   throw;
+               }
+               catch (std::exception & e)
+               {
+                   std::cerr << "ERROR: " << e.what() << "\n";
+               }
+               catch (Glib::Exception & e)
+               {
+                   std::cerr << "ERROR: " << e.what() << "\n";
+               }
+               catch (...)
+               {
+                   std::cerr << "ERROR: Unknown exception\n";
+               }
+
+               Gtk::Main::quit();
+           }
        }
+
+       // Call again if we're not done.
+       return state_ != state_finished;
     }
 
     bool conversion_window::process()
@@ -511,10 +524,6 @@ namespace
        nsCOMPtr<nsIWebBrowser> browser(browser_widget_.get_browser());
        nsCOMPtr<nsIDocShell> doc_shell(do_GetInterface(browser));
        assert(doc_shell);
-       nsCOMPtr<nsIPresShell> pres_shell;
-       check(doc_shell->GetPresShell(getter_AddRefs(pres_shell)));
-       nsCOMPtr<nsPresContext> pres_context;
-       check(doc_shell->GetPresContext(getter_AddRefs(pres_context)));
        nsCOMPtr<nsIDOMWindow> dom_window;
        check(browser->GetContentDOMWindow(getter_AddRefs(dom_window)));
 
@@ -527,9 +536,7 @@ namespace
                new page_state(
                    get_screenshot(),
                    basic_doc, frame_params_.width, frame_params_.height));
-       if (!process_links(
-               page_state_.get(),
-               basic_doc, pres_shell, pres_context, dom_window))
+       if (!process_links(page_state_.get(), basic_doc, doc_shell, dom_window))
        {
            // We've finished work on the links so generate the
            // menu VOB.
@@ -572,8 +579,7 @@ namespace
     bool conversion_window::process_links(
        page_state * state,
        nsIDOMDocument * basic_doc,
-       nsIPresShell * pres_shell,
-       nsPresContext * pres_context,
+       nsIDocShell * doc_shell,
        nsIDOMWindow * dom_window)
     {
        Glib::RefPtr<Gdk::Window> window(get_window());
@@ -581,8 +587,14 @@ namespace
 
        nsCOMPtr<nsIDOMNSDocument> ns_doc(do_QueryInterface(basic_doc));
        assert(ns_doc);
+#if MOZ_VERSION_GE(2,0,-1)
+       nsCOMPtr<nsIDocument> doc(do_QueryInterface(basic_doc));
+       assert(doc);
+#endif
+       nsCOMPtr<nsIPresShell> pres_shell;
+       check(doc_shell->GetPresShell(getter_AddRefs(pres_shell)));
        nsCOMPtr<nsIEventStateManager> event_state_man(
-           pres_context->EventStateManager()); // does not AddRef
+           get_event_state_manager(doc_shell));
        assert(event_state_man);
        nsCOMPtr<nsIDOMDocumentEvent> event_factory(
            do_QueryInterface(basic_doc));
@@ -605,16 +617,24 @@ namespace
            nsCOMPtr<nsIDOMNode> node(*state->links_it);
 
            // Find the link URI and separate any fragment from it.
+           nsCOMPtr<nsIURI> uri_iface;
+#if MOZ_VERSION_GE(2,0,-1)
+           nsCOMPtr<nsIContent> content(do_QueryInterface(node));
+           assert(content);
+           uri_iface = content->GetHrefURI();
+           assert(uri_iface);
+#else
            nsCOMPtr<nsILink> link(do_QueryInterface(node));
            assert(link);
-           nsCOMPtr<nsIURI> uri_iface;
            check(link->GetHrefURI(getter_AddRefs(uri_iface)));
+#endif
            std::string uri, fragment;
            {
                nsCString link_target_ns;
                check(uri_iface->GetSpec(link_target_ns));
-               state->link_target.assign(link_target_ns.BeginReading(),
-                                         link_target_ns.EndReading());
+               const char * str;
+               PRUint32 len = NS_CStringGetData(link_target_ns, &str);
+               state->link_target.assign(str, len);
 
                std::size_t hash_pos = state->link_target.find('#');
                uri.assign(state->link_target, 0, hash_pos);
@@ -630,7 +650,11 @@ namespace
                // window.
                nsCOMPtr<nsIDOMElement> elem(do_QueryInterface(node));
                assert(elem);
+#if MOZ_VERSION_GE(2,0,-1)
+               state->link_rect = get_elem_rect(doc, elem);
+#else
                state->link_rect = get_elem_rect(ns_doc, elem);
+#endif
                state->link_rect &= window_rect;
 
                if (state->link_rect.empty())
@@ -761,7 +785,7 @@ namespace
            "Usage: " << command_name << " [gtk-options] [--preview]\n"
            "           [--video-std {525|525/60|NTSC|ntsc"
            " | 625|625/50|PAL|pal}]\n"
-           "           [--encoder {mjpegtools|mjpegtools-old}]\n"
+           "           [--encoder {ffmpeg|mjpegtools}]\n"
            "           menu-url [output-dir]\n";
     }
     
@@ -912,14 +936,9 @@ int main(int argc, char ** argv)
                {
                    encoder = dvd_generator::mpeg_encoder_ffmpeg;
                }
-               else if (std::strcmp(argv[argi + 1], "mjpegtools-old") == 0)
-               {
-                   encoder = dvd_generator::mpeg_encoder_mjpegtools_old;
-               }
-               else if (std::strcmp(argv[argi + 1], "mjpegtools") == 0
-                        || std::strcmp(argv[argi + 1], "mjpegtools-new") == 0)
+               else if (std::strcmp(argv[argi + 1], "mjpegtools") == 0)
                {
-                   encoder = dvd_generator::mpeg_encoder_mjpegtools_new;
+                   encoder = dvd_generator::mpeg_encoder_mjpegtools;
                }
                else
                {