]> git.sesse.net Git - vlc/blob - modules/access/vcdx/info.c
vcdx: Fix memleaks.
[vlc] / modules / access / vcdx / info.c
1 /*****************************************************************************
2  * info.c : CD digital audio input information routines
3  *****************************************************************************
4  * Copyright (C) 2004 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Rocky Bernstein <rocky@panix.com>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 #ifdef HAVE_CONFIG_H
25 # include "config.h"
26 #endif
27
28 #include <vlc_common.h>
29 #include <vlc_input.h>
30 #include <vlc_access.h>
31 #include "vcd.h"
32 #include <vlc_keys.h>
33 #include "info.h"
34
35 #include <cdio/cdio.h>
36 #include <cdio/cd_types.h>
37 #include <cdio/logging.h>
38 #include <cdio/util.h>
39 #include <libvcd/info.h>
40 #include <libvcd/logging.h>
41
42 static inline void
43 MetaInfoAddStr(access_t *p_access, char *psz_cat,
44                char *title, const char *psz)
45 {
46   vcdplayer_t *p_vcdplayer = (vcdplayer_t *) p_access->p_sys;
47   if ( psz ) {
48     dbg_print( INPUT_DBG_META, "cat %s, field: %s: %s", psz_cat, title, psz);
49     input_Control( p_vcdplayer->p_input, INPUT_ADD_INFO, psz_cat, title, "%s",
50            psz);
51   }
52 }
53
54
55 static inline void
56 MetaInfoAddNum(access_t *p_access, char *psz_cat, char *title, int num)
57 {
58   vcdplayer_t *p_vcdplayer = (vcdplayer_t *) p_access->p_sys;
59   dbg_print( INPUT_DBG_META, "cat %s, field %s: %d", psz_cat,  title, num);
60   input_Control( p_vcdplayer->p_input, INPUT_ADD_INFO, psz_cat, title,
61          "%d", num );
62 }
63
64 static inline void
65 MetaInfoAddHex(access_t *p_access, char *psz_cat, char *title, int hex)
66 {
67   vcdplayer_t *p_vcdplayer = (vcdplayer_t *) p_access->p_sys;
68   dbg_print( INPUT_DBG_META, "cat %s, field %s: %d", psz_cat, title, hex);
69   input_Control( p_vcdplayer->p_input, INPUT_ADD_INFO, psz_cat, title,
70          "%x", hex );
71 }
72
73 #define addstr(title, str) \
74   MetaInfoAddStr( p_access, psz_cat, title, str );
75
76 #define addnum(title, num) \
77   MetaInfoAddNum( p_access, psz_cat, title, num );
78
79 #define addhex(title, hex) \
80   MetaInfoAddHex( p_access, psz_cat, title, hex );
81
82 void
83 VCDMetaInfo( access_t *p_access, /*const*/ char *psz_mrl )
84 {
85   vcdplayer_t *p_vcdplayer = (vcdplayer_t *) p_access->p_sys;
86   unsigned int i_entries = vcdinfo_get_num_entries(p_vcdplayer->vcd);
87   unsigned int last_entry = 0;
88   char *psz_cat;
89   track_t i_track;
90
91   psz_cat = _("Disc");
92
93   addstr( _("VCD Format"),  vcdinfo_get_format_version_str(p_vcdplayer->vcd) );
94   addstr( _("Album"),       vcdinfo_get_album_id(p_vcdplayer->vcd));
95   addstr( _("Application"), vcdinfo_get_application_id(p_vcdplayer->vcd) );
96   addstr( _("Preparer"),    vcdinfo_get_preparer_id(p_vcdplayer->vcd) );
97   addnum( _("Vol #"),       vcdinfo_get_volume_num(p_vcdplayer->vcd) );
98   addnum( _("Vol max #"),   vcdinfo_get_volume_count(p_vcdplayer->vcd) );
99   addstr( _("Volume Set"),  vcdinfo_get_volumeset_id(p_vcdplayer->vcd) );
100   addstr( _("Volume"),      vcdinfo_get_volume_id(p_vcdplayer->vcd) );
101   addstr( _("Publisher"),   vcdinfo_get_publisher_id(p_vcdplayer->vcd) );
102   addstr( _("System Id"),   vcdinfo_get_system_id(p_vcdplayer->vcd) );
103   addnum( "LIDs",           vcdinfo_get_num_LIDs(p_vcdplayer->vcd) );
104   addnum( _("Entries"),     vcdinfo_get_num_entries(p_vcdplayer->vcd) );
105   addnum( _("Segments"),    vcdinfo_get_num_segments(p_vcdplayer->vcd) );
106   addnum( _("Tracks"),      vcdinfo_get_num_tracks(p_vcdplayer->vcd) );
107
108   /* Spit out track information. Could also include MSF info.
109      Also build title table.
110    */
111
112 #define TITLE_MAX 30
113   for( i_track = 1 ; i_track < p_vcdplayer->i_tracks ; i_track++ ) {
114     char psz_cat[20];
115     unsigned int audio_type = vcdinfo_get_track_audio_type(p_vcdplayer->vcd,
116                                i_track);
117     uint32_t i_secsize = vcdinfo_get_track_sect_count(p_vcdplayer->vcd, i_track);
118
119     snprintf(psz_cat, sizeof(psz_cat), "Track %d", i_track);
120     if (p_vcdplayer->b_svd) {
121       addnum(_("Audio Channels"),
122          vcdinfo_audio_type_num_channels(p_vcdplayer->vcd, audio_type) );
123     }
124
125     addnum(_("First Entry Point"), last_entry );
126     for ( ; last_entry < i_entries
127         && vcdinfo_get_track(p_vcdplayer->vcd, last_entry) == i_track;
128       last_entry++ ) ;
129     addnum(_("Last Entry Point"), last_entry-1 );
130     addnum(_("Track size (in sectors)"), i_secsize );
131   }
132  
133   {
134     lid_t i_lid;
135     for( i_lid = 1 ; i_lid <= p_vcdplayer->i_lids ; i_lid++ ) {
136       PsdListDescriptor_t pxd;
137       char psz_cat[20];
138       snprintf(psz_cat, sizeof(psz_cat), "LID %d", i_lid);
139       if (vcdinfo_lid_get_pxd(p_vcdplayer->vcd, &pxd, i_lid)) {
140     switch (pxd.descriptor_type) {
141     case PSD_TYPE_END_LIST:
142       addstr(_("type"), _("end"));
143       break;
144     case PSD_TYPE_PLAY_LIST:
145       addstr(_("type"), _("play list"));
146       addnum("items",     vcdinf_pld_get_noi(pxd.pld));
147       addhex("next",      vcdinf_pld_get_next_offset(pxd.pld));
148       addhex("previous",  vcdinf_pld_get_prev_offset(pxd.pld));
149       addhex("return",    vcdinf_pld_get_return_offset(pxd.pld));
150       addnum("wait time", vcdinf_get_wait_time(pxd.pld));
151       break;
152     case PSD_TYPE_SELECTION_LIST:
153     case PSD_TYPE_EXT_SELECTION_LIST:
154       addstr(_("type"),
155          PSD_TYPE_SELECTION_LIST == pxd.descriptor_type
156          ? _("extended selection list")
157          : _("selection list")
158          );
159       addhex("default",          vcdinf_psd_get_default_offset(pxd.psd));
160       addhex("loop count",       vcdinf_get_loop_count(pxd.psd));
161       addhex("next",             vcdinf_psd_get_next_offset(pxd.psd));
162       addhex("previous",         vcdinf_psd_get_prev_offset(pxd.psd));
163       addhex("return",           vcdinf_psd_get_return_offset(pxd.psd));
164       addhex("rejected",         vcdinf_psd_get_lid_rejected(pxd.psd));
165       addhex("time-out offset",  vcdinf_get_timeout_offset(pxd.psd));
166       addnum("time-out time",    vcdinf_get_timeout_time(pxd.psd));
167       break;
168     default:
169       addstr(_("type"), _("unknown type"));
170       break;
171     }
172       }
173     }
174   }
175
176   if ( CDIO_INVALID_TRACK != i_track )
177   {
178     char* psz_title_format = config_GetPsz( p_access, MODULE_STRING "-title-format" );
179     char *psz_name =
180       VCDFormatStr( p_access, p_vcdplayer, psz_title_format, psz_mrl,
181                     &(p_vcdplayer->play_item) );
182     free( psz_title_format );
183  
184     input_Control( p_vcdplayer->p_input, INPUT_SET_NAME, psz_name );
185   }
186
187 }
188
189 #define add_format_str_info(val)                   \
190   {                                   \
191     const char *str = strdup(val);                   \
192     unsigned int len;                           \
193     if (val != NULL) {                           \
194       len=strlen(str);                           \
195       if (len != 0) {                           \
196         strncat(tp, str, TEMP_STR_LEN-(tp-temp_str));           \
197         tp += len;                           \
198       }                                                        \
199       saw_control_prefix = false;                   \
200     }                                   \
201   }
202
203 #define add_format_num_info( val, fmt )                   \
204   {                                   \
205     char num_str[10];                           \
206     unsigned int len;                           \
207     sprintf(num_str, fmt, val);                                \
208     len = strlen(num_str);                       \
209     if( len != 0 )                                             \
210     {                                           \
211       strncat(tp, num_str, TEMP_STR_LEN-(tp-temp_str));        \
212       tp += len;                           \
213     }                                   \
214     saw_control_prefix = false;                                \
215   }
216
217 /*!
218    Take a format string and expand escape sequences, that is sequences that
219    begin with %, with information from the current VCD.
220    The expanded string is returned. Here is a list of escape sequences:
221
222    %A : The album information
223    %C : The VCD volume count - the number of CD's in the collection.
224    %c : The VCD volume num - the number of the CD in the collection.
225    %F : The VCD Format, e.g. VCD 1.0, VCD 1.1, VCD 2.0, or SVCD
226    %I : The current entry/segment/playback type, e.g. ENTRY, TRACK, SEGMENT...
227    %L : The playlist ID prefixed with " LID" if it exists
228    %M : MRL
229    %N : The current number of the %I - a decimal number
230    %P : The publisher ID
231    %p : The preparer ID
232    %S : If we are in a segment (menu), the kind of segment
233    %T : The track number
234    %V : The volume set ID
235    %v : The volume ID
236        A number between 1 and the volume count.
237    %% : a %
238 */
239 char *
240 VCDFormatStr(const access_t *p_access, vcdplayer_t *p_vcdplayer,
241              const char format_str[], const char *mrl,
242              const vcdinfo_itemid_t *itemid)
243 {
244 #define TEMP_STR_SIZE 256
245 #define TEMP_STR_LEN (TEMP_STR_SIZE-1)
246   static char    temp_str[TEMP_STR_SIZE];
247   size_t         i;
248   char *         tp = temp_str;
249   bool     saw_control_prefix = false;
250   size_t         format_len = strlen(format_str);
251
252   memset(temp_str, 0, TEMP_STR_SIZE);
253
254   for (i=0; i<format_len; i++) {
255
256     if (!saw_control_prefix && format_str[i] != '%') {
257       *tp++ = format_str[i];
258       saw_control_prefix = false;
259       continue;
260     }
261
262     switch(format_str[i]) {
263     case '%':
264       if (saw_control_prefix) {
265         *tp++ = '%';
266       }
267       saw_control_prefix = !saw_control_prefix;
268       break;
269     case 'A':
270       add_format_str_info(vcdinfo_strip_trail(vcdinfo_get_album_id(p_vcdplayer->vcd),
271                                               MAX_ALBUM_LEN));
272       break;
273
274     case 'c':
275       add_format_num_info(vcdinfo_get_volume_num(p_vcdplayer->vcd), "%d");
276       break;
277
278     case 'C':
279       add_format_num_info(vcdinfo_get_volume_count(p_vcdplayer->vcd), "%d");
280       break;
281
282     case 'F':
283       add_format_str_info(vcdinfo_get_format_version_str(p_vcdplayer->vcd));
284       break;
285
286     case 'I':
287       {
288         switch (itemid->type) {
289         case VCDINFO_ITEM_TYPE_TRACK:
290           strncat(tp, _("Track"), TEMP_STR_LEN-(tp-temp_str));
291           tp += strlen(_("Track"));
292         break;
293         case VCDINFO_ITEM_TYPE_ENTRY:
294           strncat(tp, _("Entry"), TEMP_STR_LEN-(tp-temp_str));
295           tp += strlen(_("Entry"));
296           break;
297         case VCDINFO_ITEM_TYPE_SEGMENT:
298           strncat(tp, _("Segment"), TEMP_STR_LEN-(tp-temp_str));
299           tp += strlen(_("Segment"));
300           break;
301         case VCDINFO_ITEM_TYPE_LID:
302           strncat(tp, _("List ID"), TEMP_STR_LEN-(tp-temp_str));
303           tp += strlen(_("List ID"));
304           break;
305         case VCDINFO_ITEM_TYPE_SPAREID2:
306           strncat(tp, _("Navigation"), TEMP_STR_LEN-(tp-temp_str));
307           tp += strlen(_("Navigation"));
308           break;
309         default:
310           /* What to do? */
311           ;
312         }
313         saw_control_prefix = false;
314       }
315       break;
316
317     case 'L':
318       if (vcdplayer_pbc_is_on(p_vcdplayer)) {
319         char num_str[40];
320         sprintf(num_str, "%s %d", _("List ID"), p_vcdplayer->i_lid);
321         strncat(tp, num_str, TEMP_STR_LEN-(tp-temp_str));
322         tp += strlen(num_str);
323       }
324       saw_control_prefix = false;
325       break;
326
327     case 'M':
328       add_format_str_info(mrl);
329       break;
330
331     case 'N':
332       add_format_num_info(itemid->num, "%d");
333       break;
334
335     case 'p':
336       add_format_str_info(vcdinfo_get_preparer_id(p_vcdplayer->vcd));
337       break;
338
339     case 'P':
340       add_format_str_info(vcdinfo_get_publisher_id(p_vcdplayer->vcd));
341       break;
342
343     case 'S':
344       if ( VCDINFO_ITEM_TYPE_SEGMENT==itemid->type ) {
345         char seg_type_str[30];
346
347         sprintf(seg_type_str, " %s",
348                 vcdinfo_video_type2str(p_vcdplayer->vcd, itemid->num));
349         strncat(tp, seg_type_str, TEMP_STR_LEN-(tp-temp_str));
350         tp += strlen(seg_type_str);
351       }
352       saw_control_prefix = false;
353       break;
354
355     case 'T':
356       add_format_num_info(p_vcdplayer->i_track, "%d");
357       break;
358
359     case 'V':
360       add_format_str_info(vcdinfo_get_volumeset_id(p_vcdplayer->vcd));
361       break;
362
363     case 'v':
364       add_format_str_info(vcdinfo_get_volume_id(p_vcdplayer->vcd));
365       break;
366
367     default:
368       *tp++ = '%';
369       *tp++ = format_str[i];
370       saw_control_prefix = false;
371     }
372   }
373   return strdup(temp_str);
374 }
375
376 void
377 VCDUpdateTitle( access_t *p_access )
378 {
379
380     vcdplayer_t *p_vcdplayer= (vcdplayer_t *)p_access->p_sys;
381
382     unsigned int psz_mrl_max = strlen(VCD_MRL_PREFIX)
383       + strlen(p_vcdplayer->psz_source) + sizeof("@E999")+3;
384     char *psz_mrl = malloc( psz_mrl_max );
385
386     if( psz_mrl )
387     {
388         char *psz_name;
389         char* psz_title_format = config_GetPsz( p_access, MODULE_STRING "-title-format" )
390         snprintf( psz_mrl, psz_mrl_max, "%s%s",
391                   VCD_MRL_PREFIX, p_vcdplayer->psz_source );
392         psz_name = VCDFormatStr( p_access, p_vcdplayer, psz_title_format, psz_mrl,
393                                  &(p_vcdplayer->play_item) );
394         input_Control( p_vcdplayer->p_input, INPUT_SET_NAME, psz_name );
395         free( psz_title_format );
396         free(psz_mrl);
397     }
398 }
399