1 /*
2 Copyright (C) 2002-2003, 2017 Rocky Bernstein <rocky@gnu.org>
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Foundation
16 Software, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
19 /*
20 Things here refer to lower-level structures using a structure other
21 than vcdinfo_t. For higher-level structures via the vcdinfo_t, see
22 info.c
23 */
24
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <stdio.h>
31 #include <stddef.h>
32 #include <errno.h>
33
34 #ifdef HAVE_STDLIB_H
35 #include <stdlib.h>
36 #endif
37 #ifdef HAVE_STRING_H
38 #include <string.h>
39 #endif
40 #ifdef HAVE_SYS_TYPES_H
41 #include <sys/types.h>
42 #endif
43 #ifdef HAVE_SYS_STAT_H
44 #include <sys/stat.h>
45 #endif
46 #ifdef HAVE_UNISTD_H
47 #include <unistd.h>
48 #endif
49
50 /* We don't want to pull in cdio's config */
51 #define __CDIO_CONFIG_H__
52 #include <cdio/cdio.h>
53 #include <cdio/bytesex.h>
54 #include <cdio/util.h>
55
56 /* Eventually move above libvcd includes but having vcdinfo including. */
57 #include <libvcd/info.h>
58
59 /* Private headers */
60 #include "info_private.h"
61 #include "pbc.h"
62
63 #define BUF_COUNT 16
64 #define BUF_SIZE 80
65
66 /* Return a pointer to a internal free buffer */
67 static char *
_getbuf(void)68 _getbuf (void)
69 {
70 static char _buf[BUF_COUNT][BUF_SIZE];
71 static int _num = -1;
72
73 _num++;
74 _num %= BUF_COUNT;
75
76 memset (_buf[_num], 0, BUF_SIZE);
77
78 return _buf[_num];
79 }
80
81 const char *
vcdinf_area_str(const struct psd_area_t * _area)82 vcdinf_area_str (const struct psd_area_t *_area)
83 {
84 char *buf;
85
86 if (!_area->x1
87 && !_area->y1
88 && !_area->x2
89 && !_area->y2)
90 return "disabled";
91
92 buf = _getbuf ();
93
94 snprintf (buf, BUF_SIZE, "[%3d,%3d] - [%3d,%3d]",
95 _area->x1, _area->y1,
96 _area->x2, _area->y2);
97
98 return buf;
99 }
100
101 /*!
102 Return a string containing the VCD album id, or NULL if there is
103 some problem in getting this.
104 */
105 const char *
vcdinf_get_album_id(const InfoVcd_t * info)106 vcdinf_get_album_id(const InfoVcd_t *info)
107 {
108 if (NULL==info) return NULL;
109 return vcdinfo_strip_trail (info->album_desc, MAX_ALBUM_LEN);
110 }
111
112 /*!
113 Get autowait time value for PsdPlayListDescriptor *d.
114 Time is in seconds unless it is -1 (unlimited).
115 */
116 int
vcdinf_get_autowait_time(const PsdPlayListDescriptor_t * d)117 vcdinf_get_autowait_time (const PsdPlayListDescriptor_t *d)
118 {
119 return vcdinfo_get_wait_time (d->atime);
120 }
121
122 /*!
123 Return the base selection number. VCD_INVALID_BSN is returned if there
124 is an error.
125 */
126 unsigned int
vcdinf_get_bsn(const PsdSelectionListDescriptor_t * psd)127 vcdinf_get_bsn(const PsdSelectionListDescriptor_t *psd)
128 {
129 if (NULL==psd) return VCDINFO_INVALID_BSN;
130 return(psd->bsn);
131 }
132
133 /*!
134 Return a string giving VCD format (VCD 1.0 VCD 1.1, SVCD, ...
135 for this object.
136 */
137 const char *
vcdinf_get_format_version_str(vcd_type_t vcd_type)138 vcdinf_get_format_version_str (vcd_type_t vcd_type)
139 {
140 switch (vcd_type)
141 {
142 case VCD_TYPE_VCD:
143 return ("VCD 1.0");
144 break;
145 case VCD_TYPE_VCD11:
146 return ("VCD 1.1");
147 break;
148 case VCD_TYPE_VCD2:
149 return ("VCD 2.0");
150 break;
151 case VCD_TYPE_SVCD:
152 return ("SVCD");
153 break;
154 case VCD_TYPE_HQVCD:
155 return ("HQVCD");
156 break;
157 case VCD_TYPE_INVALID:
158 return ("INVALID");
159 break;
160 default:
161 return ( "????");
162 }
163 }
164
165 /*!
166 Return loop count. 0 is infinite loop.
167 */
168 uint16_t
vcdinf_get_loop_count(const PsdSelectionListDescriptor_t * psd)169 vcdinf_get_loop_count (const PsdSelectionListDescriptor_t *psd)
170 {
171 return 0x7f & psd->loop;
172 }
173
174 /*!
175 Return LOT offset
176 */
177 uint16_t
vcdinf_get_lot_offset(const LotVcd_t * lot,unsigned int n)178 vcdinf_get_lot_offset (const LotVcd_t *lot, unsigned int n)
179 {
180 return uint16_from_be (lot->offset[n]);
181 }
182
183 /*!
184 Return the number of entries in the VCD.
185 */
186 unsigned int
vcdinf_get_num_entries(const EntriesVcd_t * entries)187 vcdinf_get_num_entries(const EntriesVcd_t *entries)
188 {
189 if (NULL==entries) return 0;
190 return (uint16_from_be (entries->entry_count));
191 }
192
193 /*!
194 Return the number of segments in the VCD.
195 */
196 segnum_t
vcdinf_get_num_segments(const InfoVcd_t * info)197 vcdinf_get_num_segments(const InfoVcd_t *info)
198 {
199 if (NULL==info) return 0;
200 return (uint16_from_be (info->item_count));
201 }
202
203 /*!
204 Return number of LIDs.
205 */
206 lid_t
vcdinf_get_num_LIDs(const InfoVcd_t * info)207 vcdinf_get_num_LIDs (const InfoVcd_t *info)
208 {
209 if (NULL==info) return 0;
210 /* Should probably use _vcd_pbc_max_lid instead? */
211 return uint16_from_be (info->lot_entries);
212 }
213
214 /*!
215 Return the number of menu selections for selection list descriptor psd.
216 */
217 unsigned int
vcdinf_get_num_selections(const PsdSelectionListDescriptor_t * psd)218 vcdinf_get_num_selections(const PsdSelectionListDescriptor_t *psd)
219 {
220 return psd->nos;
221 }
222
223 /*!
224 Get play time value for PsdPlayListDescriptor *d.
225 Time is in 1/15-second units.
226 */
227 uint16_t
vcdinf_get_play_time(const PsdPlayListDescriptor_t * d)228 vcdinf_get_play_time (const PsdPlayListDescriptor_t *d)
229 {
230 if (NULL==d) return 0;
231 return uint16_from_be (d->ptime);
232 }
233
234 /*!
235 Return number of bytes in PSD.
236 */
237 uint32_t
vcdinf_get_psd_size(const InfoVcd_t * info)238 vcdinf_get_psd_size (const InfoVcd_t *info)
239 {
240 if (NULL==info) return 0;
241 return uint32_from_be (info->psd_size);
242 }
243
244 /*!
245 Get timeout wait time value for PsdPlayListDescriptor *d.
246 Return VCDINFO_INVALID_OFFSET if d is NULL;
247 Time is in seconds unless it is -1 (unlimited).
248 */
249 uint16_t
vcdinf_get_timeout_offset(const PsdSelectionListDescriptor_t * d)250 vcdinf_get_timeout_offset (const PsdSelectionListDescriptor_t *d)
251 {
252 if (NULL == d) return VCDINFO_INVALID_OFFSET;
253 return uint16_from_be (d->timeout_ofs);
254 }
255
256 /*!
257 Get timeout wait time value for PsdPlayListDescriptor *d.
258 Time is in seconds unless it is -1 (unlimited).
259 */
260 int
vcdinf_get_timeout_time(const PsdSelectionListDescriptor_t * d)261 vcdinf_get_timeout_time (const PsdSelectionListDescriptor_t *d)
262 {
263 return vcdinfo_get_wait_time (d->totime);
264 }
265
266 /*!
267 Return the track number for entry n in obj. The first track starts
268 at 1. Note this is one less than the track number reported in vcddump.
269 (We don't count the header track?)
270 */
271 track_t
vcdinf_get_track(const EntriesVcd_t * entries,const unsigned int entry_num)272 vcdinf_get_track(const EntriesVcd_t *entries, const unsigned int entry_num)
273 {
274 const unsigned int entry_count = uint16_from_be (entries->entry_count);
275 /* Note entry_num is 0 origin. */
276 return entry_num < entry_count ?
277 cdio_from_bcd8 (entries->entry[entry_num].n):
278 VCDINFO_INVALID_TRACK;
279 }
280
281 /*!
282 Return the VCD volume count - the number of CD's in the collection.
283 */
284 unsigned int
vcdinf_get_volume_count(const InfoVcd_t * info)285 vcdinf_get_volume_count(const InfoVcd_t *info)
286 {
287 if (NULL==info) return 0;
288 return(uint16_from_be( info->vol_count));
289 }
290
291 /*!
292 Return the VCD volume num - the number of the CD in the collection.
293 This is a number between 1 and the volume count.
294 */
295 unsigned int
vcdinf_get_volume_num(const InfoVcd_t * info)296 vcdinf_get_volume_num(const InfoVcd_t *info)
297 {
298 if (NULL == info) return 0;
299 return uint16_from_be(info->vol_id);
300 }
301
302 /*!
303 Get wait time value for PsdPlayListDescriptor *d.
304 Time is in seconds unless it is -1 (unlimited).
305 */
306 int
vcdinf_get_wait_time(const PsdPlayListDescriptor_t * d)307 vcdinf_get_wait_time (const PsdPlayListDescriptor_t *d)
308 {
309 return vcdinfo_get_wait_time (d->wtime);
310 }
311
312 /*!
313 Return true if loop has a jump delay
314 */
315 bool
vcdinf_has_jump_delay(const PsdSelectionListDescriptor_t * psd)316 vcdinf_has_jump_delay (const PsdSelectionListDescriptor_t *psd)
317 {
318 if (NULL==psd) return false;
319 return ((0x80 & psd->loop) != 0);
320 }
321
322 /*!
323 Comparison routine used in sorting. We compare LIDs and if those are
324 equal, use the offset.
325 Note: we assume an unassigned LID is 0 and this compares as a high value.
326
327 NOTE: Consider making static.
328 */
329 int
vcdinf_lid_t_cmp(vcdinfo_offset_t * a,vcdinfo_offset_t * b)330 vcdinf_lid_t_cmp (vcdinfo_offset_t *a, vcdinfo_offset_t *b)
331 {
332 if (a->lid && b->lid)
333 {
334 if (a->lid > b->lid) return +1;
335 if (a->lid < b->lid) return -1;
336 vcd_warn ("LID %d at offset %d has same nunber as LID of offset %d",
337 a->lid, a->offset, b->offset);
338 }
339 else if (a->lid) return -1;
340 else if (b->lid) return +1;
341
342 /* Failed to sort on LID, try offset now. */
343
344 if (a->offset > b->offset) return +1;
345 if (a->offset < b->offset) return -1;
346
347 /* LIDS and offsets are equal. */
348 return 0;
349 }
350
351 /* Get the LID from a given play-list descriptor.
352 VCDINFO_REJECTED_MASK is returned d on error or pld is NULL.
353 */
354 lid_t
vcdinf_pld_get_lid(const PsdPlayListDescriptor_t * pld)355 vcdinf_pld_get_lid(const PsdPlayListDescriptor_t *pld)
356 {
357 return (pld != NULL)
358 ? uint16_from_be (pld->lid) & VCDINFO_LID_MASK
359 : VCDINFO_REJECTED_MASK;
360 }
361
362 /**
363 \fn vcdinfo_pld_get_next_offset(const PsdPlayListDescriptor *pld);
364 \brief Get next offset for a given PSD selector descriptor.
365 \return VCDINFO_INVALID_OFFSET is returned on error or if pld has no "next"
366 entry or pld is NULL. Otherwise the LID offset is returned.
367 */
368 uint16_t
vcdinf_pld_get_next_offset(const PsdPlayListDescriptor_t * pld)369 vcdinf_pld_get_next_offset(const PsdPlayListDescriptor_t *pld)
370 {
371 if (NULL == pld) return VCDINFO_INVALID_OFFSET;
372 return uint16_from_be (pld->next_ofs);
373 }
374
375 /*!
376 Return number of items in LIDs. Return 0 if error or not found.
377 */
378 int
vcdinf_pld_get_noi(const PsdPlayListDescriptor_t * pld)379 vcdinf_pld_get_noi (const PsdPlayListDescriptor_t *pld)
380 {
381 if ( NULL == pld ) return 0;
382 return pld->noi;
383 }
384
385 /*!
386 Return the playlist item i in d.
387 */
388 uint16_t
vcdinf_pld_get_play_item(const PsdPlayListDescriptor_t * pld,unsigned int i)389 vcdinf_pld_get_play_item(const PsdPlayListDescriptor_t *pld, unsigned int i)
390 {
391 if (NULL==pld) return 0;
392 return uint16_from_be(pld->itemid[i]);
393 }
394
395 /**
396 \fn vcdinf_pld_get_prev_offset(const PsdPlayListDescriptor *pld);
397 \brief Get prev offset for a given PSD selector descriptor.
398 \return VCDINFO_INVALID_OFFSET is returned on error or if pld has no "prev"
399 entry or pld is NULL. Otherwise the LID offset is returned.
400 */
401 uint16_t
vcdinf_pld_get_prev_offset(const PsdPlayListDescriptor_t * pld)402 vcdinf_pld_get_prev_offset(const PsdPlayListDescriptor_t *pld)
403 {
404 return (pld != NULL) ?
405 uint16_from_be (pld->prev_ofs) : VCDINFO_INVALID_OFFSET;
406 }
407
408 /**
409 \fn vcdinf_pld_get_return_offset(const PsdPlayListDescriptor *pld);
410 \brief Get return offset for a given PLD selector descriptor.
411 \return VCDINFO_INVALID_OFFSET is returned on error or if pld has no
412 "return" entry or pld is NULL. Otherwise the LID offset is returned.
413 */
414 uint16_t
vcdinf_pld_get_return_offset(const PsdPlayListDescriptor_t * pld)415 vcdinf_pld_get_return_offset(const PsdPlayListDescriptor_t *pld)
416 {
417 return (pld != NULL) ?
418 uint16_from_be (pld->return_ofs) : VCDINFO_INVALID_OFFSET;
419 }
420
421 /**
422 * \fn vcdinfo_psd_get_default_offset(const PsdSelectionListDescriptor *psd);
423 * \brief Get next offset for a given PSD selector descriptor.
424 * \return VCDINFO_INVALID_OFFSET is returned on error or if psd is
425 * NULL. Otherwise the LID offset is returned.
426 */
427 uint16_t
vcdinf_psd_get_default_offset(const PsdSelectionListDescriptor_t * psd)428 vcdinf_psd_get_default_offset(const PsdSelectionListDescriptor_t *psd)
429 {
430 if (NULL == psd) return VCDINFO_INVALID_OFFSET;
431 return uint16_from_be (psd->default_ofs);
432 }
433
434 /*!
435 Get the item id for a given selection-list descriptor.
436 VCDINFO_REJECTED_MASK is returned on error or if psd is NULL.
437 */
438 uint16_t
vcdinf_psd_get_itemid(const PsdSelectionListDescriptor_t * psd)439 vcdinf_psd_get_itemid(const PsdSelectionListDescriptor_t *psd)
440 {
441 return (psd != NULL) ? uint16_from_be(psd->itemid) : VCDINFO_REJECTED_MASK;
442 }
443
444 /*!
445 Get the LID from a given selection-list descriptor.
446 VCDINFO_REJECTED_MASK is returned on error or psd is NULL.
447 */
448 lid_t
vcdinf_psd_get_lid(const PsdSelectionListDescriptor_t * psd)449 vcdinf_psd_get_lid(const PsdSelectionListDescriptor_t *psd)
450 {
451 return (psd != NULL)
452 ? uint16_from_be (psd->lid) & VCDINFO_LID_MASK
453 : VCDINFO_REJECTED_MASK;
454 }
455
456 /*!
457 Get the LID rejected status for a given PSD selector descriptor.
458 true is also returned d is NULL.
459 */
460 bool
vcdinf_psd_get_lid_rejected(const PsdSelectionListDescriptor_t * psd)461 vcdinf_psd_get_lid_rejected(const PsdSelectionListDescriptor_t *psd)
462 {
463 return (psd != NULL)
464 ? vcdinfo_is_rejected(uint16_from_be(psd->lid))
465 : true;
466 }
467
468 /**
469 * \fn vcdinf_psd_get_next_offset(const PsdSelectionListDescriptor *psd);
470 * \brief Get "next" offset for a given PSD selector descriptor.
471 * \return VCDINFO_INVALID_OFFSET is returned on error or if psd is
472 * NULL. Otherwise the LID offset is returned.
473 */
474 uint16_t
vcdinf_psd_get_next_offset(const PsdSelectionListDescriptor_t * psd)475 vcdinf_psd_get_next_offset(const PsdSelectionListDescriptor_t *psd)
476 {
477 if (NULL == psd) return VCDINFO_INVALID_OFFSET;
478 return uint16_from_be (psd->next_ofs);
479 }
480
481 /**
482 * \fn vcdinf_psd_get_offset(const PsdSelectionListDescriptor *d,
483 * unsigned int entry_num);
484 * \brief Get offset entry_num for a given PSD selector descriptor.
485 * \return VCDINFO_INVALID_OFFSET is returned if d on error or d is
486 * NULL. Otherwise the LID offset is returned.
487 */
488 uint16_t
vcdinf_psd_get_offset(const PsdSelectionListDescriptor_t * psd,unsigned int entry_num)489 vcdinf_psd_get_offset(const PsdSelectionListDescriptor_t *psd,
490 unsigned int entry_num)
491 {
492 return (psd != NULL && entry_num < vcdinf_get_num_selections(psd))
493 ? uint16_from_be (psd->ofs[entry_num]) : VCDINFO_INVALID_OFFSET;
494 }
495
496 /**
497 \fn vcdinf_psd_get_prev_offset(const PsdSelectionListDescriptor *psd);
498 \brief Get "prev" offset for a given PSD selector descriptor.
499 \return VCDINFO_INVALID_OFFSET is returned on error or if psd has no "prev"
500 entry or psd is NULL. Otherwise the LID offset is returned.
501 */
502 uint16_t
vcdinf_psd_get_prev_offset(const PsdSelectionListDescriptor_t * psd)503 vcdinf_psd_get_prev_offset(const PsdSelectionListDescriptor_t *psd)
504 {
505 return (psd != NULL) ?
506 uint16_from_be (psd->prev_ofs) : VCDINFO_INVALID_OFFSET;
507 }
508
509 /**
510 * \fn vcdinf_psd_get_return_offset(const PsdSelectionListDescriptor *psd);
511 * \brief Get return offset for a given PSD selector descriptor.
512 \return VCDINFO_INVALID_OFFSET is returned on error or if psd has no
513 "return" entry or psd is NULL. Otherwise the LID offset is returned.
514 */
515 uint16_t
vcdinf_psd_get_return_offset(const PsdSelectionListDescriptor_t * psd)516 vcdinf_psd_get_return_offset(const PsdSelectionListDescriptor_t *psd)
517 {
518 return (psd != NULL) ?
519 uint16_from_be (psd->return_ofs) : VCDINFO_INVALID_OFFSET;
520 }
521
522
523 /*
524 * Local variables:
525 * c-file-style: "gnu"
526 * tab-width: 8
527 * indent-tabs-mode: nil
528 * End:
529 */
530