From 6bc4ef41d90923d964f58288e2a76bda7016a4a3 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sat, 14 Oct 2006 00:47:31 +0000 Subject: [PATCH 01/16] Removed strict version dependency on libxul0d based on an assurances from Mike Hommey (bug #385566). --- debian/changelog | 7 +++++++ debian/rules | 14 +++++++------- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/debian/changelog b/debian/changelog index f4ec4c2..d3be7f4 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +videolink (0.9-2) unstable; urgency=low + + * Removed strict version dependency on libxul0d on advice of its + maintainer - closes: #385566 + + -- Ben Hutchings Wed, 6 Sep 2006 03:27:54 +0100 + videolink (0.9-1) unstable; urgency=low * New upstream version diff --git a/debian/rules b/debian/rules index 3e48256..ff70afd 100755 --- a/debian/rules +++ b/debian/rules @@ -10,13 +10,13 @@ binary-arch : build make DESTDIR=debian/videolink prefix=/usr install dh_strip dh_shlibdeps - # VideoLink relies on some "internal" APIs which we cannot trust - # Mozilla.org not to break between releases or even with security - # patches. So we add a dependendency on the exact same version - # of the library that we're building against. - if pkg-config --exists xulrunner-gtkmozembed; then \ - MOZ_VERSION=$$(dpkg-query -W --showformat='$${version}' libxul0d | sed 's/+b[0-9]*$$//') \ - && echo "mozilla:Depends=libxul0d (>= $$MOZ_VERSION), libxul0d (<< $${MOZ_VERSION}+b99)" >> debian/videolink.substvars ; \ + # VideoLink relies on some un-frozen APIs which may break + # between releases and even with backported security patches. + # The libxul packages have sonames and a shlibs file so we + # should get correct dependencies automatically, but this is + # not the case for mozilla-browser. + if dpkg-query -W libxul-dev >&/dev/null; then \ + echo "mozilla:Depends=" >> debian/videolink.substvars ; \ else \ MOZ_VERSION=$$(dpkg-query -W --showformat='$${version}' mozilla-browser | sed 's/+b[0-9]*$$//') \ && echo "mozilla:Depends=mozilla-browser (>= $$MOZ_VERSION), mozilla-browser (<< $${MOZ_VERSION}+b99)" >> debian/videolink.substvars ; \ -- 2.39.2 From 180cac3ff20c3a365c7f75f95b87a25229b1f1a4 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sat, 14 Oct 2006 00:49:01 +0000 Subject: [PATCH 02/16] Removed obsolete list of docs. --- debian/videolink.docs | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 debian/videolink.docs diff --git a/debian/videolink.docs b/debian/videolink.docs deleted file mode 100644 index e69de29..0000000 -- 2.39.2 From 095c46b0de5edd5ae14b4e311d54c723eb73e11f Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sat, 14 Oct 2006 00:52:28 +0000 Subject: [PATCH 03/16] Changed style-sheet application in Mozila/XULRunner 1.8 to override built-in preferences, fixing link colours. --- style_sheets.cpp | 60 ++++++++++++++++++++++++++++++++---------------- style_sheets.hpp | 29 ++++++++++++++++++----- videolink.cpp | 13 ++++------- 3 files changed, 67 insertions(+), 35 deletions(-) diff --git a/style_sheets.cpp b/style_sheets.cpp index 9c59982..1f66810 100644 --- a/style_sheets.cpp +++ b/style_sheets.cpp @@ -4,12 +4,13 @@ #include "style_sheets.hpp" #include -#include -#include -#include #if MOZ_VERSION_MAJOR > 1 || (MOZ_VERSION_MAJOR == 1 && MOZ_VERSION_MINOR >= 8) +# include # include #else +# include +# include +# include # include #endif #include @@ -19,9 +20,34 @@ using xpcom_support::check; -// Load a CSS from an (absolute) URI. -// TODO: Support loading from an absolute, or better, relative filename. -already_AddRefed load_css(const char * uri) +#if MOZ_VERSION_MAJOR > 1 || (MOZ_VERSION_MAJOR == 1 && MOZ_VERSION_MINOR >= 8) + +// We just have to load and register a style-sheet as a user +// style-sheet. There is no need to do anything for each page. + +agent_style_sheet_holder init_agent_style_sheet(const char * uri) +{ + nsCOMPtr style_sheet_uri; + check(NS_NewURI(getter_AddRefs(style_sheet_uri), nsCString(uri))); + + nsCOMPtr style_sheet_service; + static const nsCID style_sheet_service_cid = { + // NS_STYLESHEETSERVICE_CID copied from + // layout/base/nsStyleSheetService.cpp + 0xfcca6f83, 0x9f7d, 0x44e4, + {0xa7, 0x4b, 0xb5, 0x94, 0x33, 0xe6, 0xc8, 0xc3} + }; + check(CallGetService( + style_sheet_service_cid, getter_AddRefs(style_sheet_service))); + check(style_sheet_service->LoadAndRegisterSheet( + style_sheet_uri, nsIStyleSheetService::USER_SHEET)); + + return agent_style_sheet_holder(); +} + +#else // Mozilla version < 1.8 + +already_AddRefed init_agent_style_sheet(const char * uri) { nsCOMPtr css_loader; static const nsCID css_loader_cid = NS_CSS_LOADER_CID; @@ -38,25 +64,19 @@ already_AddRefed load_css(const char * uri) // Apply a style-sheet to a given presentation shell as the top-priority // agent style-sheet and disable the preferences-derived style rules. -void apply_style_sheet(nsIStyleSheet * style_sheet, nsIPresShell * pres_shell) +void apply_agent_style_sheet(nsIStyleSheet * style_sheet, + nsIPresShell * pres_shell) { nsCOMArray style_sheets; check(pres_shell->GetAgentStyleSheets(style_sheets)); - check(style_sheets.AppendObject(style_sheet)); + check(style_sheets.InsertObjectAt(style_sheet, 0)); check(pres_shell->SetAgentStyleSheets(style_sheets)); - // FIXME: We need to find an alternative that works in Mozilla 1.8. -# if MOZ_VERSION_MAJOR == 1 && MOZ_VERSION_MINOR < 8 - check(pres_shell->EnablePrefStyleRules(false)); -# endif + check(pres_shell->EnablePrefStyleRules(false)); // Update the display -# if MOZ_VERSION_MAJOR > 1 \ - || (MOZ_VERSION_MAJOR == 1 && MOZ_VERSION_MINOR >= 8) - pres_shell->ReconstructStyleData(); - check(pres_shell->FlushPendingNotifications(Flush_Display)); -# else - check(pres_shell->ReconstructStyleData()); - check(pres_shell->FlushPendingNotifications(true)); -# endif + check(pres_shell->ReconstructStyleData()); + check(pres_shell->FlushPendingNotifications(true)); } + +#endif // Mozilla version >=/< 1.8 diff --git a/style_sheets.hpp b/style_sheets.hpp index bb39b22..ef4aef3 100644 --- a/style_sheets.hpp +++ b/style_sheets.hpp @@ -9,12 +9,29 @@ class nsIPresShell; -// Load a CSS from an (absolute) URI. -// TODO: Support loading from an absolute, or better, relative filename. -already_AddRefed load_css(const char * uri); +// These functions load and apply a style-sheet as necessary, +// overriding the built-in "preferences". + +// init_agent_style_sheet() must be called once during startup +// apply_agent_style_sheet() must be called for each page + +#if MOZ_VERSION_MAJOR > 1 || (MOZ_VERSION_MAJOR == 1 && MOZ_VERSION_MINOR >= 8) + +struct agent_style_sheet_holder {}; + +// Load agent style sheet from an (absolute) URI, and register it if +// possible. +agent_style_sheet_holder init_agent_style_sheet(const char * uri); +inline void apply_agent_style_sheet(agent_style_sheet_holder, nsIPresShell *) +{} + +#else + +typedef nsCOMPtr agent_style_sheet_holder; +already_AddRefed init_agent_style_sheet(const char * uri); +void apply_agent_style_sheet(nsIStyleSheet *, nsIPresShell *); + +#endif -// Apply a style-sheet to a given presentation shell as the top-priority -// agent style-sheet and disable the preferences-derived style rules. -void apply_style_sheet(nsIStyleSheet *, nsIPresShell *); #endif // !INC_STYLESHEETS_HPP diff --git a/videolink.cpp b/videolink.cpp index 59956c7..8ab5266 100644 --- a/videolink.cpp +++ b/videolink.cpp @@ -194,7 +194,7 @@ namespace std::string output_dir_; mpeg_encoder encoder_; browser_widget browser_widget_; - nsCOMPtr stylesheet_; + agent_style_sheet_holder style_sheet_; dvd_contents contents_; typedef std::map resource_map_type; @@ -219,7 +219,8 @@ namespace : frame_params_(frame_params), output_dir_(output_dir), encoder_(encoder), - stylesheet_(load_css("file://" VIDEOLINK_SHARE_DIR "/videolink.css")), + style_sheet_(init_agent_style_sheet( + "file://"VIDEOLINK_SHARE_DIR"/videolink.css")), pending_window_update_(false), pending_req_count_(0), have_tweaked_page_(false), @@ -440,7 +441,7 @@ namespace // disable scrollbars. if (!have_tweaked_page_) { - apply_style_sheet(stylesheet_, pres_shell); + apply_agent_style_sheet(style_sheet_, pres_shell); // This actually only needs to be done once. nsCOMPtr dom_bar_prop; @@ -874,12 +875,6 @@ namespace check(pref_branch->SetBoolPref( "layout.fire_onload_after_image_background_loads", true)); - - // Turn off link underlining. This is also set in the agent - // stylesheet, but seems to be overridden by preferences in - // Mozilla 1.8. - check(pref_branch->SetBoolPref("browser.underline_anchors", - false)); # endif // Set display resolution. With standard-definition video we -- 2.39.2 From 585c5f5f2320972eb1fa87ecb915bae58a4fc301 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sat, 14 Oct 2006 00:52:59 +0000 Subject: [PATCH 04/16] Corrected link colour style rules to apply only to links. --- videolink.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/videolink.css b/videolink.css index b441499..86800b8 100644 --- a/videolink.css +++ b/videolink.css @@ -14,11 +14,11 @@ a:link, a:visited { white-space: nowrap; } /* The hover state must be made obvious since DVD players have no pointer. */ -a:hover { +a:link:hover, a:visited:hover { color: red; } /* The active state should provide visual feedback, but is not so critical. */ -a:active { +a:link:active, a:visited:active { color: purple; } /* Don't show focus rectangles. */ -- 2.39.2 From 277a4f13736cd3eac53d1301dddc2e0eecba9dba Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sat, 14 Oct 2006 00:53:28 +0000 Subject: [PATCH 05/16] Stopped setting assumed screen resolution in Mozilla/XULRunner 1.8 since the browser uses it wrongly. Documented this problem. --- README | 28 ++++++++++++++++++++++++++++ videolink.cpp | 17 +++++++++++++++-- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/README b/README index df6b8f7..c273e43 100644 --- a/README +++ b/README @@ -176,6 +176,34 @@ aspect ratio and sample rate. However, each chapter will run into the next. If this is a real problem, let me know, and I may be able to provide a better solution in a later version of VideoLink. +Bugs +---- + +Under Mozilla 1.7, VideoLink sets the assumed screen resolution to +40 dpi, which I reckon to be the average resolution of a standard +definition TV display. This should mean that text with a font size +expressed in millimetres or points will appear around the specified +size. Unfortunately this setting has a different effect under +Mozilla/XULRunner 1.8: + +Mozilla Assumed Requested Actual size +version resolution size (pixels) (inches) + (dpi) + + 1.7 default:96 20 px 20 0.5 + 1.7 default:96 36 pt 48 1.2 + 1.7 40 20 px 20 0.5 + 1.7 40 36 pt 20 0.5 + 1.8 default:96 20 px 20 0.5 + 1.8 default:96 36 pt 48 1.2 + 1.8 40 20 px 48 1.2 + 1.8 40 36 pt 48 1.2 + +From version 0.10, until I have a proper solution, VideoLink will not +set the assumed screen resolution under Mozilla 1.8. I must advise +against using font sizes in millimetres or points since they will vary +between browser versions. + Author and copyright -------------------- diff --git a/videolink.cpp b/videolink.cpp index 8ab5266..bda78ce 100644 --- a/videolink.cpp +++ b/videolink.cpp @@ -885,8 +885,21 @@ namespace // slightly different but unfortunately Mozilla doesn't // support non-square pixels (and neither do fontconfig or Xft // anyway). - check(pref_branch->SetIntPref("browser.display.screen_resolution", - 40)); + + // The browser.display.screen_resolution preference sets the + // the nominal resolution for dimensions expressed in pixels. + // (They may be scaled!) In Mozilla 1.7 it also sets the + // assumed resolution of the display - hence pixel sizes are + // respected on-screen - but this is no longer the case in + // 1.8. Therefore it was renamed to layout.css.dpi in 1.8.1. + // In 1.8 we need to set the assumed screen resolution + // separately, but don't know how yet. Setting one to 40 + // but not the other is *bad*, so currently we set neither. + +# if MOZ_VERSION_MAJOR == 1 && MOZ_VERSION_MINOR < 8 + check(pref_branch->SetIntPref("browser.display.screen_resolution", + 40)); +# endif } } // namespace -- 2.39.2 From df5fd006468fed2f1c10e949993fe849d4fb453e Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sat, 14 Oct 2006 00:53:48 +0000 Subject: [PATCH 06/16] Made source dependency generation more efficient. --- Makefile | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 81566a7..e001b0a 100644 --- a/Makefile +++ b/Makefile @@ -98,17 +98,14 @@ install : -DMOZ_VERSION_MINOR=$(moz_version_minor) \ -DMOZ_VERSION_PATCHLEVEL=$(moz_version_patchlevel) -.objs/%.d : %.cpp .objs/.created - $(CXX) $(CXXFLAGS) $(CPPFLAGS) -MM -MF $@ $< - -.objs/%.d : %.c .objs/.created - $(CC) $(CFLAGS) $(CPPFLAGS) -MM -MF $@ $< +.objs/%.d : .objs/.created + touch $@ .objs/%.o : %.cpp .objs/.created - $(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $@ -c $< + $(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $@ -MD -MF .objs/$*.d -c $< .objs/%.o : %.c .objs/.created - $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ -c $< + $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ -MD -MF .objs/$*.d -c $< %/.created : mkdir -p $* -- 2.39.2 From 1c05822d40aae48b8a9a971ba909641379d0709e Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sat, 14 Oct 2006 00:54:14 +0000 Subject: [PATCH 07/16] Released version 0.10 and version 0.10-1. --- ChangeLog | 11 +++++++++++ debian/changelog | 6 ++++++ 2 files changed, 17 insertions(+) diff --git a/ChangeLog b/ChangeLog index 1fc78a3..8482890 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +videolink (0.10) unstable; urgency=low + + * Changed style-sheet application in Mozila/XULRunner 1.8 to override + built-in preferences, fixing link colours + * Corrected link colour style rules to apply only to links + * Stopped setting assumed screen resolution in Mozilla/XULRunner 1.8 + since the browser uses it wrongly + * Made source dependency generation more efficient + + -- Ben Hutchings Sun, 10 Sep 2006 14:43:15 +0100 + videolink (0.9) unstable; urgency=low * Minor build and installation improvements diff --git a/debian/changelog b/debian/changelog index d3be7f4..e840519 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +videolink (0.10-1) unstable; urgency=low + + * New upstream version - closes: #386832 + + -- Ben Hutchings Sun, 10 Sep 2006 17:44:40 +0100 + videolink (0.9-2) unstable; urgency=low * Removed strict version dependency on libxul0d on advice of its -- 2.39.2 From f5d9069647f70b7aab8e656f59cf42176c419461 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sat, 14 Oct 2006 01:03:15 +0000 Subject: [PATCH 08/16] Moved generation of menu VOBs from videolink_window to dvd_generator. Fixed operation of "top menu" or "title menu" button. Added explicit aspect ratio to menu streams encoded with ffmpeg, since some players will default to 16:9 otherwise. Fixed off-by-one error in link coordinates passed to spumux. Changed default padding for the body element to 10% of frame dimensions, a common rule for the title-safe area. Added explicit assignment of actions to direction buttons since dvdauthor's policy doesn't seem to work that well. Documented limit of 119 menus discovered by Mark Burton. Fixed an occasional problem of links appearing in their hover state initially due to the pointer being in the middle of the virtual framebuffer. --- ChangeLog | 17 ++ Makefile | 10 +- README | 20 +- TODO | 7 +- debian/changelog | 6 + generate_dvd.cpp | 313 ++++++++++++++++++++++++++----- generate_dvd.hpp | 66 ++++++- geometry.hpp | 51 ++++++ ntsc.css | 4 + pal.css | 4 + pixbufs.cpp | 16 +- pixbufs.hpp | 8 +- video.hpp | 2 +- videolink.cpp | 469 ++++++++++++++++++----------------------------- videolink.css | 2 - warp_pointer.cpp | 16 ++ warp_pointer.hpp | 10 + 17 files changed, 648 insertions(+), 373 deletions(-) create mode 100644 geometry.hpp create mode 100644 ntsc.css create mode 100644 pal.css create mode 100644 warp_pointer.cpp create mode 100644 warp_pointer.hpp diff --git a/ChangeLog b/ChangeLog index 8482890..2ad2df2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +videolink (0.11) unstable; urgency=low + + * Fixed operation of "top menu" or "title menu" button + * Added explicit aspect ratio to menu streams encoded with ffmpeg, + since some players will default to 16:9 otherwise + * Fixed off-by-one error in link coordinates passed to spumux + * Changed default padding for the body element to 10% of frame + dimensions, a common rule for the title-safe area + * Added explicit assignment of actions to direction buttons + since dvdauthor's policy doesn't seem to work that well + * Documented limit of 119 menus discovered by Mark Burton + * Fixed an occasional problem of links appearing in their hover state + initially due to the pointer being in the middle of the virtual + framebuffer + + -- Ben Hutchings Mon, 25 Sep 2006 18:11:07 +0100 + videolink (0.10) unstable; urgency=low * Changed style-sheet application in Mozila/XULRunner 1.8 to override diff --git a/Makefile b/Makefile index e001b0a..02a8030 100644 --- a/Makefile +++ b/Makefile @@ -41,8 +41,8 @@ endif cxxsources := \ auto_proc.cpp browser_widget.cpp child_iterator.cpp generate_dvd.cpp \ link_iterator.cpp null_prompt_service.cpp pixbufs.cpp style_sheets.cpp \ - temp_file.cpp video.cpp vob_list.cpp videolink.cpp x_frame_buffer.cpp \ - xml_utils.cpp xpcom_support.cpp + temp_file.cpp video.cpp vob_list.cpp videolink.cpp warp_pointer.cpp \ + x_frame_buffer.cpp xml_utils.cpp xpcom_support.cpp csources := jquant2.c videolink : $(cxxsources:%.cpp=.objs/%.o) $(csources:%.c=.objs/%.o) @@ -63,7 +63,7 @@ install : gzip -c9 videolink.1 >$(DESTDIR)$(mandir)/man1/videolink.1.gz chmod 644 $(DESTDIR)$(mandir)/man1/videolink.1.gz mkdir -p -m 755 $(DESTDIR)$(sharedir)/videolink - install -m 644 videolink.css $(DESTDIR)$(sharedir)/videolink + install -m 644 *.css $(DESTDIR)$(sharedir)/videolink .PHONY : clean install @@ -72,8 +72,8 @@ install : .objs/videolink.% \ : CPPFLAGS += -DVIDEOLINK_SHARE_DIR='"$(sharedir)/videolink"' -.objs/browser_widget.% .objs/generate_dvd.% .objs/pixbufs.% \ -.objs/temp_file.% .objs/vob_list.% .objs/videolink.% \ +.objs/browser_widget.% .objs/generate_dvd.% .objs/pixbufs.% \ +.objs/temp_file.% .objs/vob_list.% .objs/videolink.% .objs/warp_pointer.% \ : CPPFLAGS += $(shell pkg-config --cflags gtkmm-2.0) .objs/browser_widget.% .objs/child_iterator.% .objs/link_iterator.% \ diff --git a/README b/README index c273e43..e51a3e6 100644 --- a/README +++ b/README @@ -42,10 +42,10 @@ below. Linking to video You can link directly to local MPEG video files whose names end in -".vob". If you wish to combine multiple files into a single video -sequence ("title" in DVD terminology) or to add chapter marks to a -video sequence, create and link to a VOB-list file (explained below) -whose name ends in ".voblist". +".mpeg", ".mpeg2" or ".vob". If you wish to combine multiple files +into a single video sequence ("title" in DVD terminology) or to add +chapter marks to a video sequence, create and link to a VOB-list file +(explained below) whose name ends in ".voblist". VOB-lists @@ -135,9 +135,9 @@ multiple menus. The frame size is dictated by the video standard; see above. The exact visible area varies between TVs so the background should cover all or very nearly all the frame whereas the important content such as text must not be placed near the edge. For this -reason VideoLink applies a stylesheet to all pages that adds 60 pixels of -padding on all sides of the body; this doesn't apply to the -background. +reason VideoLink applies a stylesheet to all pages that adds padding +equal to 10% of the frame dimension on each side of the body; this +doesn't apply to the background. Prior to version 1.8, Mozilla may signal that a page is completely loaded before any background images are loaded and displayed. This @@ -176,6 +176,12 @@ aspect ratio and sample rate. However, each chapter will run into the next. If this is a real problem, let me know, and I may be able to provide a better solution in a later version of VideoLink. +There is a limit of 128 menus in each "domain" of a DVD, which is +further reduced by dvdauthor to a practical limit of 119 menus. +Currently VideoLink generates all menus in a single domain (the VMGM +domain). Later versions of VideoLink should support larger numbers of +menus by using multiple domains. + Bugs ---- diff --git a/TODO b/TODO index 41c7770..18c4fb9 100644 --- a/TODO +++ b/TODO @@ -4,13 +4,14 @@ Priority 2 Use ffmpeg to convert unsuitable video files (how do we check this?). Add keyboard command for "top menu" in preview mode. Add support for videos in preview mode. -Support more than 99 videos somehow (grouping them into titlesets won't help) -Allow explicit ordering of videos. +Support more than 99 titles somehow (grouping them into titlesets won't help) +Support more than 119 menus somehow. +Track down and fix/suppress the NS_BINDING_ABORTED (0x804b002) error that occasionally appears in preview mode. Priority 3 (lowest) Provide a means to specify menu & audio language. -May need to override default menu navigation actions because dvdauthor seems to cause rather undesirable behaviour when buttons are not arranged in a grid. For any page with no links, add a "back" link (this raises the issue of localisation, of course). If a page is too large, split it and add "next" and "previous" links (seems very difficult). Set Mozilla's idea of the pixel aspect ratio to match video pixels. (For extra credit, scale preview mode to correct for the differing aspect ratio.) This seems to be impossible. Avoid running Xvfb if we're only going to display an error message. +Allow explicit ordering of titles. diff --git a/debian/changelog b/debian/changelog index e840519..f1e7959 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +videolink (0.11-1) unstable; urgency=low + + * New upstream version + + -- Ben Hutchings Tue, 26 Sep 2006 02:21:15 +0100 + videolink (0.10-1) unstable; urgency=low * New upstream version - closes: #386832 diff --git a/generate_dvd.cpp b/generate_dvd.cpp index 32ce0f2..ff1b635 100644 --- a/generate_dvd.cpp +++ b/generate_dvd.cpp @@ -2,22 +2,241 @@ // See the file "COPYING" for licence details. #include +#include +#include #include +#include #include #include "dvd.hpp" #include "generate_dvd.hpp" #include "xml_utils.hpp" -dvd_contents::menu::menu() +namespace +{ + // Return a closeness metric of an "end" rectangle to a "start" + // rectangle in the upward (-1) or downward (+1) direction. Given + // several possible "end" rectangles, the one that seems visually + // closest in the given direction should have the highest value of + // this metric. This is necessarily a heuristic function! + double directed_closeness(const rectangle & start, const rectangle & end, + int y_dir) + { + // The obvious approach is to use the centres of the + // rectangles. However, for the "end" rectangle, using the + // horizontal position nearest the centre of the "start" + // rectangle seems to produce more reasonable results. For + // example, if there are two "end" rectangles equally near to + // the "start" rectangle in terms of vertical distance and one + // of them horizontally overlaps the centre of the "start" + // rectangle, we want to pick that one even if the centre of + // that rectangle is further away from the centre of the + // "start" rectangle. + int start_x = (start.left + start.right) / 2; + int start_y = (start.top + start.bottom) / 2; + int end_y = (end.top + end.bottom) / 2; + int end_x; + if (end.right < start_x) + end_x = end.right; + else if (end.left > start_x) + end_x = end.left; + else + end_x = start_x; + + // Return cosine of angle between the line between these points + // and the vertical, divided by the distance between the points + // if that is defined and positive; otherwise return 0. + int vertical_distance = (end_y - start_y) * y_dir; + if (vertical_distance <= 0) + return 0.0; + double distance_squared = + (end_x - start_x) * (end_x - start_x) + + (end_y - start_y) * (end_y - start_y); + return vertical_distance / distance_squared; + } +} + +dvd_generator::menu::menu() : vob_temp(new temp_file("videolink-vob-")) { vob_temp->close(); } -void generate_dvd(const dvd_contents & contents, - const std::string & output_dir) +dvd_generator::pgc_ref dvd_generator::add_menu() +{ + pgc_ref next_menu(menu_pgc, menus_.size()); + + // Check against maximum number of menus. It appears that no more + // than 128 menus are reachable through LinkPGCN instructions, and + // dvdauthor uses some menu numbers for special purposes, resulting + // in a practical limit of 119 per domain. We can work around this + // later by spreading some menus across titlesets. + if (next_menu.index == 119) + throw std::runtime_error("No more than 119 menus can be used"); + + menus_.resize(next_menu.index + 1); + return next_menu; +} + +void dvd_generator::add_menu_entry(unsigned index, + const rectangle & area, + const pgc_ref & target) +{ + assert(index < menus_.size()); + assert(target.type == menu_pgc && target.index < menus_.size() + || target.type == title_pgc && target.index < titles_.size()); + menu_entry new_entry = { area, target }; + menus_[index].entries.push_back(new_entry); +} + +void dvd_generator::generate_menu_vob(unsigned index, + Glib::RefPtr background, + Glib::RefPtr highlights) + const +{ + assert(index < menus_.size()); + const menu & this_menu = menus_[index]; + + temp_file background_temp("videolink-back-"); + background_temp.close(); + std::cout << "saving " << background_temp.get_name() << std::endl; + background->save(background_temp.get_name(), "png"); + + temp_file highlights_temp("videolink-links-"); + highlights_temp.close(); + std::cout << "saving " << highlights_temp.get_name() << std::endl; + highlights->save(highlights_temp.get_name(), "png"); + + temp_file spumux_temp("videolink-spumux-"); + spumux_temp.close(); + std::ofstream spumux_file(spumux_temp.get_name().c_str()); + spumux_file << + "\n" + " \n" + " \n"; + int button_count = this_menu.entries.size(); + for (int i = 0; i != button_count; ++i) + { + const menu_entry & this_entry = this_menu.entries[i]; + + // We program left and right to cycle through the buttons in + // the order the entries were added. This should result in + // left and right behaving like the tab and shift-tab keys + // would in the browser. Hopefully that's a sensible order. + // We program up and down to behave geometrically. + int up_button = i, down_button = i; + double up_closeness = 0.0, down_closeness = 0.0; + for (int j = 0; j != button_count; ++j) + { + const menu_entry & other_entry = this_menu.entries[j]; + double closeness = directed_closeness( + this_entry.area, other_entry.area, -1); + if (closeness > up_closeness) + { + up_button = j; + up_closeness = closeness; + } + else + { + closeness = directed_closeness( + this_entry.area, other_entry.area, 1); + if (closeness > down_closeness) + { + down_button = j; + down_closeness = closeness; + } + } + } + spumux_file << " \n"; + } + spumux_file << + " \n" + " \n" + "\n"; + spumux_file.close(); + if (!spumux_file) + throw std::runtime_error("Failed to write control file for spumux"); + + std::ostringstream command_stream; + if (encoder_ == mpeg_encoder_ffmpeg) + { + command_stream + << "ffmpeg" + << " -f image2 -vcodec png -i " + << background_temp.get_name() + << " -target " << frame_params_.common_name << "-dvd" + << " -vcodec mpeg2video -aspect 4:3 -an -y /dev/stdout"; + } + else + { + assert(encoder_ == mpeg_encoder_mjpegtools_old + || encoder_ == mpeg_encoder_mjpegtools_new); + command_stream + << "pngtopnm " + << background_temp.get_name() + << " | ppmtoy4m -v0 -n1 -F" + << frame_params_.rate_numer << ":" << frame_params_.rate_denom + << " -A" << frame_params_.pixel_ratio_width + << ":" << frame_params_.pixel_ratio_height + << " -Ip "; + // The chroma subsampling keywords changed between + // versions 1.6.2 and 1.8 of mjpegtools. There is no + // keyword that works with both. + if (encoder_ == mpeg_encoder_mjpegtools_old) + command_stream << "-S420_mpeg2"; + else + command_stream << "-S420mpeg2"; + command_stream << + " | mpeg2enc -v0 -f8 -a2 -o/dev/stdout" + " | mplex -v0 -f8 -o/dev/stdout /dev/stdin"; + } + command_stream + << " | spumux -v0 -mdvd " << spumux_temp.get_name() + << " > " << this_menu.vob_temp->get_name(); + std::string command(command_stream.str()); + const char * argv[] = { + "/bin/sh", "-c", command.c_str(), 0 + }; + std::cout << "running " << command << std::endl; + int command_result; + Glib::spawn_sync(".", + Glib::ArrayHandle( + argv, sizeof(argv)/sizeof(argv[0]), + Glib::OWNERSHIP_NONE), + Glib::SPAWN_STDOUT_TO_DEV_NULL, + SigC::Slot0(), + 0, 0, + &command_result); + if (command_result != 0) + throw std::runtime_error("spumux pipeline failed"); +} + +dvd_generator::pgc_ref dvd_generator::add_title(vob_list & content) +{ + pgc_ref next_title(title_pgc, titles_.size()); + + // Check against maximum number of titles. + if (next_title.index == 99) + throw std::runtime_error("No more than 99 titles can be used"); + + titles_.resize(next_title.index + 1); + titles_[next_title.index].swap(content); + return next_title; +} + +void dvd_generator::generate(const std::string & output_dir) const { temp_file temp("videolink-dvdauthor-"); temp.close(); @@ -26,8 +245,8 @@ void generate_dvd(const dvd_contents & contents, // We generate code that uses registers in the following way: // // g0: scratch - // g1: current location - // g2: location that last jumped to a title + // g1: target menu location + // g2: source/return menu location for title // g3: target chapter number // // All locations are divided into two bitfields: the least @@ -45,11 +264,9 @@ void generate_dvd(const dvd_contents & contents, " \n" " \n"; - for (unsigned menu_index = 0; - menu_index != contents.menus.size(); - ++menu_index) + for (unsigned menu_index = 0; menu_index != menus_.size(); ++menu_index) { - const dvd_contents::menu & menu = contents.menus[menu_index]; + const menu & this_menu = menus_[menu_index]; if (menu_index == 0) { @@ -58,8 +275,9 @@ void generate_dvd(const dvd_contents & contents, file << " \n" "
\n"
-		// Initialise the current location if it is not set
-		// (all general registers are initially 0).
+		// Set a default target location if none is set.
+		// This covers first play and use of the "top menu"
+		// button.
 		"          if (g1 eq 0)\n"
 		"            g1 = " << 1 + button_mult << ";\n";
 	}
@@ -70,7 +288,7 @@ void generate_dvd(const dvd_contents & contents,
 		"        
\n";
 	}
 
-	// When a title finishes or the user presses the menu
+	// When a title finishes or the user presses the "menu"
 	// button, this always jumps to the titleset's root menu.
 	// We want to return the user to the last menu they used.
 	// So we arrange for each titleset's root menu to return
@@ -95,7 +313,7 @@ void generate_dvd(const dvd_contents & contents,
 	     menu_incr != 0;
 	     menu_incr /= 2)
 	{
-	    if (menu_index + menu_incr < contents.menus.size()
+	    if (menu_index + menu_incr < menus_.size()
 		&& (menu_index & (menu_incr * 2 - 1)) == 0)
 	    {
 		file <<
@@ -109,19 +327,22 @@ void generate_dvd(const dvd_contents & contents,
 	file <<
 	    // Highlight the appropriate button.
 	    "          s8 = g1 & " << button_mask << ";\n"
+	    // Forget the link target.  If we don't do this, pressing
+	    // the "top menu" button will result in jumping back to
+	    // this same menu!
+	    "          g1 = 0;\n"
 	    "        
\n" - " \n"; + " \n"; for (unsigned button_index = 0; - button_index != menu.entries.size(); + button_index != this_menu.entries.size(); ++button_index) { - const dvd_contents::pgc_ref & target = - menu.entries[button_index]; + const pgc_ref & target = this_menu.entries[button_index].target; file << "
\n" - " \n"; + " \n"; for (unsigned button_index = 0; button_index != this_menu.entries.size(); @@ -491,7 +510,7 @@ void dvd_generator::generate(const std::string & output_dir) const const char * argv[] = { "dvdauthor", "-o", output_dir.c_str(), - "-x", temp.get_name().c_str(), + "-x", name.c_str(), 0 }; int command_result; diff --git a/generate_dvd.hpp b/generate_dvd.hpp index 7f3823f..d768163 100644 --- a/generate_dvd.hpp +++ b/generate_dvd.hpp @@ -60,10 +60,7 @@ public: }; dvd_generator(const video::frame_params & frame_params, - mpeg_encoder encoder) - : frame_params_(frame_params), - encoder_(encoder) - {} + mpeg_encoder encoder); // Create a new empty menu; return a reference to it. // The client must call generate_menu_vob() for each menu before @@ -96,17 +93,12 @@ private: // Menu definition. struct menu { - menu(); - - // Temporary file in which the menu VOB should be generated. - // This is created as an empty file and then closed. - boost::shared_ptr vob_temp; - // References to the menus and titles that the menu buttons // are meant to link to, in the same order as the buttons. std::vector entries; }; + temp_dir temp_dir_; video::frame_params frame_params_; mpeg_encoder encoder_; std::vector menus_; diff --git a/temp_file.cpp b/temp_file.cpp index fc4106c..323b358 100644 --- a/temp_file.cpp +++ b/temp_file.cpp @@ -1,4 +1,4 @@ -// Copyright 2005 Ben Hutchings . +// Copyright 2005-6 Ben Hutchings . // See the file "COPYING" for licence details. #include "temp_file.hpp" @@ -7,6 +7,8 @@ #include #include #include +#include +#include #include #include @@ -14,6 +16,31 @@ #include #include +#include + +namespace +{ + bool try_rmdir_recursive(const std::string & dir_name) + { + Glib::Dir dir(dir_name); + bool empty = true; + + for (Glib::Dir::iterator it = dir.begin(), end = dir.end(); + it != end; + ++it) + { + std::string full_name(Glib::build_filename(dir_name, *it)); + if (!(Glib::file_test(full_name, Glib::FILE_TEST_IS_DIR) + ? try_rmdir_recursive(full_name) + : (unlink(full_name.c_str()) == 0 || errno == ENOENT))) + empty = false; + } + + return empty && (rmdir(dir_name.c_str()) == 0 || errno == ENOENT); + } + + bool do_keep_all = false; +} temp_file::temp_file(const std::string & base_name) { @@ -37,7 +64,7 @@ temp_file::~temp_file() { close(); - if (!keep_) + if (!do_keep_all) { // Don't assert that this is successful. The file could have // been removed by another process. @@ -55,9 +82,33 @@ void temp_file::close() } } -bool temp_file::keep_ = false; - void temp_file::keep_all(bool keep) { - keep_ = keep; + do_keep_all = keep; +} + +temp_dir::temp_dir(const std::string & base_name) +{ + std::string tmp_dir_name(Glib::get_tmp_dir()); + std::vector template_name; + template_name.reserve(tmp_dir_name.size() + 1 + base_name.size() + 6 + 1); + name_.reserve(tmp_dir_name.size() + 1 + base_name.size() + 6); + template_name.assign(tmp_dir_name.begin(), tmp_dir_name.end()); + template_name.insert(template_name.end(), '/'); + template_name.insert(template_name.end(), + base_name.begin(), base_name.end()); + template_name.insert(template_name.end(), 6, 'X'); + template_name.insert(template_name.end(), '\0'); + if (mkdtemp(&template_name[0])) + name_.assign(template_name.begin(), template_name.end() - 1); + else + throw std::runtime_error( + std::string("mkdtemp: ").append(std::strerror(errno))); +} + +temp_dir::~temp_dir() +{ + if (!do_keep_all && !try_rmdir_recursive(name_)) + std::cerr << "Warning: failed to remove temporary directory " + << name_ << "\n"; } diff --git a/temp_file.hpp b/temp_file.hpp index 1ead61a..9ea55f3 100644 --- a/temp_file.hpp +++ b/temp_file.hpp @@ -22,8 +22,17 @@ public: private: int fd_; std::string name_; +}; - static bool keep_; +class temp_dir +{ +public: + explicit temp_dir(const std::string & base_name); + ~temp_dir(); + const std::string & get_name() const { return name_; } + +private: + std::string name_; }; #endif // !INC_TEMP_FILE_HPP -- 2.39.2 From ef1488deebfb1a8f84ea4c0c498e50b90b75ff3d Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sat, 14 Oct 2006 02:23:02 +0000 Subject: [PATCH 10/16] Increased number of frames in menu, defined a cell covering each menu, and moved still time from menu PGCs to cells. This should result in more reliable freeze-framing. --- generate_dvd.cpp | 53 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/generate_dvd.cpp b/generate_dvd.cpp index aa57775..398fdd1 100644 --- a/generate_dvd.cpp +++ b/generate_dvd.cpp @@ -72,6 +72,16 @@ namespace return Glib::build_filename(dir.get_name(), base_name); } + + // We would like to use just a single frame for the menu but this + // seems not to be legal or compatible. The minimum length of a + // cell is 0.4 seconds but I've seen a static menu using 12 frames + // on a "PAL" disc so let's say 0.5 seconds rounded down. + const char menu_duration_string[] = "0.5"; + unsigned menu_duration_frames(const video::frame_params & params) + { + return params.rate_numer / params.rate_denom / 2; + } } dvd_generator::dvd_generator(const video::frame_params & frame_params, @@ -188,23 +198,31 @@ void dvd_generator::generate_menu_vob(unsigned index, throw std::runtime_error("Failed to write control file for spumux"); std::ostringstream command_stream; + unsigned frame_count(menu_duration_frames(frame_params_)); if (encoder_ == mpeg_encoder_ffmpeg) { - command_stream - << "ffmpeg" - << " -f image2 -vcodec png -i " - << background_name - << " -target " << frame_params_.common_name << "-dvd" - << " -vcodec mpeg2video -aspect 4:3 -an -y /dev/stdout"; + for (unsigned i = 0; i != frame_count; ++i) + { + std::string frame_name(background_name); + frame_name.push_back('-'); + frame_name.push_back('0' + i / 10); + frame_name.push_back('0' + i % 10); + if (symlink(background_name.c_str(), frame_name.c_str()) != 0) + throw std::runtime_error( + std::string("symlink: ").append(std::strerror(errno))); + } + command_stream << + "ffmpeg -f image2 -vcodec png -i " << background_name << "-%02d" + " -target " << frame_params_.common_name << "-dvd" + " -vcodec mpeg2video -aspect 4:3 -an -y /dev/stdout"; } else { assert(encoder_ == mpeg_encoder_mjpegtools_old || encoder_ == mpeg_encoder_mjpegtools_new); command_stream - << "pngtopnm " - << background_name - << " | ppmtoy4m -v0 -n1 -F" + << "pngtopnm " << background_name + << " | ppmtoy4m -v0 -n" << frame_count << " -F" << frame_params_.rate_numer << ":" << frame_params_.rate_denom << " -A" << frame_params_.pixel_ratio_width << ":" << frame_params_.pixel_ratio_height @@ -290,7 +308,7 @@ void dvd_generator::generate(const std::string & output_dir) const // This is the first (title) menu, displayed when the // disc is first played. file << - " \n" + " \n" "
\n"
 		// Set a default target location if none is set.
 		// This covers first play and use of the "top menu"
@@ -301,7 +319,7 @@ void dvd_generator::generate(const std::string & output_dir) const
 	else
 	{
 	    file <<
-		"      \n"
+		"      \n"
 		"        
\n";
 	}
 
@@ -351,7 +369,13 @@ void dvd_generator::generate(const std::string & output_dir) const
 	    "        
\n" " \n"; + << "'>\n" + // Define a cell covering the whole menu and set a still + // time at the end of that, since it seems all players + // support that but some ignore a still time set on a PGC. + " \n" + " \n"; for (unsigned button_index = 0; button_index != this_menu.entries.size(); @@ -410,11 +434,6 @@ void dvd_generator::generate(const std::string & output_dir) const } file << - // Some DVD players don't seem to obey pause='inf' so make - // them loop. - " \n" - " jump cell 1;\n" - " \n" "
\n"; } -- 2.39.2 From 07a027ef87333662b3709215025838646ee3d6be Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sun, 15 Oct 2006 00:57:16 +0000 Subject: [PATCH 11/16] Added more standard headers that are strictly required. Added explicit input frame rate to ffmpeg command line since the assumed default is 25 fps and *not* the output frame rate. Changed menu duration to 12 frames regardless of frame rate since this *should* be legal at 29.97 fps and it seems to avoid some problematic rounding errors. --- generate_dvd.cpp | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/generate_dvd.cpp b/generate_dvd.cpp index 398fdd1..64079d2 100644 --- a/generate_dvd.cpp +++ b/generate_dvd.cpp @@ -1,8 +1,12 @@ // Copyright 2005-6 Ben Hutchings . // See the file "COPYING" for licence details. +#include +#include #include +#include #include +#include #include #include @@ -76,11 +80,16 @@ namespace // We would like to use just a single frame for the menu but this // seems not to be legal or compatible. The minimum length of a // cell is 0.4 seconds but I've seen a static menu using 12 frames - // on a "PAL" disc so let's say 0.5 seconds rounded down. - const char menu_duration_string[] = "0.5"; + // on a commercial "PAL" disc so let's use 12 frames regardless. unsigned menu_duration_frames(const video::frame_params & params) { - return params.rate_numer / params.rate_denom / 2; + return 12; + } + double menu_duration_seconds(const video::frame_params & params) + { + return double(menu_duration_frames(params)) + * double(params.rate_numer) + / double(params.rate_denom); } } @@ -212,7 +221,10 @@ void dvd_generator::generate_menu_vob(unsigned index, std::string("symlink: ").append(std::strerror(errno))); } command_stream << - "ffmpeg -f image2 -vcodec png -i " << background_name << "-%02d" + "ffmpeg -f image2 -vcodec png" + " -r " << frame_params_.rate_numer << + "/" << frame_params_.rate_denom << + " -i " << background_name << "-%02d" " -target " << frame_params_.common_name << "-dvd" " -vcodec mpeg2video -aspect 4:3 -an -y /dev/stdout"; } @@ -373,7 +385,9 @@ void dvd_generator::generate(const std::string & output_dir) const // Define a cell covering the whole menu and set a still // time at the end of that, since it seems all players // support that but some ignore a still time set on a PGC. - " \n" " \n"; -- 2.39.2 From 12780c6ecf9ec8c227d5795e8fd1083b48891d7b Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sun, 15 Oct 2006 00:58:32 +0000 Subject: [PATCH 12/16] Released version 1.0. Hurrah! --- ChangeLog | 10 ++++++++++ debian/changelog | 6 ++++++ 2 files changed, 16 insertions(+) diff --git a/ChangeLog b/ChangeLog index 2ad2df2..e474e5b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +videolink (1.0) unstable; urgency=low + + * The "delete once, write twice" release + * Changed creation of temporary files to use regular names under a + temporary directory + * Changed method of freeze-framing menus since some players do not + support the old method + + -- Ben Hutchings Sun, 15 Oct 2006 01:57:39 +0100 + videolink (0.11) unstable; urgency=low * Fixed operation of "top menu" or "title menu" button diff --git a/debian/changelog b/debian/changelog index f1e7959..76d1b01 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +videolink (1.0-1) unstable; urgency=low + + * New upstream version + + -- Ben Hutchings Sun, 15 Oct 2006 01:57:44 +0100 + videolink (0.11-1) unstable; urgency=low * New upstream version -- 2.39.2 From 856f9bfe9778a88ff359436c64c3e104fe5f56dc Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sun, 15 Oct 2006 01:07:55 +0000 Subject: [PATCH 13/16] Updated Standards-Version to 3.7.2. No changes are required to comply with the new version. --- debian/changelog | 3 ++- debian/control | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index 76d1b01..e96d34c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,8 +1,9 @@ videolink (1.0-1) unstable; urgency=low * New upstream version + * Updated Standards-Version to 3.7.2 (no other changes required) - -- Ben Hutchings Sun, 15 Oct 2006 01:57:44 +0100 + -- Ben Hutchings Sun, 15 Oct 2006 02:05:46 +0100 videolink (0.11-1) unstable; urgency=low diff --git a/debian/control b/debian/control index fc313c3..4072ffe 100644 --- a/debian/control +++ b/debian/control @@ -3,7 +3,7 @@ Maintainer: Ben Hutchings Section: graphics Priority: extra Build-Depends: debhelper (>=4), libboost-dev, libgtkmm2.0-dev, libxul-dev | mozilla-dev, libexpat1-dev -Standards-Version: 3.6.2 +Standards-Version: 3.7.2 Package: videolink Architecture: any -- 2.39.2 From b463276d863f86a4268b5cac63fc6879ad6517bc Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 1 Nov 2006 01:19:26 +0000 Subject: [PATCH 14/16] Placed DVD limit values consistently in dvd.hpp. Made limit checking consistent and placed it all in generate_dvd.cpp. --- dvd.hpp | 17 +++++++++++++---- generate_dvd.cpp | 24 +++++++++++++++--------- videolink.cpp | 14 -------------- 3 files changed, 28 insertions(+), 27 deletions(-) diff --git a/dvd.hpp b/dvd.hpp index 9811fa3..db0f983 100644 --- a/dvd.hpp +++ b/dvd.hpp @@ -4,18 +4,27 @@ namespace dvd { // Maximum number of buttons in a menu. - const int menu_buttons_max = 36; + const unsigned menu_buttons_max = 36; // Number of colours allowed in each button. // Buttons can change colour when they are selected. - const int button_n_colours = 4; + const unsigned button_n_colours = 4; // DVD virtual machine register size. - const int reg_bits = 16; + const unsigned reg_bits = 16; // Number by which button numbers must be multiplied when stored in // system register 8. - const int reg_s8_button_mult = 0x400; + const unsigned reg_s8_button_mult = 0x400; + + // Maximum number of PGCs in a domain that can be linked to. + // dvdauthor uses some menu numbers for special purposes, + // resulting in a practical limit of 119 per domain. + const unsigned domain_pgcs_max = 119; + + // Maximum number of titles on a disc. (Also the maximum number of + // titlesets per disc.) + const unsigned titles_max = 99; } #endif // !INC_DVD_HPP diff --git a/generate_dvd.cpp b/generate_dvd.cpp index 64079d2..7f496c2 100644 --- a/generate_dvd.cpp +++ b/generate_dvd.cpp @@ -91,6 +91,13 @@ namespace * double(params.rate_numer) / double(params.rate_denom); } + + void throw_length_error(const char * limit_type, std::size_t limit) + { + std::ostringstream oss; + oss << "exceeded DVD limit: " << limit_type << " > " << limit; + throw std::length_error(oss.str()); + } } dvd_generator::dvd_generator(const video::frame_params & frame_params, @@ -104,13 +111,8 @@ dvd_generator::pgc_ref dvd_generator::add_menu() { pgc_ref next_menu(menu_pgc, menus_.size()); - // Check against maximum number of menus. It appears that no more - // than 128 menus are reachable through LinkPGCN instructions, and - // dvdauthor uses some menu numbers for special purposes, resulting - // in a practical limit of 119 per domain. We can work around this - // later by spreading some menus across titlesets. - if (next_menu.index == 119) - throw std::runtime_error("No more than 119 menus can be used"); + if (next_menu.index == dvd::domain_pgcs_max) + throw_length_error("number of menus", dvd::domain_pgcs_max); menus_.resize(next_menu.index + 1); return next_menu; @@ -123,6 +125,10 @@ void dvd_generator::add_menu_entry(unsigned index, assert(index < menus_.size()); assert(target.type == menu_pgc && target.index < menus_.size() || target.type == title_pgc && target.index < titles_.size()); + + if (menus_[index].entries.size() == dvd::menu_buttons_max) + throw_length_error("number of buttons", dvd::menu_buttons_max); + menu_entry new_entry = { area, target }; menus_[index].entries.push_back(new_entry); } @@ -276,8 +282,8 @@ dvd_generator::pgc_ref dvd_generator::add_title(vob_list & content) pgc_ref next_title(title_pgc, titles_.size()); // Check against maximum number of titles. - if (next_title.index == 99) - throw std::runtime_error("No more than 99 titles can be used"); + if (next_title.index == dvd::titles_max) + throw_length_error("number of titles", dvd::titles_max); titles_.resize(next_title.index + 1); titles_[next_title.index].swap(content); diff --git a/videolink.cpp b/videolink.cpp index 3d88f4e..a5792bb 100644 --- a/videolink.cpp +++ b/videolink.cpp @@ -428,7 +428,6 @@ namespace Gdk::COLORSPACE_RGB, true, 8, // has_alpha, bits_per_sample width, height)), - link_num(0), links_it(doc), link_changing(false) { @@ -437,7 +436,6 @@ namespace Glib::RefPtr norm_pixbuf; Glib::RefPtr diff_pixbuf; - unsigned link_num; link_iterator links_it, links_end; rectangle link_rect; @@ -609,18 +607,6 @@ namespace continue; } - ++state->link_num; - - if (state->link_num >= unsigned(dvd::menu_buttons_max)) - { - if (state->link_num == unsigned(dvd::menu_buttons_max)) - std::cerr << "No more than " << dvd::menu_buttons_max - << " buttons can be placed on a menu\n"; - std::cerr << "Ignoring link to " << uri_and_fragment - << "\n"; - continue; - } - // Check whether this is a link to a video or a page then // add it to the known resources if not already seen; then // add it to the menu entries. -- 2.39.2 From 2bc553f13070e61f28fb28ec333d9abd710d2b51 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 1 Nov 2006 01:32:40 +0000 Subject: [PATCH 15/16] Moved dvdauthor quirk out of dvd.hpp. --- dvd.hpp | 4 +--- generate_dvd.cpp | 11 +++++++++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/dvd.hpp b/dvd.hpp index db0f983..f1b1bb1 100644 --- a/dvd.hpp +++ b/dvd.hpp @@ -18,9 +18,7 @@ namespace dvd const unsigned reg_s8_button_mult = 0x400; // Maximum number of PGCs in a domain that can be linked to. - // dvdauthor uses some menu numbers for special purposes, - // resulting in a practical limit of 119 per domain. - const unsigned domain_pgcs_max = 119; + const unsigned domain_pgcs_max = 127; // Maximum number of titles on a disc. (Also the maximum number of // titlesets per disc.) diff --git a/generate_dvd.cpp b/generate_dvd.cpp index 7f496c2..eb8fc04 100644 --- a/generate_dvd.cpp +++ b/generate_dvd.cpp @@ -98,6 +98,13 @@ namespace oss << "exceeded DVD limit: " << limit_type << " > " << limit; throw std::length_error(oss.str()); } + + // dvdauthor uses some menu numbers to represent entry points - + // distinct from the actual numbers of the menus assigned as those + // entry points - resulting in a practical limit of 119 per + // domain. This seems to be an oddity of the parser that could be + // fixed, but for now we'll have to work with it. + const unsigned dvdauthor_anonymous_menus_max = dvd::domain_pgcs_max - 8; } dvd_generator::dvd_generator(const video::frame_params & frame_params, @@ -111,8 +118,8 @@ dvd_generator::pgc_ref dvd_generator::add_menu() { pgc_ref next_menu(menu_pgc, menus_.size()); - if (next_menu.index == dvd::domain_pgcs_max) - throw_length_error("number of menus", dvd::domain_pgcs_max); + if (next_menu.index == dvdauthor_anonymous_menus_max) + throw_length_error("number of menus", dvdauthor_anonymous_menus_max); menus_.resize(next_menu.index + 1); return next_menu; -- 2.39.2 From 3a7baf39d3211c0bda3de1ab2b657e024a35b8af Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 30 Nov 2006 02:38:56 +0000 Subject: [PATCH 16/16] Corrected formula in menu_duration_seconds. It looks like any sufficiently large return value will actually work, but let's try the right one! --- generate_dvd.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/generate_dvd.cpp b/generate_dvd.cpp index eb8fc04..5d357e6 100644 --- a/generate_dvd.cpp +++ b/generate_dvd.cpp @@ -88,8 +88,8 @@ namespace double menu_duration_seconds(const video::frame_params & params) { return double(menu_duration_frames(params)) - * double(params.rate_numer) - / double(params.rate_denom); + / double(params.rate_numer) + * double(params.rate_denom); } void throw_length_error(const char * limit_type, std::size_t limit) -- 2.39.2