]> git.decadent.org.uk Git - videolink.git/commitdiff
Implemented jumping to chapters by setting a register in each button linking to a...
authorBen Hutchings <ben@decadent.org.uk>
Sun, 6 Aug 2006 12:19:38 +0000 (12:19 +0000)
committerBen Hutchings <ben@decadent.org.uk>
Sun, 2 Nov 2008 23:40:01 +0000 (23:40 +0000)
Changed index variable naming to use _index suffix if 0-based and _num suffix if 1-based.

TODO
generate_dvd.cpp

diff --git a/TODO b/TODO
index 1c64870827120ade6ee1f6ccf6e99fde29fc1909..7bf02e232b593518d61886ea566998f7b1e03ab8 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,6 +1,5 @@
 Priority 1 (highest)
 Investigate and fix the crash that occurs after we trigger exit from null_prompt_service.
-Make linking to chapters actually work.
 
 Priority 2
 Use ffmpeg to convert unsuitable video files (how do we check this?).
index 9f15d2f96a903e3d8dd73d74cadeb2788bcef142..6c507b9b26cd4a528fc92def995ab4957be9ecd6 100644 (file)
@@ -27,7 +27,8 @@ void generate_dvd(const dvd_contents & contents,
     //
     // g0:     scratch
     // g1:     current location
-    // g12:    location that last jumped to a video
+    // g2:     location that last jumped to a title
+    // g3:     target chapter number
     //
     // All locations are divided into two bitfields: the least
     // significant 10 bits are a page/menu number and the most
@@ -44,13 +45,13 @@ void generate_dvd(const dvd_contents & contents,
        "  <vmgm>\n"
        "    <menus>\n";
            
-    for (unsigned menu_num = 0;
-        menu_num != contents.menus.size();
-        ++menu_num)
+    for (unsigned menu_index = 0;
+        menu_index != contents.menus.size();
+        ++menu_index)
     {
-       const dvd_contents::menu & menu = contents.menus[menu_num];
+       const dvd_contents::menu & menu = contents.menus[menu_index];
 
-       if (menu_num == 0)
+       if (menu_index == 0)
        {
            // This is the first (title) menu, displayed when the
            // disc is first played.
@@ -94,13 +95,13 @@ void generate_dvd(const dvd_contents & contents,
             menu_incr != 0;
             menu_incr /= 2)
        {
-           if (menu_num + menu_incr < contents.menus.size()
-               && (menu_num & (menu_incr * 2 - 1)) == 0)
+           if (menu_index + menu_incr < contents.menus.size()
+               && (menu_index & (menu_incr * 2 - 1)) == 0)
            {
                file <<
-                   "          if (g0 ge " << 1 + menu_num + menu_incr
+                   "          if (g0 ge " << 1 + menu_index + menu_incr
                                           << ")\n"
-                   "            jump menu " << 1 + menu_num + menu_incr
+                   "            jump menu " << 1 + menu_index + menu_incr
                                           << ";\n";
            }
        }
@@ -111,12 +112,12 @@ void generate_dvd(const dvd_contents & contents,
            "        </pre>\n"
            "        <vob file='" << menu.vob_temp->get_name() << "'/>\n";
 
-       for (unsigned button_num = 0;
-            button_num != menu.entries.size();
-            ++button_num)
+       for (unsigned button_index = 0;
+            button_index != menu.entries.size();
+            ++button_index)
        {
            const dvd_contents::pgc_ref & target =
-               menu.entries[button_num];
+               menu.entries[button_index];
 
            file << "        <button> ";
 
@@ -138,36 +139,37 @@ void generate_dvd(const dvd_contents & contents,
                        target_menu_entries =
                        contents.menus[target.index].entries;
                    dvd_contents::pgc_ref this_pgc(dvd_contents::menu_pgc,
-                                                  menu_num);
+                                                  menu_index);
                    target_button_num = target_menu_entries.size();
                    while (target_button_num != 0
-                          && (target_menu_entries[--target_button_num]
+                          && (target_menu_entries[target_button_num - 1]
                               != this_pgc))
-                       ;
-                   target_button_num += 1;
+                       --target_button_num;
                }
                         
-               file << "g1 = "
-                    << (1 + target.index
-                        + target_button_num * button_mult)
-                    << "; jump menu " << 1 + target.index << ";";
+               file <<
+                   // Set new menu location.
+                   "g1 = " << (1 + target.index
+                               + target_button_num * button_mult) << "; "
+                   // Jump to the target menu.
+                   "jump menu " << 1 + target.index << "; ";
            }
            else
            {
                assert(target.type == dvd_contents::title_pgc);
 
-               file << "g1 = "
-                    << 1 + menu_num + (1 + button_num) * button_mult
-                    << "; jump title "
-                    << 1 + target.index;
-               // FIXME: Here we should check target.sub_index and
-               // jump to a specific chapter if it is non-zero.
-               // However, we can't jump directly to chapters from
-               // the VMGM.
-               file << ";";
+               file <<
+                   // Record current menu location (g1 specifies this
+                   // menu but not necessarily this button).
+                   "g1 = " << (1 + menu_index
+                               + (1 + button_index) * button_mult) << "; "
+                   // Set target chapter number.
+                   "g3 = " << target.sub_index << "; "
+                   // Jump to the target title.
+                   "jump title " << 1 + target.index << "; ";
            }
 
-           file <<  " </button>\n";
+           file <<  "</button>\n";
        }
 
        file <<
@@ -186,9 +188,9 @@ void generate_dvd(const dvd_contents & contents,
     // Generate a titleset for each title.  This appears to make
     // jumping to titles a whole lot simpler (but limits us to 99
     // titles).
-    for (unsigned title_num = 0;
-        title_num != contents.titles.size();
-        ++title_num)
+    for (unsigned title_index = 0;
+        title_index != contents.titles.size();
+        ++title_index)
     {
        file <<
            "  <titleset>\n"
@@ -201,11 +203,46 @@ void generate_dvd(const dvd_contents & contents,
            "    </menus>\n"
            "    <titles>\n"
            "      <pgc>\n"
+           "        <pre>\n"
            // Record calling location.
-           "        <pre> g12 = g1; </pre>\n";
+           "          g2 = g1;\n";
 
-       for (vob_list::const_iterator it = contents.titles[title_num].begin(),
-                end = contents.titles[title_num].end();
+       // Count chapters in the title.
+       unsigned n_chapters = 0;
+       for (vob_list::const_iterator
+                it = contents.titles[title_index].begin(),
+                end = contents.titles[title_index].end();
+            it != end;
+            ++it)
+       {
+           // Chapter start times may be specified in the "chapters"
+           // attribute as a comma-separated list.  If this is not
+           // specified then the beginning of each file starts a new
+           // chapter.  Thus the number of chapters in each file is
+           // the number of commas in the chapter attribute, plus 1.
+           ++n_chapters;
+           std::size_t pos = 0;
+           while ((pos = it->chapters.find(',', pos)) != std::string::npos)
+           {
+               ++n_chapters;
+               ++pos;
+           }
+       }
+
+       // Generate jump "table" for chapters.
+       for (unsigned chapter_num = 1;
+            chapter_num <= n_chapters;
+            ++chapter_num)
+           file <<
+               "          if (g3 == " << chapter_num << ")\n"
+               "            jump chapter " << chapter_num << ";\n";
+
+       file <<
+           "        </pre>\n";
+
+       for (vob_list::const_iterator
+                it = contents.titles[title_index].begin(),
+                end = contents.titles[title_index].end();
             it != end;
             ++it)
        {
@@ -218,12 +255,15 @@ void generate_dvd(const dvd_contents & contents,
        }
 
        file <<
+           "        <post>\n"
            // 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
-           // menu.
-           "        <post> if (g1 eq g12) g1 = g1 + " << button_mult
-            << "; call menu; </post>\n"
+           // button in the menu.
+           "          if (g1 eq g2)\n"
+           "            g1 = g1 + " << button_mult << ";\n"
+           // In any case, return to some menu.
+           "          call menu;\n"
+           "        </post>\n"
            "      </pgc>\n"
            "    </titles>\n"
            "  </titleset>\n";