]> git.decadent.org.uk Git - videolink.git/blobdiff - webdvd.cpp
Changed webdvd_window::generate_dvd() into a free function.
[videolink.git] / webdvd.cpp
index d0f2e05f3e8dd2f9718f4f47e9636f119828ee3d..e80996874157ce339063dd7a5fd5ab30b42aaa4f 100644 (file)
@@ -142,6 +142,36 @@ namespace
        return result;
     }
 
+
+    std::string xml_escape(const std::string & str)
+    {
+       std::string result;
+       std::size_t begin = 0;
+
+       for (;;)
+       {
+           std::size_t end = str.find_first_of("\"&'<>", begin);
+           result.append(str, begin, end - begin);
+           if (end == std::string::npos)
+               return result;
+
+           const char * entity = NULL;
+           switch (str[end])
+           {
+           case '"':  entity = "&quot;"; break;
+           case '&':  entity = "&amp;";  break;
+           case '\'': entity = "&apos;"; break;
+           case '<':  entity = "&lt;";   break;
+           case '>':  entity = "&gt;";   break;
+           }
+           assert(entity);
+           result.append(entity);
+
+           begin = end + 1;
+       }
+    }
+
+    
     struct dvd_contents
     {
        enum pgc_type { menu_pgc, title_pgc };
@@ -171,7 +201,10 @@ namespace
        std::vector<menu> menus;
        std::vector<title> titles;
     };
-    
+
+    void generate_dvd(const dvd_contents & contents,
+                     const std::string & output_dir);
+
     class webdvd_window : public Gtk::Window
     {
     public:
@@ -185,12 +218,15 @@ namespace
        dvd_contents::pgc_ref add_title(const std::string & uri);
        void load_next_page();
        void on_net_state_change(const char * uri, gint flags, guint status);
+       bool browser_is_busy() const
+           {
+               return pending_window_update_ || pending_req_count_;
+           }
        bool process_page();
        void save_screenshot();
        void process_links(nsIPresShell * pres_shell,
                           nsIPresContext * pres_context,
                           nsIDOMWindow * dom_window);
-       void generate_dvd();
 
        video::frame_params frame_params_;
        std::string output_dir_;
@@ -280,8 +316,7 @@ namespace
                        filename + " is missing or not a regular file");
                vob_list
                    .append("<vob file='")
-                   // FIXME: Should XML-escape the path
-                   .append(filename)
+                   .append(xml_escape(filename))
                    .append("'/>\n");
            }
            else
@@ -378,7 +413,7 @@ namespace
            pending_window_update_ = false;
        }
 
-       if (pending_req_count_ == 0 && !pending_window_update_)
+       if (!browser_is_busy())
        {
            try
            {
@@ -426,7 +461,7 @@ namespace
 
            // Might need to wait a while for things to load or more
            // likely for a re-layout.
-           if (pending_req_count_ > 0)
+           if (browser_is_busy())
                return true;
        }
 
@@ -448,7 +483,7 @@ namespace
                page_queue_.pop();
                if (page_queue_.empty())
                {
-                   generate_dvd();
+                   generate_dvd(contents_, output_dir_);
                    return false;
                }
                else
@@ -685,7 +720,7 @@ namespace
                // We may have to exit and wait for image loading
                // to complete, at which point we will be called
                // again.
-               if (pending_req_count_ > 0)
+               if (browser_is_busy())
                {
                    state->link_changing = true;
                    page_state_ = state;
@@ -765,7 +800,8 @@ namespace
        }
     }
 
-    void webdvd_window::generate_dvd()
+    void generate_dvd(const dvd_contents & contents,
+                     const std::string & output_dir)
     {
        temp_file temp("webdvd-dvdauthor-");
        temp.close();
@@ -793,10 +829,10 @@ namespace
            "    <menus>\n";
            
        for (std::size_t menu_num = 0;
-            menu_num != contents_.menus.size();
+            menu_num != contents.menus.size();
             ++menu_num)
        {
-           dvd_contents::menu & menu = contents_.menus[menu_num];
+           const dvd_contents::menu & menu = contents.menus[menu_num];
 
            if (menu_num == 0)
            {
@@ -842,7 +878,7 @@ namespace
                 menu_incr != 0;
                 menu_incr /= 2)
            {
-               if (menu_num + menu_incr < contents_.menus.size()
+               if (menu_num + menu_incr < contents.menus.size()
                    && (menu_num & (menu_incr * 2 - 1)) == 0)
                {
                    file <<
@@ -875,7 +911,7 @@ namespace
                    // first button.
                    const std::vector<dvd_contents::pgc_ref> &
                        dest_menu_entries =
-                       contents_.menus[dest_menu_num].entries;
+                       contents.menus[dest_menu_num].entries;
                    dvd_contents::pgc_ref this_pgc(
                        dvd_contents::menu_pgc, menu_num);
                    std::size_t dest_button_num = dest_menu_entries.size();
@@ -913,7 +949,7 @@ namespace
        // jumping to titles a whole lot simpler (but limits us to 99
        // titles).
        for (std::size_t title_num = 0;
-            title_num != contents_.titles.size();
+            title_num != contents.titles.size();
             ++title_num)
        {
            file <<
@@ -929,7 +965,7 @@ namespace
                "      <pgc>\n"
                // Record calling location.
                "        <pre> g12 = g1; </pre>\n"
-                << contents_.titles[title_num].vob_list <<
+                << contents.titles[title_num].vob_list <<
                // If the menu location has not been changed during
                // the title, set the location to be the following
                // button in the menu.  In any case, return to some
@@ -949,7 +985,7 @@ namespace
        {
            const char * argv[] = {
                "dvdauthor",
-               "-o", output_dir_.c_str(),
+               "-o", output_dir.c_str(),
                "-x", temp.get_name().c_str(),
                0
            };
@@ -1000,16 +1036,17 @@ namespace
     
     void set_browser_preferences()
     {
-       // Disable IE-compatibility kluge that causes backgrounds to
-       // sometimes/usually be missing from snapshots.  This is only
-       // effective from Mozilla 1.8 onward.
-#      if MOZ_VERSION_MAJOR > 1                                 \
-           || (MOZ_VERSION_MAJOR == 1 && MOZ_VERSION_MINOR >= 8)
        nsCOMPtr<nsIPrefService> pref_service;
        static const nsCID pref_service_cid = NS_PREFSERVICE_CID;
        check(CallGetService<nsIPrefService>(pref_service_cid,
                                             getter_AddRefs(pref_service)));
        nsCOMPtr<nsIPrefBranch> pref_branch;
+
+       // Disable IE-compatibility kluge that causes backgrounds to
+       // sometimes/usually be missing from snapshots.  This is only
+       // effective from Mozilla 1.8 onward.
+#      if MOZ_VERSION_MAJOR > 1                                 \
+           || (MOZ_VERSION_MAJOR == 1 && MOZ_VERSION_MINOR >= 8)
        check(pref_service->GetDefaultBranch("layout",
                                             getter_AddRefs(pref_branch)));
        check(pref_branch->SetBoolPref(
@@ -1017,9 +1054,17 @@ namespace
                  true));
 #      endif
 
-       // TODO: Set display resolution?  Unfortunately Mozilla doesn't
-       // support non-square pixels (and neither do fontconfig or Xft
-       // anyway).
+       // Set display resolution.  With standard-definition video we
+       // will be fitting ~600 pixels across a screen typically
+       // ranging from 10 to 25 inches wide, for a resolution of
+       // 24-60 dpi.  I therefore declare the average horizontal
+       // resolution to be 40 dpi.  The vertical resolution will be
+       // slightly higher (PAL/SECAM) or lower (NTSC), but
+       // unfortunately Mozilla doesn't support non-square pixels
+       // (and neither do fontconfig or Xft anyway).
+       check(pref_service->GetDefaultBranch("browser.display",
+                                            getter_AddRefs(pref_branch)));
+       check(pref_branch->SetIntPref("screen_resolution", 40));
     }
 
 } // namespace