// See the file "COPYING" for licence details.
#include <cassert>
+#include <cstring>
#include <exception>
#include <fstream>
#include <iomanip>
{
rectangle result;
+ // Start with this element's bounding box
nsCOMPtr<nsIBoxObject> box;
check(ns_doc->GetBoxObjectFor(elem, getter_AddRefs(box)));
int width, height;
result.right = result.left + width;
result.bottom = result.top + height;
+ // Merge bounding boxes of all child elements
for (ChildIterator it = ChildIterator(elem), end; it != end; ++it)
{
nsCOMPtr<nsIDOMNode> child_node(*it);
void add_video(const std::string & uri);
void load_next_page();
void on_net_state_change(const char * uri, gint flags, guint status);
+ bool process_page();
void save_screenshot();
void process_links(nsIPresShell * pres_shell,
nsIPresContext * pres_context,
bool pending_window_update_;
int pending_req_count_;
std::auto_ptr<temp_file> background_temp_;
- struct link_state;
- std::auto_ptr<link_state> link_state_;
+ struct page_state;
+ std::auto_ptr<page_state> page_state_;
std::vector<boost::shared_ptr<temp_file> > page_temp_files_;
};
pending_window_update_(false),
pending_req_count_(0)
{
- set_default_size(frame_params_.width, frame_params_.height);
+ set_size_request(frame_params_.width, frame_params_.height);
+ set_resizable(false);
+
add(browser_widget_);
browser_widget_.show();
browser_widget_.signal_net_state().connect(
video_paths_.size() + 1)))
.second)
{
- // FIXME: Should accept some slightly different URI prefixes
- // (e.g. file://localhost/) and decode any URI-escaped
- // characters in the path.
- assert(uri.compare(0, 8, "file:///") == 0);
- video_paths_.push_back(uri.substr(7));
+ Glib::ustring hostname;
+ video_paths_.push_back(Glib::filename_from_uri(uri, hostname));
+ // FIXME: Should check the hostname
}
}
if (flags & GTK_MOZ_EMBED_FLAG_STOP
&& flags & GTK_MOZ_EMBED_FLAG_IS_WINDOW)
+ {
+ // Check whether the load was successful, ignoring this
+ // pseudo-error.
+ if (status != NS_IMAGELIB_ERROR_LOAD_ABORTED)
+ check(status);
+
pending_window_update_ = false;
+ }
if (pending_req_count_ == 0 && !pending_window_update_)
{
- assert(!page_queue_.empty());
-
try
{
- // Check whether the load was successful, ignoring this
- // pseudo-error.
- if (status != NS_IMAGELIB_ERROR_LOAD_ABORTED)
- check(status);
-
- 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<nsIPresContext> pres_context;
- check(doc_shell->GetPresContext(
- getter_AddRefs(pres_context)));
- nsCOMPtr<nsIDOMWindow> dom_window;
- check(browser->GetContentDOMWindow(
- getter_AddRefs(dom_window)));
-
- if (output_dir_.empty())
- {
- apply_style_sheet(stylesheet_, pres_shell);
- }
- else
- {
- if (!link_state_.get())
- {
- apply_style_sheet(stylesheet_, pres_shell);
- save_screenshot();
- }
-
- process_links(pres_shell, pres_context, dom_window);
-
- if (!link_state_.get())
- {
- page_queue_.pop();
- if (page_queue_.empty())
- {
- generate_dvd();
- Gtk::Main::quit();
- }
- else
- {
- load_next_page();
- }
- }
- }
+ if (!process_page())
+ Gtk::Main::quit();
}
catch (std::exception & e)
{
}
}
+ bool WebDvdWindow::process_page()
+ {
+ assert(!page_queue_.empty());
+
+ 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<nsIPresContext> pres_context;
+ check(doc_shell->GetPresContext(getter_AddRefs(pres_context)));
+ nsCOMPtr<nsIDOMWindow> dom_window;
+ check(browser->GetContentDOMWindow(getter_AddRefs(dom_window)));
+
+ if (output_dir_.empty())
+ {
+ // In preview mode, just apply the stylesheet and let the
+ // user select links.
+ apply_style_sheet(stylesheet_, pres_shell);
+ }
+ else
+ {
+ // If we haven't already started work on this page, apply
+ // the stylesheet and save a screenshot of its normal
+ // appearance.
+ if (!page_state_.get())
+ {
+ apply_style_sheet(stylesheet_, pres_shell);
+ save_screenshot();
+ }
+
+ // Start or continue processing links.
+ process_links(pres_shell, pres_context, dom_window);
+
+ // If we've finished work on the links, move on to the
+ // next page, if any, or else generate the DVD filesystem.
+ if (!page_state_.get())
+ {
+ page_queue_.pop();
+ if (page_queue_.empty())
+ {
+ generate_dvd();
+ return false;
+ }
+ else
+ {
+ load_next_page();
+ }
+ }
+ }
+
+ return true;
+ }
+
void WebDvdWindow::save_screenshot()
{
Glib::RefPtr<Gdk::Window> window(get_window());
->save(background_temp_->get_name(), "png");
}
- struct WebDvdWindow::link_state
+ struct WebDvdWindow::page_state
{
+ page_state(nsIDOMDocument * doc, int width, int height)
+ : diff_pixbuf(Gdk::Pixbuf::create(
+ Gdk::COLORSPACE_RGB,
+ true, 8, // has_alpha, bits_per_sample
+ width, height)),
+ spumux_temp("webdvd-spumux-"),
+ links_temp("webdvd-links-"),
+ link_num(0),
+ links_it(doc),
+ link_changing(false)
+ {
+ spumux_temp.close();
+ links_temp.close();
+ }
+
Glib::RefPtr<Gdk::Pixbuf> diff_pixbuf;
- std::auto_ptr<temp_file> spumux_temp;
+ temp_file spumux_temp;
std::ofstream spumux_file;
- std::auto_ptr<temp_file> links_temp;
+ temp_file links_temp;
int link_num;
LinkIterator links_it, links_end;
check(doc_view->GetDefaultView(getter_AddRefs(view)));
// Set up or recover our iteration state.
- std::auto_ptr<link_state> state(link_state_);
+ std::auto_ptr<page_state> state(page_state_);
if (!state.get())
{
- state.reset(new link_state);
-
- state->diff_pixbuf = Gdk::Pixbuf::create(
- Gdk::COLORSPACE_RGB,
- true, 8, // has_alpha, bits_per_sample
- frame_params_.width, frame_params_.height);
-
- state->spumux_temp.reset(new temp_file("webdvd-spumux-"));
- state->spumux_temp->close();
-
- state->links_temp.reset(new temp_file("webdvd-links-"));
- state->links_temp->close();
+ state.reset(
+ new page_state(
+ basic_doc, frame_params_.width, frame_params_.height));
- state->spumux_file.open(state->spumux_temp->get_name().c_str());
+ state->spumux_file.open(state->spumux_temp.get_name().c_str());
state->spumux_file <<
"<subpictures>\n"
" <stream>\n"
" <spu force='yes' start='00:00:00.00'\n"
- " highlight='" << state->links_temp->get_name()
- << "'\n"
- " select='" << state->links_temp->get_name()
- << "'>\n";
-
- state->link_num = 0;
- state->links_it = LinkIterator(basic_doc);
- state->link_changing = false;
+ " highlight='" << state->links_temp.get_name() << "'\n"
+ " select='" << state->links_temp.get_name() << "'>\n";
}
-
+
rectangle window_rect = {
0, 0, frame_params_.width, frame_params_.height
};
if (pending_req_count_ > 0)
{
state->link_changing = true;
- link_state_ = state;
+ page_state_ = state;
return;
}
}
quantise_rgba_pixbuf(state->diff_pixbuf, dvd::button_n_colours);
- std::cout << "saving " << state->links_temp->get_name()
+ std::cout << "saving " << state->links_temp.get_name()
<< std::endl;
- state->diff_pixbuf->save(state->links_temp->get_name(), "png");
+ state->diff_pixbuf->save(state->links_temp.get_name(), "png");
state->spumux_file <<
" </spu>\n"
" | mpeg2enc -v0 -f8 -a2 -o/dev/stdout"
" | mplex -v0 -f8 -o/dev/stdout /dev/stdin"
" | spumux -v0 -mdvd ")
- << state->spumux_temp->get_name()
+ << state->spumux_temp.get_name()
<< " > " << vob_temp->get_name();
std::string command(command_stream.str());
const char * argv[] = {
{
video::frame_params frame_params = video::pal_params;
bool preview_mode = false;
+ std::string menu_url;
+ std::string output_dir;
- // Do initial argument parsing. We have to do this before
+ // Do initial option parsing. We have to do this before
// letting Gtk parse the arguments since we may need to spawn
// Xvfb first.
int argi = 1;
// Initialise Gtk
Gtk::Main kit(argc, argv);
- // Complete argument parsing with Gtk's options out of the way.
+ // Complete option parsing with Gtk's options out of the way.
argi = 1;
while (argi != argc)
{
break;
}
}
- if (argc - argi != (preview_mode ? 1 : 2))
+
+ // Look for a starting URL or filename and (except in preview
+ // mode) an output directory after the options.
+ if (argc - argi != (preview_mode ? 1 : 2))
{
print_usage(std::cerr, argv[0]);
return EXIT_FAILURE;
}
+ if (std::strstr(argv[argi], "://"))
+ {
+ // It appears to be an absolute URL, so use it as-is.
+ menu_url = argv[argi];
+ }
+ else
+ {
+ // Assume it's a filename. Resolve it to an absolute URL.
+ std::string path(argv[argi]);
+ if (!Glib::path_is_absolute(path))
+ path = Glib::build_filename(Glib::get_current_dir(), path);
+ menu_url = Glib::filename_to_uri(path);
+ }
+ if (!preview_mode)
+ output_dir = argv[argi + 1];
// Initialise Mozilla
BrowserWidget::init();
- WebDvdWindow window(frame_params,
- argv[argi],
- preview_mode ? "" : argv[argi + 1]);
+ // Run the browser/converter
+ WebDvdWindow window(frame_params, menu_url, output_dir);
Gtk::Main::run(window);
}
catch (std::exception & e)