Mercurial > hg > index.fcgi > dvdnav-rip > dvdnav-rip-1pba
comparison menus.c @ 2:399518436fcf
fix tabbing
author | paulo@thepaulopc |
---|---|
date | Fri, 13 Nov 2009 00:02:37 -0800 |
parents | cfe5048cc182 |
children | ffbf478b80c2 |
comparison
equal
deleted
inserted
replaced
1:f14c340e1864 | 2:516c64130cf8 |
---|---|
43 #ifdef WIN32 | 43 #ifdef WIN32 |
44 #define S_IRWXG 0 | 44 #define S_IRWXG 0 |
45 #endif | 45 #endif |
46 | 46 |
47 int main(int argc, char **argv) { | 47 int main(int argc, char **argv) { |
48 dvdnav_t *dvdnav; | 48 dvdnav_t *dvdnav; |
49 uint8_t mem[DVD_VIDEO_LB_LEN]; | 49 uint8_t mem[DVD_VIDEO_LB_LEN]; |
50 int finished = 0; | 50 int finished = 0; |
51 int output_fd = 0; | 51 int output_fd = 0; |
52 int dump = 0, tt_dump = 0, tt_skip = 0; | 52 int dump = 0, tt_dump = 0, tt_skip = 0; |
53 | 53 |
54 /* open dvdnav handle */ | 54 /* open dvdnav handle */ |
55 printf("Opening DVD...\n"); | 55 printf("Opening DVD...\n"); |
56 if (dvdnav_open(&dvdnav, "/dev/dvd") != DVDNAV_STATUS_OK) { | 56 if (dvdnav_open(&dvdnav, "/dev/dvd") != DVDNAV_STATUS_OK) { |
57 printf("Error on dvdnav_open\n"); | 57 printf("Error on dvdnav_open\n"); |
58 return 1; | 58 return 1; |
59 } | 59 } |
60 | 60 |
61 /* set read ahead cache usage */ | 61 /* set read ahead cache usage */ |
62 if (dvdnav_set_readahead_flag(dvdnav, DVD_READ_CACHE) != DVDNAV_STATUS_OK) { | 62 if (dvdnav_set_readahead_flag(dvdnav, DVD_READ_CACHE) != DVDNAV_STATUS_OK) { |
63 printf("Error on dvdnav_set_readahead_flag: %s\n", dvdnav_err_to_string(dvdnav)); | 63 printf("Error on dvdnav_set_readahead_flag: %s\n", dvdnav_err_to_string(dvdnav)); |
64 return 2; | 64 return 2; |
65 } | 65 } |
66 | 66 |
67 /* set the language */ | 67 /* set the language */ |
68 if (dvdnav_menu_language_select(dvdnav, DVD_LANGUAGE) != DVDNAV_STATUS_OK || | 68 if (dvdnav_menu_language_select(dvdnav, DVD_LANGUAGE) != DVDNAV_STATUS_OK || |
69 dvdnav_audio_language_select(dvdnav, DVD_LANGUAGE) != DVDNAV_STATUS_OK || | 69 dvdnav_audio_language_select(dvdnav, DVD_LANGUAGE) != DVDNAV_STATUS_OK || |
70 dvdnav_spu_language_select(dvdnav, DVD_LANGUAGE) != DVDNAV_STATUS_OK) { | 70 dvdnav_spu_language_select(dvdnav, DVD_LANGUAGE) != DVDNAV_STATUS_OK) { |
71 printf("Error on setting languages: %s\n", dvdnav_err_to_string(dvdnav)); | 71 printf("Error on setting languages: %s\n", dvdnav_err_to_string(dvdnav)); |
72 return 2; | 72 return 2; |
73 } | 73 } |
74 | 74 |
75 /* set the PGC positioning flag to have position information relatively to the | 75 /* set the PGC positioning flag to have position information relatively to the |
76 * whole feature instead of just relatively to the current chapter */ | 76 * whole feature instead of just relatively to the current chapter */ |
77 if (dvdnav_set_PGC_positioning_flag(dvdnav, 1) != DVDNAV_STATUS_OK) { | 77 if (dvdnav_set_PGC_positioning_flag(dvdnav, 1) != DVDNAV_STATUS_OK) { |
78 printf("Error on dvdnav_set_PGC_positioning_flag: %s\n", dvdnav_err_to_string(dvdnav)); | 78 printf("Error on dvdnav_set_PGC_positioning_flag: %s\n", dvdnav_err_to_string(dvdnav)); |
79 return 2; | 79 return 2; |
80 } | 80 } |
81 | 81 |
82 | 82 |
83 /* the read loop which regularly calls dvdnav_get_next_block | 83 /* the read loop which regularly calls dvdnav_get_next_block |
84 * and handles the returned events */ | 84 * and handles the returned events */ |
85 printf("Reading...\n"); | 85 printf("Reading...\n"); |
86 while (!finished) { | 86 while (!finished) { |
87 int result, event, len; | 87 int result, event, len; |
88 uint8_t *buf = mem; | 88 uint8_t *buf = mem; |
89 | 89 |
90 /* the main reading function */ | 90 /* the main reading function */ |
91 #if DVD_READ_CACHE | 91 #if DVD_READ_CACHE |
92 result = dvdnav_get_next_cache_block(dvdnav, &buf, &event, &len); | 92 result = dvdnav_get_next_cache_block(dvdnav, &buf, &event, &len); |
93 #else | 93 #else |
94 result = dvdnav_get_next_block(dvdnav, buf, &event, &len); | 94 result = dvdnav_get_next_block(dvdnav, buf, &event, &len); |
95 #endif | 95 #endif |
96 | 96 |
97 if (result == DVDNAV_STATUS_ERR) { | 97 if (result == DVDNAV_STATUS_ERR) { |
98 printf("Error getting next block: %s\n", dvdnav_err_to_string(dvdnav)); | 98 printf("Error getting next block: %s\n", dvdnav_err_to_string(dvdnav)); |
99 return 3; | 99 return 3; |
100 } | 100 } |
101 | 101 |
102 switch (event) { | 102 switch (event) { |
103 case DVDNAV_BLOCK_OK: | 103 case DVDNAV_BLOCK_OK: |
104 /* We have received a regular block of the currently playing MPEG stream. | 104 /* We have received a regular block of the currently playing MPEG stream. |
105 * A real player application would now pass this block through demuxing | 105 * A real player application would now pass this block through demuxing |
106 * and decoding. We simply write it to disc here. */ | 106 * and decoding. We simply write it to disc here. */ |
107 | 107 |
108 if (!output_fd && (dump || tt_dump)) { | 108 if (!output_fd && (dump || tt_dump)) { |
109 printf("Opening output...\n"); | 109 printf("Opening output...\n"); |
110 output_fd = open("libdvdnav.mpg", O_CREAT | O_WRONLY | O_APPEND, S_IRWXU | S_IRWXG); | 110 output_fd = open("libdvdnav.mpg", O_CREAT | O_WRONLY | O_APPEND, S_IRWXU | S_IRWXG); |
111 if (output_fd == -1) { | 111 if (output_fd == -1) { |
112 printf("Error opening output\n"); | 112 printf("Error opening output\n"); |
113 return 4; | 113 return 4; |
114 } | 114 } |
115 } | 115 } |
116 | 116 |
117 if (dump || tt_dump) | 117 if (dump || tt_dump) |
118 write(output_fd, buf, len); | 118 write(output_fd, buf, len); |
119 | 119 |
120 break; | 120 break; |
121 case DVDNAV_NOP: | 121 case DVDNAV_NOP: |
122 /* Nothing to do here. */ | 122 /* Nothing to do here. */ |
123 break; | 123 break; |
124 case DVDNAV_STILL_FRAME: | 124 case DVDNAV_STILL_FRAME: |
125 /* We have reached a still frame. A real player application would wait | 125 /* We have reached a still frame. A real player application would wait |
126 * the amount of time specified by the still's length while still handling | 126 * the amount of time specified by the still's length while still handling |
127 * user input to make menus and other interactive stills work. | 127 * user input to make menus and other interactive stills work. |
128 * A length of 0xff means an indefinite still which has to be skipped | 128 * A length of 0xff means an indefinite still which has to be skipped |
129 * indirectly by some user interaction. */ | 129 * indirectly by some user interaction. */ |
130 { | 130 dvdnav_still_event_t *still_event = (dvdnav_still_event_t *)buf; |
131 dvdnav_still_event_t *still_event = (dvdnav_still_event_t *)buf; | 131 if (still_event->length < 0xff) |
132 if (still_event->length < 0xff) | 132 printf("Skipping %d seconds of still frame\n", still_event->length); |
133 printf("Skipping %d seconds of still frame\n", still_event->length); | 133 else |
134 else | 134 printf("Skipping indefinite length still frame\n"); |
135 printf("Skipping indefinite length still frame\n"); | 135 dvdnav_still_skip(dvdnav); |
136 dvdnav_still_skip(dvdnav); | 136 break; |
137 } | 137 case DVDNAV_WAIT: |
138 break; | 138 /* We have reached a point in DVD playback, where timing is critical. |
139 case DVDNAV_WAIT: | 139 * Player application with internal fifos can introduce state |
140 /* We have reached a point in DVD playback, where timing is critical. | 140 * inconsistencies, because libdvdnav is always the fifo's length |
141 * Player application with internal fifos can introduce state | 141 * ahead in the stream compared to what the application sees. |
142 * inconsistencies, because libdvdnav is always the fifo's length | 142 * Such applications should wait until their fifos are empty |
143 * ahead in the stream compared to what the application sees. | 143 * when they receive this type of event. */ |
144 * Such applications should wait until their fifos are empty | 144 printf("Skipping wait condition\n"); |
145 * when they receive this type of event. */ | 145 dvdnav_wait_skip(dvdnav); |
146 printf("Skipping wait condition\n"); | 146 break; |
147 dvdnav_wait_skip(dvdnav); | 147 case DVDNAV_SPU_CLUT_CHANGE: |
148 break; | 148 /* Player applications should pass the new colour lookup table to their |
149 case DVDNAV_SPU_CLUT_CHANGE: | 149 * SPU decoder */ |
150 /* Player applications should pass the new colour lookup table to their | 150 break; |
151 * SPU decoder */ | 151 case DVDNAV_SPU_STREAM_CHANGE: |
152 break; | 152 /* Player applications should inform their SPU decoder to switch channels */ |
153 case DVDNAV_SPU_STREAM_CHANGE: | 153 break; |
154 /* Player applications should inform their SPU decoder to switch channels */ | 154 case DVDNAV_AUDIO_STREAM_CHANGE: |
155 break; | 155 /* Player applications should inform their audio decoder to switch channels */ |
156 case DVDNAV_AUDIO_STREAM_CHANGE: | 156 break; |
157 /* Player applications should inform their audio decoder to switch channels */ | 157 case DVDNAV_HIGHLIGHT: |
158 break; | 158 /* Player applications should inform their overlay engine to highlight the |
159 case DVDNAV_HIGHLIGHT: | 159 * given button */ |
160 /* Player applications should inform their overlay engine to highlight the | 160 dvdnav_highlight_event_t *highlight_event = (dvdnav_highlight_event_t *)buf; |
161 * given button */ | 161 printf("Selected button %d\n", highlight_event->buttonN); |
162 { | 162 break; |
163 dvdnav_highlight_event_t *highlight_event = (dvdnav_highlight_event_t *)buf; | 163 case DVDNAV_VTS_CHANGE: |
164 printf("Selected button %d\n", highlight_event->buttonN); | 164 /* Some status information like video aspect and video scale permissions do |
165 } | 165 * not change inside a VTS. Therefore this event can be used to query such |
166 break; | 166 * information only when necessary and update the decoding/displaying |
167 case DVDNAV_VTS_CHANGE: | 167 * accordingly. */ |
168 /* Some status information like video aspect and video scale permissions do | 168 break; |
169 * not change inside a VTS. Therefore this event can be used to query such | 169 case DVDNAV_CELL_CHANGE: |
170 * information only when necessary and update the decoding/displaying | 170 /* Some status information like the current Title and Part numbers do not |
171 * accordingly. */ | 171 * change inside a cell. Therefore this event can be used to query such |
172 break; | 172 * information only when necessary and update the decoding/displaying |
173 case DVDNAV_CELL_CHANGE: | 173 * accordingly. */ |
174 /* Some status information like the current Title and Part numbers do not | 174 { |
175 * change inside a cell. Therefore this event can be used to query such | 175 int32_t tt = 0, ptt = 0; |
176 * information only when necessary and update the decoding/displaying | 176 uint32_t pos, len; |
177 * accordingly. */ | 177 char input = '\0'; |
178 { | 178 |
179 int32_t tt = 0, ptt = 0; | 179 dvdnav_current_title_info(dvdnav, &tt, &ptt); |
180 uint32_t pos, len; | 180 dvdnav_get_position(dvdnav, &pos, &len); |
181 char input = '\0'; | 181 printf("Cell change: Title %d, Chapter %d\n", tt, ptt); |
182 | 182 printf("At position %.0f%% inside the feature\n", 100 * (double)pos / (double)len); |
183 dvdnav_current_title_info(dvdnav, &tt, &ptt); | 183 |
184 dvdnav_get_position(dvdnav, &pos, &len); | 184 dump = 0; |
185 printf("Cell change: Title %d, Chapter %d\n", tt, ptt); | 185 if (tt_dump && tt != tt_dump) |
186 printf("At position %.0f%% inside the feature\n", 100 * (double)pos / (double)len); | 186 tt_dump = 0; |
187 | 187 |
188 dump = 0; | 188 if (tt_skip && tt != tt_skip) |
189 if (tt_dump && tt != tt_dump) | 189 tt_skip = 0; |
190 tt_dump = 0; | 190 |
191 | 191 if (output_fd && !tt_dump) { |
192 if (tt_skip && tt != tt_skip) | 192 printf("Closing output...\n"); |
193 tt_skip = 0; | 193 output_fd = close(output_fd); |
194 | 194 } |
195 if (output_fd && !tt_dump) { | 195 |
196 printf("Closing output...\n"); | 196 if (!dump && !tt_dump && !tt_skip) { |
197 output_fd = close(output_fd); | 197 fflush(stdin); |
198 } | 198 while ((input != 'a') && (input != 's') && (input != 'q') && (input != 't') && (input != 'l')) { |
199 | 199 printf("(a)ppend cell to output\n(s)kip cell\nappend until end of (t)itle\nskip tit(l)e\n(q)uit\n"); |
200 if (!dump && !tt_dump && !tt_skip) { | 200 scanf("%c", &input); |
201 fflush(stdin); | 201 } |
202 while ((input != 'a') && (input != 's') && (input != 'q') && (input != 't') && (input != 'l')) { | 202 |
203 printf("(a)ppend cell to output\n(s)kip cell\nappend until end of (t)itle\nskip tit(l)e\n(q)uit\n"); | 203 switch (input) { |
204 scanf("%c", &input); | 204 case 'a': |
205 } | 205 dump = 1; |
206 | 206 break; |
207 switch (input) { | 207 case 't': |
208 case 'a': | 208 tt_dump = tt; |
209 dump = 1; | 209 break; |
210 break; | 210 case 'l': |
211 case 't': | 211 tt_skip = tt; |
212 tt_dump = tt; | 212 break; |
213 break; | 213 case 'q': |
214 case 'l': | 214 finished = 1; |
215 tt_skip = tt; | 215 } |
216 break; | 216 } |
217 case 'q': | 217 } |
218 finished = 1; | 218 break; |
219 } | 219 case DVDNAV_NAV_PACKET: |
220 } | 220 /* A NAV packet provides PTS discontinuity information, angle linking information and |
221 } | 221 * button definitions for DVD menus. Angles are handled completely inside libdvdnav. |
222 break; | 222 * For the menus to work, the NAV packet information has to be passed to the overlay |
223 case DVDNAV_NAV_PACKET: | 223 * engine of the player so that it knows the dimensions of the button areas. */ |
224 /* A NAV packet provides PTS discontinuity information, angle linking information and | 224 { |
225 * button definitions for DVD menus. Angles are handled completely inside libdvdnav. | 225 pci_t *pci; |
226 * For the menus to work, the NAV packet information has to be passed to the overlay | 226 |
227 * engine of the player so that it knows the dimensions of the button areas. */ | 227 /* Applications with fifos should not use these functions to retrieve NAV packets, |
228 { | 228 * they should implement their own NAV handling, because the packet you get from these |
229 pci_t *pci; | 229 * functions will already be ahead in the stream which can cause state inconsistencies. |
230 | 230 * Applications with fifos should therefore pass the NAV packet through the fifo |
231 /* Applications with fifos should not use these functions to retrieve NAV packets, | 231 * and decoding pipeline just like any other data. */ |
232 * they should implement their own NAV handling, because the packet you get from these | 232 pci = dvdnav_get_current_nav_pci(dvdnav); |
233 * functions will already be ahead in the stream which can cause state inconsistencies. | 233 dvdnav_get_current_nav_dsi(dvdnav); |
234 * Applications with fifos should therefore pass the NAV packet through the fifo | 234 |
235 * and decoding pipeline just like any other data. */ | 235 if(pci->hli.hl_gi.btn_ns > 0) { |
236 pci = dvdnav_get_current_nav_pci(dvdnav); | 236 int button; |
237 dvdnav_get_current_nav_dsi(dvdnav); | 237 |
238 | 238 printf("Found %i DVD menu buttons...\n", pci->hli.hl_gi.btn_ns); |
239 if(pci->hli.hl_gi.btn_ns > 0) { | 239 |
240 int button; | 240 for (button = 0; button < pci->hli.hl_gi.btn_ns; button++) { |
241 | 241 btni_t *btni = &(pci->hli.btnit[button]); |
242 printf("Found %i DVD menu buttons...\n", pci->hli.hl_gi.btn_ns); | 242 printf("Button %i top-left @ (%i,%i), bottom-right @ (%i,%i)\n", |
243 | 243 button + 1, btni->x_start, btni->y_start, |
244 for (button = 0; button < pci->hli.hl_gi.btn_ns; button++) { | 244 btni->x_end, btni->y_end); |
245 btni_t *btni = &(pci->hli.btnit[button]); | 245 } |
246 printf("Button %i top-left @ (%i,%i), bottom-right @ (%i,%i)\n", | 246 |
247 button + 1, btni->x_start, btni->y_start, | 247 button = 0; |
248 btni->x_end, btni->y_end); | 248 while ((button <= 0) || (button > pci->hli.hl_gi.btn_ns)) { |
249 } | 249 printf("Which button (1 to %i): ", pci->hli.hl_gi.btn_ns); |
250 | 250 scanf("%i", &button); |
251 button = 0; | 251 } |
252 while ((button <= 0) || (button > pci->hli.hl_gi.btn_ns)) { | 252 |
253 printf("Which button (1 to %i): ", pci->hli.hl_gi.btn_ns); | 253 printf("Selecting button %i...\n", button); |
254 scanf("%i", &button); | 254 /* This is the point where applications with fifos have to hand in a NAV packet |
255 } | 255 * which has traveled through the fifos. See the notes above. */ |
256 | 256 dvdnav_button_select_and_activate(dvdnav, pci, button); |
257 printf("Selecting button %i...\n", button); | 257 } |
258 /* This is the point where applications with fifos have to hand in a NAV packet | 258 } |
259 * which has traveled through the fifos. See the notes above. */ | 259 break; |
260 dvdnav_button_select_and_activate(dvdnav, pci, button); | 260 case DVDNAV_HOP_CHANNEL: |
261 } | 261 /* This event is issued whenever a non-seamless operation has been executed. |
262 } | 262 * Applications with fifos should drop the fifos content to speed up responsiveness. */ |
263 break; | 263 break; |
264 case DVDNAV_HOP_CHANNEL: | 264 case DVDNAV_STOP: |
265 /* This event is issued whenever a non-seamless operation has been executed. | 265 /* Playback should end here. */ |
266 * Applications with fifos should drop the fifos content to speed up responsiveness. */ | 266 finished = 1; |
267 break; | 267 break; |
268 case DVDNAV_STOP: | 268 default: |
269 /* Playback should end here. */ | 269 printf("Unknown event (%i)\n", event); |
270 { | 270 finished = 1; |
271 finished = 1; | 271 break; |
272 } | 272 } |
273 break; | |
274 default: | |
275 printf("Unknown event (%i)\n", event); | |
276 finished = 1; | |
277 break; | |
278 } | |
279 #if DVD_READ_CACHE | 273 #if DVD_READ_CACHE |
280 dvdnav_free_cache_block(dvdnav, buf); | 274 dvdnav_free_cache_block(dvdnav, buf); |
281 #endif | 275 #endif |
282 } | 276 } |
283 | 277 |
284 /* destroy dvdnav handle */ | 278 /* destroy dvdnav handle */ |
285 if (dvdnav_close(dvdnav) != DVDNAV_STATUS_OK) { | 279 if (dvdnav_close(dvdnav) != DVDNAV_STATUS_OK) { |
286 printf("Error on dvdnav_close: %s\n", dvdnav_err_to_string(dvdnav)); | 280 printf("Error on dvdnav_close: %s\n", dvdnav_err_to_string(dvdnav)); |
287 return 5; | 281 return 5; |
288 } | 282 } |
289 close(output_fd); | 283 close(output_fd); |
290 | 284 |
291 return 0; | 285 return 0; |
292 } | 286 } |