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