summaryrefslogtreecommitdiffstats
path: root/contrib/libdvdnav/A01-program-info.patch
blob: 531741b84356e025c7efd1c5e4d34fa0dc2136d6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
diff -Naur libdvdnav.orig/src/dvdnav/dvdnav.h libdvdnav/src/dvdnav/dvdnav.h
--- libdvdnav.orig/src/dvdnav/dvdnav.h	2009-03-13 18:28:22.000000000 -0700
+++ libdvdnav/src/dvdnav/dvdnav.h	2009-04-30 10:56:29.000000000 -0700
@@ -279,6 +279,11 @@
 dvdnav_status_t dvdnav_part_play(dvdnav_t *self, int32_t title, int32_t part);
 
 /*
+ * Plays the specified title, starting from the specified program
+ */
+dvdnav_status_t dvdnav_program_play(dvdnav_t *this, int32_t title, int32_t pgcn, int32_t pgn);
+
+/*
  * Stores in *times an array (that the application *must* free) of
  * dvdtimes corresponding to the chapter times for the chosen title.
  * *duration will have the duration of the title
@@ -320,6 +325,13 @@
 					  int32_t *part);
 
 /*
+ * Return the title number, pgcn and pgn currently being played.
+ * A title of 0 indicates, we are in a menu.
+ */
+dvdnav_status_t dvdnav_current_title_program(dvdnav_t *self, int32_t *title,
+					  int32_t *pgcn, int32_t *pgn);
+
+/*
  * Return the current position (in blocks) within the current
  * title and the length (in blocks) of said title.
  *
diff -Naur libdvdnav.orig/src/navigation.c libdvdnav/src/navigation.c
--- libdvdnav.orig/src/navigation.c	2009-01-08 14:57:11.000000000 -0800
+++ libdvdnav/src/navigation.c	2009-04-30 10:55:47.000000000 -0700
@@ -122,10 +122,90 @@
   return DVDNAV_STATUS_ERR;
 }
 
+dvdnav_status_t dvdnav_current_title_program(dvdnav_t *this, int32_t *title, int32_t *pgcn, int32_t *pgn) {
+  int32_t retval;
+  int32_t part;
+
+  pthread_mutex_lock(&this->vm_lock);
+  if (!this->vm->vtsi || !this->vm->vmgi) {
+    printerr("Bad VM state.");
+    pthread_mutex_unlock(&this->vm_lock);
+    return DVDNAV_STATUS_ERR;
+  }
+  if (!this->started) {
+    printerr("Virtual DVD machine not started.");
+    pthread_mutex_unlock(&this->vm_lock);
+    return DVDNAV_STATUS_ERR;
+  }
+  if (!this->vm->state.pgc) {
+    printerr("No current PGC.");
+    pthread_mutex_unlock(&this->vm_lock);
+    return DVDNAV_STATUS_ERR;
+  }
+  if ( (this->vm->state.domain == VTSM_DOMAIN)
+      || (this->vm->state.domain == VMGM_DOMAIN) ) {
+    /* Get current Menu ID: into *part. */
+    if(! vm_get_current_menu(this->vm, &part)) {
+      pthread_mutex_unlock(&this->vm_lock);
+      return DVDNAV_STATUS_ERR;
+    }
+    if (part > -1) {
+      *title = 0;
+      *pgcn = this->vm->state.pgcN;
+      *pgn = this->vm->state.pgN;
+      pthread_mutex_unlock(&this->vm_lock);
+      return DVDNAV_STATUS_OK;
+    }
+  }
+  if (this->vm->state.domain == VTS_DOMAIN) {
+    retval = vm_get_current_title_part(this->vm, title, &part);
+    *pgcn = this->vm->state.pgcN;
+    *pgn = this->vm->state.pgN;
+    pthread_mutex_unlock(&this->vm_lock);
+    return retval ? DVDNAV_STATUS_OK : DVDNAV_STATUS_ERR;
+  }
+  printerr("Not in a title or menu.");
+  pthread_mutex_unlock(&this->vm_lock);
+  return DVDNAV_STATUS_ERR;
+}
+
 dvdnav_status_t dvdnav_title_play(dvdnav_t *this, int32_t title) {
   return dvdnav_part_play(this, title, 1);
 }
 
+dvdnav_status_t dvdnav_program_play(dvdnav_t *this, int32_t title, int32_t pgcn, int32_t pgn) {
+  int32_t retval;
+
+  pthread_mutex_lock(&this->vm_lock);
+  if (!this->vm->vmgi) {
+    printerr("Bad VM state.");
+    pthread_mutex_unlock(&this->vm_lock);
+    return DVDNAV_STATUS_ERR;
+  }
+  if (!this->started) {
+    /* don't report an error but be nice */
+    vm_start(this->vm);
+    this->started = 1;
+  }
+  if (!this->vm->state.pgc) {
+    printerr("No current PGC.");
+    pthread_mutex_unlock(&this->vm_lock);
+    return DVDNAV_STATUS_ERR;
+  }
+  if((title < 1) || (title > this->vm->vmgi->tt_srpt->nr_of_srpts)) {
+    printerr("Title out of range.");
+    pthread_mutex_unlock(&this->vm_lock);
+    return DVDNAV_STATUS_ERR;
+  }
+
+  retval = vm_jump_title_program(this->vm, title, pgcn, pgn);
+  if (retval)
+    this->vm->hop_channel++;
+  pthread_mutex_unlock(&this->vm_lock);
+
+  return retval ? DVDNAV_STATUS_OK : DVDNAV_STATUS_ERR;
+}
+
 dvdnav_status_t dvdnav_part_play(dvdnav_t *this, int32_t title, int32_t part) {
   int32_t retval;
 
diff -Naur libdvdnav.orig/src/vm/vm.c libdvdnav/src/vm/vm.c
--- libdvdnav.orig/src/vm/vm.c	2009-03-13 18:28:22.000000000 -0700
+++ libdvdnav/src/vm/vm.c	2009-04-30 11:07:35.000000000 -0700
@@ -83,6 +83,8 @@
 static int  set_PTT(vm_t *vm, int tt, int ptt);
 static int  set_VTS_TT(vm_t *vm, int vtsN, int vts_ttn);
 static int  set_VTS_PTT(vm_t *vm, int vtsN, int vts_ttn, int part);
+static int  set_PROG(vm_t *vm, int tt, int pgcn, int pgn);
+static int  set_VTS_PROG(vm_t *vm, int vtsN, int vts_ttn, int pgcn, int pgn);
 static int  set_FP_PGC(vm_t *vm);
 static int  set_MENU(vm_t *vm, int menu);
 static int  set_PGCN(vm_t *vm, int pgcN);
@@ -516,6 +518,24 @@
   return 1;
 }
 
+int vm_jump_title_program(vm_t *vm, int title, int pgcn, int pgn) {
+  link_t link;
+
+  if(!set_PROG(vm, title, pgcn, pgn))
+    return 0;
+  /* Some DVDs do not want us to jump directly into a title and have
+   * PGC pre commands taking us back to some menu. Since we do not like that,
+   * we do not execute PGC pre commands that would do a jump. */
+  /* process_command(vm, play_PGC_PG(vm, (vm->state).pgN)); */
+  link = play_PGC_PG(vm, (vm->state).pgN);
+  if (link.command != PlayThis)
+    /* jump occured -> ignore it and play the PG anyway */
+    process_command(vm, play_PG(vm));
+  else
+    process_command(vm, link);
+  return 1;
+}
+
 int vm_jump_title_part(vm_t *vm, int title, int part) {
   link_t link;
 
@@ -1644,6 +1664,42 @@
   return res;
 }
 
+static int set_PROG(vm_t *vm, int tt, int pgcn, int pgn) {
+  assert(tt <= vm->vmgi->tt_srpt->nr_of_srpts);
+  return set_VTS_PROG(vm, vm->vmgi->tt_srpt->title[tt - 1].title_set_nr,
+		     vm->vmgi->tt_srpt->title[tt - 1].vts_ttn, pgcn, pgn);
+}
+
+static int set_VTS_PROG(vm_t *vm, int vtsN, int vts_ttn, int pgcn, int pgn) {
+  int pgcN, pgN, res, title, part;
+
+  (vm->state).domain = VTS_DOMAIN;
+
+  if (vtsN != (vm->state).vtsN)
+    if (!ifoOpenNewVTSI(vm, vm->dvd, vtsN))  /* Also sets (vm->state).vtsN */
+      return 0;
+
+  if ((vts_ttn < 1) || (vts_ttn > vm->vtsi->vts_ptt_srpt->nr_of_srpts)) {
+    return 0;
+  }
+
+  pgcN = pgcn;
+  pgN = pgn;
+
+  (vm->state).TT_PGCN_REG = pgcN;
+  (vm->state).TTN_REG     = get_TT(vm, vtsN, vts_ttn);
+  assert( (vm->state.TTN_REG) != 0 );
+  (vm->state).VTS_TTN_REG = vts_ttn;
+  (vm->state).vtsN        = vtsN;  /* Not sure about this one. We can get to it easily from TTN_REG */
+  /* Any other registers? */
+
+  res = set_PGCN(vm, pgcN);   /* This clobber's state.pgN (sets it to 1), but we don't want clobbering here. */
+  (vm->state).pgN = pgN;
+  vm_get_current_title_part(vm, &title, &part);
+  (vm->state).PTTN_REG    = part;
+  return res;
+}
+
 static int set_FP_PGC(vm_t *vm) {
   (vm->state).domain = FP_DOMAIN;
   if (!vm->vmgi->first_play_pgc) {
diff -Naur libdvdnav.orig/src/vm/vm.h libdvdnav/src/vm/vm.h
--- libdvdnav.orig/src/vm/vm.h	2009-03-13 18:28:22.000000000 -0700
+++ libdvdnav/src/vm/vm.h	2009-04-30 10:57:02.000000000 -0700
@@ -139,6 +139,7 @@
 int vm_jump_pg(vm_t *vm, int pg);
 int vm_jump_cell_block(vm_t *vm, int cell, int block);
 int vm_jump_title_part(vm_t *vm, int title, int part);
+int vm_jump_title_program(vm_t *vm, int title, int pgcn, int pgn);
 int vm_jump_top_pg(vm_t *vm);
 int vm_jump_next_pg(vm_t *vm);
 int vm_jump_prev_pg(vm_t *vm);