Mercurial > hg > index.fcgi > dvdnav-rip > dvdnav-rip-1pba
comparison menus.c @ 0:7e8d91fad6c7
copy menus.c from examples/ in libdvdnav-4.1.3
author | paulo@thepaulopc |
---|---|
date | Thu, 12 Nov 2009 23:26:25 -0800 |
parents | |
children | cfe5048cc182 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:93749ee354c6 |
---|---|
1 /* | |
2 * Copyright (C) 2003 by the libdvdnav project | |
3 * | |
4 * This file is part of libdvdnav, a DVD navigation library. | |
5 * | |
6 * libdvdnav is free software; you can redistribute it and/or modify | |
7 * it under the terms of the GNU General Public License as published by | |
8 * the Free Software Foundation; either version 2 of the License, or | |
9 * (at your option) any later version. | |
10 * | |
11 * libdvdnav is distributed in the hope that it will be useful, | |
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 * GNU General Public License for more details. | |
15 * | |
16 * You should have received a copy of the GNU General Public License | |
17 * along with this program; if not, write to the Free Software | |
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA | |
19 * | |
20 * $Id: menus.c 1135 2008-09-06 21:55:51Z rathann $ | |
21 * | |
22 */ | |
23 | |
24 #include <stdio.h> | |
25 #include <unistd.h> | |
26 #include <inttypes.h> | |
27 #include <sys/types.h> | |
28 #include <sys/stat.h> | |
29 #include <fcntl.h> | |
30 #include "dvd_types.h" | |
31 #include <dvdread/dvd_reader.h> | |
32 #include <dvdread/nav_types.h> | |
33 #include <dvdread/ifo_types.h> /* For vm_cmd_t */ | |
34 #include "dvdnav.h" | |
35 #include "dvdnav_events.h" | |
36 | |
37 /* shall we use libdvdnav's read ahead cache? */ | |
38 #define DVD_READ_CACHE 1 | |
39 | |
40 /* which is the default language for menus/audio/subpictures? */ | |
41 #define DVD_LANGUAGE "en" | |
42 | |
43 #ifdef WIN32 | |
44 #define S_IRWXG 0 | |
45 #endif | |
46 | |
47 int main(int argc, char **argv) { | |
48 dvdnav_t *dvdnav; | |
49 uint8_t mem[DVD_VIDEO_LB_LEN]; | |
50 int finished = 0; | |
51 int output_fd = 0; | |
52 int dump = 0, tt_dump = 0; | |
53 | |
54 /* open dvdnav handle */ | |
55 printf("Opening DVD...\n"); | |
56 if (dvdnav_open(&dvdnav, "/dev/dvd") != DVDNAV_STATUS_OK) { | |
57 printf("Error on dvdnav_open\n"); | |
58 return 1; | |
59 } | |
60 | |
61 /* set read ahead cache usage */ | |
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)); | |
64 return 2; | |
65 } | |
66 | |
67 /* set the language */ | |
68 if (dvdnav_menu_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) { | |
71 printf("Error on setting languages: %s\n", dvdnav_err_to_string(dvdnav)); | |
72 return 2; | |
73 } | |
74 | |
75 /* set the PGC positioning flag to have position information relatively to the | |
76 * whole feature instead of just relatively to the current chapter */ | |
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)); | |
79 return 2; | |
80 } | |
81 | |
82 | |
83 /* the read loop which regularly calls dvdnav_get_next_block | |
84 * and handles the returned events */ | |
85 printf("Reading...\n"); | |
86 while (!finished) { | |
87 int result, event, len; | |
88 uint8_t *buf = mem; | |
89 | |
90 /* the main reading function */ | |
91 #if DVD_READ_CACHE | |
92 result = dvdnav_get_next_cache_block(dvdnav, &buf, &event, &len); | |
93 #else | |
94 result = dvdnav_get_next_block(dvdnav, buf, &event, &len); | |
95 #endif | |
96 | |
97 if (result == DVDNAV_STATUS_ERR) { | |
98 printf("Error getting next block: %s\n", dvdnav_err_to_string(dvdnav)); | |
99 return 3; | |
100 } | |
101 | |
102 switch (event) { | |
103 case DVDNAV_BLOCK_OK: | |
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 | |
106 * and decoding. We simply write it to disc here. */ | |
107 | |
108 if (!output_fd) { | |
109 printf("Opening output...\n"); | |
110 output_fd = open("libdvdnav.mpg", O_CREAT | O_WRONLY, S_IRWXU | S_IRWXG); | |
111 if (output_fd == -1) { | |
112 printf("Error opening output\n"); | |
113 return 4; | |
114 } | |
115 } | |
116 | |
117 if (dump || tt_dump) | |
118 write(output_fd, buf, len); | |
119 | |
120 break; | |
121 case DVDNAV_NOP: | |
122 /* Nothing to do here. */ | |
123 break; | |
124 case DVDNAV_STILL_FRAME: | |
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 | |
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 | |
129 * indirectly by some user interaction. */ | |
130 { | |
131 dvdnav_still_event_t *still_event = (dvdnav_still_event_t *)buf; | |
132 if (still_event->length < 0xff) | |
133 printf("Skipping %d seconds of still frame\n", still_event->length); | |
134 else | |
135 printf("Skipping indefinite length still frame\n"); | |
136 dvdnav_still_skip(dvdnav); | |
137 } | |
138 break; | |
139 case DVDNAV_WAIT: | |
140 /* We have reached a point in DVD playback, where timing is critical. | |
141 * Player application with internal fifos can introduce state | |
142 * inconsistencies, because libdvdnav is always the fifo's length | |
143 * ahead in the stream compared to what the application sees. | |
144 * Such applications should wait until their fifos are empty | |
145 * when they receive this type of event. */ | |
146 printf("Skipping wait condition\n"); | |
147 dvdnav_wait_skip(dvdnav); | |
148 break; | |
149 case DVDNAV_SPU_CLUT_CHANGE: | |
150 /* Player applications should pass the new colour lookup table to their | |
151 * SPU decoder */ | |
152 break; | |
153 case DVDNAV_SPU_STREAM_CHANGE: | |
154 /* Player applications should inform their SPU decoder to switch channels */ | |
155 break; | |
156 case DVDNAV_AUDIO_STREAM_CHANGE: | |
157 /* Player applications should inform their audio decoder to switch channels */ | |
158 break; | |
159 case DVDNAV_HIGHLIGHT: | |
160 /* Player applications should inform their overlay engine to highlight the | |
161 * given button */ | |
162 { | |
163 dvdnav_highlight_event_t *highlight_event = (dvdnav_highlight_event_t *)buf; | |
164 printf("Selected button %d\n", highlight_event->buttonN); | |
165 } | |
166 break; | |
167 case DVDNAV_VTS_CHANGE: | |
168 /* Some status information like video aspect and video scale permissions do | |
169 * not change inside a VTS. Therefore this event can be used to query such | |
170 * information only when necessary and update the decoding/displaying | |
171 * accordingly. */ | |
172 break; | |
173 case DVDNAV_CELL_CHANGE: | |
174 /* Some status information like the current Title and Part numbers do not | |
175 * change inside a cell. Therefore this event can be used to query such | |
176 * information only when necessary and update the decoding/displaying | |
177 * accordingly. */ | |
178 { | |
179 int32_t tt = 0, ptt = 0; | |
180 uint32_t pos, len; | |
181 char input = '\0'; | |
182 | |
183 dvdnav_current_title_info(dvdnav, &tt, &ptt); | |
184 dvdnav_get_position(dvdnav, &pos, &len); | |
185 printf("Cell change: Title %d, Chapter %d\n", tt, ptt); | |
186 printf("At position %.0f%% inside the feature\n", 100 * (double)pos / (double)len); | |
187 | |
188 dump = 0; | |
189 if (tt_dump && tt != tt_dump) | |
190 tt_dump = 0; | |
191 | |
192 if (!dump && !tt_dump) { | |
193 fflush(stdin); | |
194 while ((input != 'a') && (input != 's') && (input != 'q') && (input != 't')) { | |
195 printf("(a)ppend cell to output\n(s)kip cell\nappend until end of (t)itle\n(q)uit\n"); | |
196 scanf("%c", &input); | |
197 } | |
198 | |
199 switch (input) { | |
200 case 'a': | |
201 dump = 1; | |
202 break; | |
203 case 't': | |
204 tt_dump = tt; | |
205 break; | |
206 case 'q': | |
207 finished = 1; | |
208 } | |
209 } | |
210 } | |
211 break; | |
212 case DVDNAV_NAV_PACKET: | |
213 /* A NAV packet provides PTS discontinuity information, angle linking information and | |
214 * button definitions for DVD menus. Angles are handled completely inside libdvdnav. | |
215 * For the menus to work, the NAV packet information has to be passed to the overlay | |
216 * engine of the player so that it knows the dimensions of the button areas. */ | |
217 { | |
218 pci_t *pci; | |
219 | |
220 /* Applications with fifos should not use these functions to retrieve NAV packets, | |
221 * they should implement their own NAV handling, because the packet you get from these | |
222 * functions will already be ahead in the stream which can cause state inconsistencies. | |
223 * Applications with fifos should therefore pass the NAV packet through the fifo | |
224 * and decoding pipeline just like any other data. */ | |
225 pci = dvdnav_get_current_nav_pci(dvdnav); | |
226 dvdnav_get_current_nav_dsi(dvdnav); | |
227 | |
228 if(pci->hli.hl_gi.btn_ns > 0) { | |
229 int button; | |
230 | |
231 printf("Found %i DVD menu buttons...\n", pci->hli.hl_gi.btn_ns); | |
232 | |
233 for (button = 0; button < pci->hli.hl_gi.btn_ns; button++) { | |
234 btni_t *btni = &(pci->hli.btnit[button]); | |
235 printf("Button %i top-left @ (%i,%i), bottom-right @ (%i,%i)\n", | |
236 button + 1, btni->x_start, btni->y_start, | |
237 btni->x_end, btni->y_end); | |
238 } | |
239 | |
240 button = 0; | |
241 while ((button <= 0) || (button > pci->hli.hl_gi.btn_ns)) { | |
242 printf("Which button (1 to %i): ", pci->hli.hl_gi.btn_ns); | |
243 scanf("%i", &button); | |
244 } | |
245 | |
246 printf("Selecting button %i...\n", button); | |
247 /* This is the point where applications with fifos have to hand in a NAV packet | |
248 * which has traveled through the fifos. See the notes above. */ | |
249 dvdnav_button_select_and_activate(dvdnav, pci, button); | |
250 } | |
251 } | |
252 break; | |
253 case DVDNAV_HOP_CHANNEL: | |
254 /* This event is issued whenever a non-seamless operation has been executed. | |
255 * Applications with fifos should drop the fifos content to speed up responsiveness. */ | |
256 break; | |
257 case DVDNAV_STOP: | |
258 /* Playback should end here. */ | |
259 { | |
260 finished = 1; | |
261 } | |
262 break; | |
263 default: | |
264 printf("Unknown event (%i)\n", event); | |
265 finished = 1; | |
266 break; | |
267 } | |
268 #if DVD_READ_CACHE | |
269 dvdnav_free_cache_block(dvdnav, buf); | |
270 #endif | |
271 } | |
272 | |
273 /* destroy dvdnav handle */ | |
274 if (dvdnav_close(dvdnav) != DVDNAV_STATUS_OK) { | |
275 printf("Error on dvdnav_close: %s\n", dvdnav_err_to_string(dvdnav)); | |
276 return 5; | |
277 } | |
278 close(output_fd); | |
279 | |
280 return 0; | |
281 } |