1 /*
2  * Copyright (C) 2001-2004 Rich Wareham <richwareham@users.sourceforge.net>
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 
21 #ifndef DVDNAV_INTERNAL_H_INCLUDED
22 #define DVDNAV_INTERNAL_H_INCLUDED
23 
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27 
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <unistd.h>
31 #include <limits.h>
32 #include <string.h>
33 
34 #ifndef HAVE_GETTIMEOFDAY
35 #  ifdef WIN32
36 #    include <winsock.h>
37 struct timezone;
38 #  else
39 #    include <sys/time.h>
40 #  endif
41 /* replacement gettimeofday implementation */
42 #include <sys/timeb.h>
dvdnav_private_gettimeofday(struct timeval * tv,void * tz)43 static inline int dvdnav_private_gettimeofday( struct timeval *tv, void *tz )
44 {
45   struct timeb t;
46   ftime( &t );
47   tv->tv_sec = t.time;
48   tv->tv_usec = t.millitm * 1000;
49   return 0;
50 }
51 #define gettimeofday(TV, TZ) dvdnav_private_gettimeofday((TV), (TZ))
52 #define HAVE_GETTIMEOFDAY 1
53 #endif
54 
55 #ifndef HAVE_SNPRINTF
56 #  ifdef HAVE__SNPRINTF
57 #    define snprintf _snprintf
58 #    define HAVE_SNPRINTF 1
59 #  endif
60 #endif
61 
62 #ifdef WIN32
63 
64 /* pthread_mutex_* wrapper for win32 */
65 #include <windows.h>
66 #include <process.h>
67 typedef CRITICAL_SECTION pthread_mutex_t;
68 #define pthread_mutex_init(a, b) InitializeCriticalSection(a)
69 #define pthread_mutex_lock(a)    EnterCriticalSection(a)
70 #define pthread_mutex_unlock(a)  LeaveCriticalSection(a)
71 #define pthread_mutex_destroy(a)
72 
73 #include <io.h> /* read() */
74 #define lseek64 _lseeki64
75 
76 #else
77 
78 #include <pthread.h>
79 
80 #endif /* WIN32 */
81 
82 /* Uncomment for VM command tracing */
83 /* #define TRACE */
84 
85 #include "decoder.h"
86 #include "dvdnav.h"
87 #include "vm.h"
88 #include "vmcmd.h"
89 
90 /* where should libdvdnav write its messages (stdout/stderr) */
91 #define MSG_OUT stdout
92 
93 /* Maximum length of an error string */
94 #define MAX_ERR_LEN 255
95 
96 /* Use the POSIX PATH_MAX if available */
97 #ifdef PATH_MAX
98 #define MAX_PATH_LEN PATH_MAX
99 #else
100 #define MAX_PATH_LEN 255 /* Arbitrary */
101 #endif
102 
103 #ifndef DVD_VIDEO_LB_LEN
104 #define DVD_VIDEO_LB_LEN 2048
105 #endif
106 
107 typedef struct read_cache_s read_cache_t;
108 
109 /*
110  * These are defined here because they are
111  * not in ifo_types.h, they maybe one day
112  */
113 
114 #ifndef audio_status_t
115 typedef struct {
116 #ifdef WORDS_BIGENDIAN
117   unsigned int available     : 1;
118   unsigned int zero1         : 4;
119   unsigned int stream_number : 3;
120   uint8_t zero2;
121 #else
122   uint8_t zero2;
123   unsigned int stream_number : 3;
124   unsigned int zero1         : 4;
125   unsigned int available     : 1;
126 #endif
127 } ATTRIBUTE_PACKED audio_status_t;
128 #endif
129 
130 #ifndef spu_status_t
131 typedef struct {
132 #ifdef WORDS_BIGENDIAN
133   unsigned int available               : 1;
134   unsigned int zero1                   : 2;
135   unsigned int stream_number_4_3       : 5;
136   unsigned int zero2                   : 3;
137   unsigned int stream_number_wide      : 5;
138   unsigned int zero3                   : 3;
139   unsigned int stream_number_letterbox : 5;
140   unsigned int zero4                   : 3;
141   unsigned int stream_number_pan_scan  : 5;
142 #else
143   unsigned int stream_number_pan_scan  : 5;
144   unsigned int zero4                   : 3;
145   unsigned int stream_number_letterbox : 5;
146   unsigned int zero3                   : 3;
147   unsigned int stream_number_wide      : 5;
148   unsigned int zero2                   : 3;
149   unsigned int stream_number_4_3       : 5;
150   unsigned int zero1                   : 2;
151   unsigned int available               : 1;
152 #endif
153 } ATTRIBUTE_PACKED spu_status_t;
154 #endif
155 
156 typedef struct dvdnav_vobu_s {
157   int32_t vobu_start;  /* Logical Absolute. MAX needed is 0x300000 */
158   int32_t vobu_length;
159   int32_t blockN;      /* Relative offset */
160   int32_t vobu_next;   /* Relative offset */
161 } dvdnav_vobu_t;
162 
163 /** The main DVDNAV type **/
164 
165 struct dvdnav_s {
166   /* General data */
167   char        path[MAX_PATH_LEN]; /* Path to DVD device/dir */
168   dvd_file_t *file;               /* Currently opened file */
169 
170   /* Position data */
171   vm_position_t position_next;
172   vm_position_t position_current;
173   dvdnav_vobu_t vobu;
174 
175   /* NAV data */
176   pci_t pci;
177   dsi_t dsi;
178   uint32_t last_cmd_nav_lbn;      /* detects when a command is issued on an already left NAV */
179 
180   /* Flags */
181   int skip_still;                 /* Set when skipping a still */
182   int sync_wait;                  /* applications should wait till they are in sync with us */
183   int sync_wait_skip;             /* Set when skipping wait state */
184   int spu_clut_changed;           /* The SPU CLUT changed */
185   int started;                    /* vm_start has been called? */
186   int use_read_ahead;             /* 1 - use read-ahead cache, 0 - don't */
187   int pgc_based;                  /* positioning works PGC based instead of PG based */
188 
189   /* VM */
190   vm_t *vm;
191   pthread_mutex_t vm_lock;
192 
193   /* Read-ahead cache */
194   read_cache_t *cache;
195 
196   /* Errors */
197   char err_str[MAX_ERR_LEN];
198 };
199 
200 /** USEFUL MACROS **/
201 
202 /* printerr*() are often called when this is NULL. Avoid segfaults by replacing these with
203  * more common prints
204  */
205 #ifdef __GNUC__
206 #define printerrf(format, args...)					\
207   do {									\
208     if ( ! this ) fprintf(stderr, "Missing 'this' pointer while erroring:" format "\n", ## args); \
209     else snprintf(this->err_str, MAX_ERR_LEN, format, ## args);		\
210   } while(0);
211 #else
212 #ifdef _MSC_VER
213 #define printerrf(str) snprintf(this->err_str, MAX_ERR_LEN, str);
214 #else
215 #define printerrf(...)						 \
216   do {								 \
217     if ( ! this ) {						 \
218       fprintf(stderr, "Missing 'this' pointer while erroring:"); \
219       fprintf(stderr, __VA_ARGS__);				 \
220       fprintf(stderr, "\n");					 \
221     } else {							 \
222       snprintf(this->err_str, MAX_ERR_LEN, __VA_ARGS__);	 \
223     }								 \
224   } while(0);
225 #endif /* WIN32 */
226 #endif
227 #define printerr(str)							\
228   do {									\
229     if ( ! this ) {							\
230       fprintf(stderr, "Missing 'this' pointer while erroring: %s\n", str); \
231     } else {								\
232       strncpy(this->err_str, str, MAX_ERR_LEN);				\
233     }									\
234   } while(0);
235 
236 #endif /* DVDNAV_INTERNAL_H_INCLUDED */
237