Mercurial > hg > index.fcgi > dvdnav-rip > dvdnav-rip-1pba
diff 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 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/menus.c Thu Nov 12 23:26:25 2009 -0800 1.3 @@ -0,0 +1,281 @@ 1.4 +/* 1.5 + * Copyright (C) 2003 by the libdvdnav project 1.6 + * 1.7 + * This file is part of libdvdnav, a DVD navigation library. 1.8 + * 1.9 + * libdvdnav is free software; you can redistribute it and/or modify 1.10 + * it under the terms of the GNU General Public License as published by 1.11 + * the Free Software Foundation; either version 2 of the License, or 1.12 + * (at your option) any later version. 1.13 + * 1.14 + * libdvdnav is distributed in the hope that it will be useful, 1.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 1.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1.17 + * GNU General Public License for more details. 1.18 + * 1.19 + * You should have received a copy of the GNU General Public License 1.20 + * along with this program; if not, write to the Free Software 1.21 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 1.22 + * 1.23 + * $Id: menus.c 1135 2008-09-06 21:55:51Z rathann $ 1.24 + * 1.25 + */ 1.26 + 1.27 +#include <stdio.h> 1.28 +#include <unistd.h> 1.29 +#include <inttypes.h> 1.30 +#include <sys/types.h> 1.31 +#include <sys/stat.h> 1.32 +#include <fcntl.h> 1.33 +#include "dvd_types.h" 1.34 +#include <dvdread/dvd_reader.h> 1.35 +#include <dvdread/nav_types.h> 1.36 +#include <dvdread/ifo_types.h> /* For vm_cmd_t */ 1.37 +#include "dvdnav.h" 1.38 +#include "dvdnav_events.h" 1.39 + 1.40 +/* shall we use libdvdnav's read ahead cache? */ 1.41 +#define DVD_READ_CACHE 1 1.42 + 1.43 +/* which is the default language for menus/audio/subpictures? */ 1.44 +#define DVD_LANGUAGE "en" 1.45 + 1.46 +#ifdef WIN32 1.47 +#define S_IRWXG 0 1.48 +#endif 1.49 + 1.50 +int main(int argc, char **argv) { 1.51 + dvdnav_t *dvdnav; 1.52 + uint8_t mem[DVD_VIDEO_LB_LEN]; 1.53 + int finished = 0; 1.54 + int output_fd = 0; 1.55 + int dump = 0, tt_dump = 0; 1.56 + 1.57 + /* open dvdnav handle */ 1.58 + printf("Opening DVD...\n"); 1.59 + if (dvdnav_open(&dvdnav, "/dev/dvd") != DVDNAV_STATUS_OK) { 1.60 + printf("Error on dvdnav_open\n"); 1.61 + return 1; 1.62 + } 1.63 + 1.64 + /* set read ahead cache usage */ 1.65 + if (dvdnav_set_readahead_flag(dvdnav, DVD_READ_CACHE) != DVDNAV_STATUS_OK) { 1.66 + printf("Error on dvdnav_set_readahead_flag: %s\n", dvdnav_err_to_string(dvdnav)); 1.67 + return 2; 1.68 + } 1.69 + 1.70 + /* set the language */ 1.71 + if (dvdnav_menu_language_select(dvdnav, DVD_LANGUAGE) != DVDNAV_STATUS_OK || 1.72 + dvdnav_audio_language_select(dvdnav, DVD_LANGUAGE) != DVDNAV_STATUS_OK || 1.73 + dvdnav_spu_language_select(dvdnav, DVD_LANGUAGE) != DVDNAV_STATUS_OK) { 1.74 + printf("Error on setting languages: %s\n", dvdnav_err_to_string(dvdnav)); 1.75 + return 2; 1.76 + } 1.77 + 1.78 + /* set the PGC positioning flag to have position information relatively to the 1.79 + * whole feature instead of just relatively to the current chapter */ 1.80 + if (dvdnav_set_PGC_positioning_flag(dvdnav, 1) != DVDNAV_STATUS_OK) { 1.81 + printf("Error on dvdnav_set_PGC_positioning_flag: %s\n", dvdnav_err_to_string(dvdnav)); 1.82 + return 2; 1.83 + } 1.84 + 1.85 + 1.86 + /* the read loop which regularly calls dvdnav_get_next_block 1.87 + * and handles the returned events */ 1.88 + printf("Reading...\n"); 1.89 + while (!finished) { 1.90 + int result, event, len; 1.91 + uint8_t *buf = mem; 1.92 + 1.93 + /* the main reading function */ 1.94 +#if DVD_READ_CACHE 1.95 + result = dvdnav_get_next_cache_block(dvdnav, &buf, &event, &len); 1.96 +#else 1.97 + result = dvdnav_get_next_block(dvdnav, buf, &event, &len); 1.98 +#endif 1.99 + 1.100 + if (result == DVDNAV_STATUS_ERR) { 1.101 + printf("Error getting next block: %s\n", dvdnav_err_to_string(dvdnav)); 1.102 + return 3; 1.103 + } 1.104 + 1.105 + switch (event) { 1.106 + case DVDNAV_BLOCK_OK: 1.107 + /* We have received a regular block of the currently playing MPEG stream. 1.108 + * A real player application would now pass this block through demuxing 1.109 + * and decoding. We simply write it to disc here. */ 1.110 + 1.111 + if (!output_fd) { 1.112 + printf("Opening output...\n"); 1.113 + output_fd = open("libdvdnav.mpg", O_CREAT | O_WRONLY, S_IRWXU | S_IRWXG); 1.114 + if (output_fd == -1) { 1.115 + printf("Error opening output\n"); 1.116 + return 4; 1.117 + } 1.118 + } 1.119 + 1.120 + if (dump || tt_dump) 1.121 + write(output_fd, buf, len); 1.122 + 1.123 + break; 1.124 + case DVDNAV_NOP: 1.125 + /* Nothing to do here. */ 1.126 + break; 1.127 + case DVDNAV_STILL_FRAME: 1.128 + /* We have reached a still frame. A real player application would wait 1.129 + * the amount of time specified by the still's length while still handling 1.130 + * user input to make menus and other interactive stills work. 1.131 + * A length of 0xff means an indefinite still which has to be skipped 1.132 + * indirectly by some user interaction. */ 1.133 + { 1.134 + dvdnav_still_event_t *still_event = (dvdnav_still_event_t *)buf; 1.135 + if (still_event->length < 0xff) 1.136 + printf("Skipping %d seconds of still frame\n", still_event->length); 1.137 + else 1.138 + printf("Skipping indefinite length still frame\n"); 1.139 + dvdnav_still_skip(dvdnav); 1.140 + } 1.141 + break; 1.142 + case DVDNAV_WAIT: 1.143 + /* We have reached a point in DVD playback, where timing is critical. 1.144 + * Player application with internal fifos can introduce state 1.145 + * inconsistencies, because libdvdnav is always the fifo's length 1.146 + * ahead in the stream compared to what the application sees. 1.147 + * Such applications should wait until their fifos are empty 1.148 + * when they receive this type of event. */ 1.149 + printf("Skipping wait condition\n"); 1.150 + dvdnav_wait_skip(dvdnav); 1.151 + break; 1.152 + case DVDNAV_SPU_CLUT_CHANGE: 1.153 + /* Player applications should pass the new colour lookup table to their 1.154 + * SPU decoder */ 1.155 + break; 1.156 + case DVDNAV_SPU_STREAM_CHANGE: 1.157 + /* Player applications should inform their SPU decoder to switch channels */ 1.158 + break; 1.159 + case DVDNAV_AUDIO_STREAM_CHANGE: 1.160 + /* Player applications should inform their audio decoder to switch channels */ 1.161 + break; 1.162 + case DVDNAV_HIGHLIGHT: 1.163 + /* Player applications should inform their overlay engine to highlight the 1.164 + * given button */ 1.165 + { 1.166 + dvdnav_highlight_event_t *highlight_event = (dvdnav_highlight_event_t *)buf; 1.167 + printf("Selected button %d\n", highlight_event->buttonN); 1.168 + } 1.169 + break; 1.170 + case DVDNAV_VTS_CHANGE: 1.171 + /* Some status information like video aspect and video scale permissions do 1.172 + * not change inside a VTS. Therefore this event can be used to query such 1.173 + * information only when necessary and update the decoding/displaying 1.174 + * accordingly. */ 1.175 + break; 1.176 + case DVDNAV_CELL_CHANGE: 1.177 + /* Some status information like the current Title and Part numbers do not 1.178 + * change inside a cell. Therefore this event can be used to query such 1.179 + * information only when necessary and update the decoding/displaying 1.180 + * accordingly. */ 1.181 + { 1.182 + int32_t tt = 0, ptt = 0; 1.183 + uint32_t pos, len; 1.184 + char input = '\0'; 1.185 + 1.186 + dvdnav_current_title_info(dvdnav, &tt, &ptt); 1.187 + dvdnav_get_position(dvdnav, &pos, &len); 1.188 + printf("Cell change: Title %d, Chapter %d\n", tt, ptt); 1.189 + printf("At position %.0f%% inside the feature\n", 100 * (double)pos / (double)len); 1.190 + 1.191 + dump = 0; 1.192 + if (tt_dump && tt != tt_dump) 1.193 + tt_dump = 0; 1.194 + 1.195 + if (!dump && !tt_dump) { 1.196 + fflush(stdin); 1.197 + while ((input != 'a') && (input != 's') && (input != 'q') && (input != 't')) { 1.198 + printf("(a)ppend cell to output\n(s)kip cell\nappend until end of (t)itle\n(q)uit\n"); 1.199 + scanf("%c", &input); 1.200 + } 1.201 + 1.202 + switch (input) { 1.203 + case 'a': 1.204 + dump = 1; 1.205 + break; 1.206 + case 't': 1.207 + tt_dump = tt; 1.208 + break; 1.209 + case 'q': 1.210 + finished = 1; 1.211 + } 1.212 + } 1.213 + } 1.214 + break; 1.215 + case DVDNAV_NAV_PACKET: 1.216 + /* A NAV packet provides PTS discontinuity information, angle linking information and 1.217 + * button definitions for DVD menus. Angles are handled completely inside libdvdnav. 1.218 + * For the menus to work, the NAV packet information has to be passed to the overlay 1.219 + * engine of the player so that it knows the dimensions of the button areas. */ 1.220 + { 1.221 + pci_t *pci; 1.222 + 1.223 + /* Applications with fifos should not use these functions to retrieve NAV packets, 1.224 + * they should implement their own NAV handling, because the packet you get from these 1.225 + * functions will already be ahead in the stream which can cause state inconsistencies. 1.226 + * Applications with fifos should therefore pass the NAV packet through the fifo 1.227 + * and decoding pipeline just like any other data. */ 1.228 + pci = dvdnav_get_current_nav_pci(dvdnav); 1.229 + dvdnav_get_current_nav_dsi(dvdnav); 1.230 + 1.231 + if(pci->hli.hl_gi.btn_ns > 0) { 1.232 + int button; 1.233 + 1.234 + printf("Found %i DVD menu buttons...\n", pci->hli.hl_gi.btn_ns); 1.235 + 1.236 + for (button = 0; button < pci->hli.hl_gi.btn_ns; button++) { 1.237 + btni_t *btni = &(pci->hli.btnit[button]); 1.238 + printf("Button %i top-left @ (%i,%i), bottom-right @ (%i,%i)\n", 1.239 + button + 1, btni->x_start, btni->y_start, 1.240 + btni->x_end, btni->y_end); 1.241 + } 1.242 + 1.243 + button = 0; 1.244 + while ((button <= 0) || (button > pci->hli.hl_gi.btn_ns)) { 1.245 + printf("Which button (1 to %i): ", pci->hli.hl_gi.btn_ns); 1.246 + scanf("%i", &button); 1.247 + } 1.248 + 1.249 + printf("Selecting button %i...\n", button); 1.250 + /* This is the point where applications with fifos have to hand in a NAV packet 1.251 + * which has traveled through the fifos. See the notes above. */ 1.252 + dvdnav_button_select_and_activate(dvdnav, pci, button); 1.253 + } 1.254 + } 1.255 + break; 1.256 + case DVDNAV_HOP_CHANNEL: 1.257 + /* This event is issued whenever a non-seamless operation has been executed. 1.258 + * Applications with fifos should drop the fifos content to speed up responsiveness. */ 1.259 + break; 1.260 + case DVDNAV_STOP: 1.261 + /* Playback should end here. */ 1.262 + { 1.263 + finished = 1; 1.264 + } 1.265 + break; 1.266 + default: 1.267 + printf("Unknown event (%i)\n", event); 1.268 + finished = 1; 1.269 + break; 1.270 + } 1.271 +#if DVD_READ_CACHE 1.272 + dvdnav_free_cache_block(dvdnav, buf); 1.273 +#endif 1.274 + } 1.275 + 1.276 + /* destroy dvdnav handle */ 1.277 + if (dvdnav_close(dvdnav) != DVDNAV_STATUS_OK) { 1.278 + printf("Error on dvdnav_close: %s\n", dvdnav_err_to_string(dvdnav)); 1.279 + return 5; 1.280 + } 1.281 + close(output_fd); 1.282 + 1.283 + return 0; 1.284 +}