]> git.sesse.net Git - vlc/blob - modules/access/vcdx/info.c
Merge branch 'master' into lpcm_encoder
[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 along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 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 "info.h"
33
34 #include <cdio/cdio.h>
35 #include <cdio/cd_types.h>
36 #include <cdio/logging.h>
37 #include <cdio/util.h>
38 #include <libvcd/info.h>
39 #include <libvcd/logging.h>
40
41 static char *
42 VCDFormatStr(vcdplayer_t *p_vcdplayer,
43              const char *format_str, const char *mrl,
44              const vcdinfo_itemid_t *itemid);
45 void
46 VCDMetaInfo( access_t *p_access, /*const*/ char *psz_mrl )
47 {
48   vcdplayer_t    *p_vcdplayer  = (vcdplayer_t *) p_access->p_sys;
49   input_thread_t *p_input = p_vcdplayer->p_input;
50   vcdinfo_obj_t  *p_vcdev = p_vcdplayer->vcd;
51
52   size_t i_entries = vcdinfo_get_num_entries(p_vcdev);
53   size_t last_entry = 0;
54   char *psz_cat = _("Disc");
55
56   track_t i_track;
57
58 # define addstr(t,v) input_Control(p_input,INPUT_ADD_INFO,psz_cat,t,"%s",v)
59 # define addnum(t,v) input_Control(p_input,INPUT_ADD_INFO,psz_cat,t,"%d",v)
60 # define addhex(t,v) input_Control(p_input,INPUT_ADD_INFO,psz_cat,t,"%x",v)
61
62   addstr(_("VCD Format"),  vcdinfo_get_format_version_str(p_vcdev));
63   addstr(_("Album"),       vcdinfo_get_album_id          (p_vcdev));
64   addstr(_("Application"), vcdinfo_get_application_id    (p_vcdev));
65   addstr(_("Preparer"),    vcdinfo_get_preparer_id       (p_vcdev));
66   addnum(_("Vol #"),       vcdinfo_get_volume_num        (p_vcdev));
67   addnum(_("Vol max #"),   vcdinfo_get_volume_count      (p_vcdev));
68   addstr(_("Volume Set"),  vcdinfo_get_volumeset_id      (p_vcdev));
69   addstr(_("Volume"),      vcdinfo_get_volume_id         (p_vcdev));
70   addstr(_("Publisher"),   vcdinfo_get_publisher_id      (p_vcdev));
71   addstr(_("System Id"),   vcdinfo_get_system_id         (p_vcdev));
72   addnum("LIDs",           vcdinfo_get_num_LIDs          (p_vcdev));
73   addnum(_("Entries"),     vcdinfo_get_num_entries       (p_vcdev));
74   addnum(_("Segments"),    vcdinfo_get_num_segments      (p_vcdev));
75   addnum(_("Tracks"),      vcdinfo_get_num_tracks        (p_vcdev));
76
77   /* Spit out track information. Could also include MSF info.
78      Also build title table.
79    */
80
81   for( i_track = 1 ; i_track < p_vcdplayer->i_tracks ; i_track++ ) {
82     unsigned int audio_type = vcdinfo_get_track_audio_type(p_vcdev, i_track);
83     uint32_t i_secsize = vcdinfo_get_track_sect_count(p_vcdev, i_track);
84
85     if (p_vcdplayer->b_svd) {
86       addnum(_("Audio Channels"),
87              vcdinfo_audio_type_num_channels(p_vcdev, audio_type) );
88     }
89
90     addnum(_("First Entry Point"), 0 );
91
92     for ( last_entry = 0 ; last_entry < i_entries
93         && vcdinfo_get_track(p_vcdev, last_entry) == i_track; last_entry++ ) ;
94
95     addnum(_("Last Entry Point"), last_entry-1 );
96     addnum(_("Track size (in sectors)"), i_secsize );
97   }
98  
99   {
100     lid_t i_lid;
101     for( i_lid = 1 ; i_lid <= p_vcdplayer->i_lids ; i_lid++ ) {
102       PsdListDescriptor_t pxd;
103       if (vcdinfo_lid_get_pxd(p_vcdev, &pxd, i_lid)) {
104     switch (pxd.descriptor_type) {
105     case PSD_TYPE_END_LIST:
106       addstr(_("type"), _("end"));
107       break;
108     case PSD_TYPE_PLAY_LIST:
109       addstr(_("type"), _("play list"));
110       addnum("items",     vcdinf_pld_get_noi(pxd.pld));
111       addhex("next",      vcdinf_pld_get_next_offset(pxd.pld));
112       addhex("previous",  vcdinf_pld_get_prev_offset(pxd.pld));
113       addhex("return",    vcdinf_pld_get_return_offset(pxd.pld));
114       addnum("wait time", vcdinf_get_wait_time(pxd.pld));
115       break;
116     case PSD_TYPE_SELECTION_LIST:
117     case PSD_TYPE_EXT_SELECTION_LIST:
118       addstr(_("type"), PSD_TYPE_SELECTION_LIST == pxd.descriptor_type
119              ? _("extended selection list") : _("selection list") );
120       addhex("default",          vcdinf_psd_get_default_offset(pxd.psd));
121       addhex("loop count",       vcdinf_get_loop_count(pxd.psd));
122       addhex("next",             vcdinf_psd_get_next_offset(pxd.psd));
123       addhex("previous",         vcdinf_psd_get_prev_offset(pxd.psd));
124       addhex("return",           vcdinf_psd_get_return_offset(pxd.psd));
125       addhex("rejected",         vcdinf_psd_get_lid_rejected(pxd.psd));
126       addhex("time-out offset",  vcdinf_get_timeout_offset(pxd.psd));
127       addnum("time-out time",    vcdinf_get_timeout_time(pxd.psd));
128       break;
129     default:
130       addstr(_("type"), _("unknown type"));
131       break;
132     }
133       }
134     }
135   }
136 # undef  addstr
137 # undef  addnum
138 # undef  addhex
139
140   if ( CDIO_INVALID_TRACK != i_track )
141   {
142     char *psz_tfmt = var_InheritString( p_access, MODULE_STRING "-title-format" );
143     char *psz_name = VCDFormatStr( p_vcdplayer, psz_tfmt, psz_mrl,
144                                                   &(p_vcdplayer->play_item) );
145     free( psz_tfmt );
146  
147     input_Control( p_input, INPUT_SET_NAME, psz_name );
148     free( psz_name );
149   }
150
151 }
152
153 /*!
154    Take a format string and expand escape sequences, that is sequences that
155    begin with %, with information from the current VCD.
156    The expanded string is returned. Here is a list of escape sequences:
157
158    %A : The album information
159    %C : The VCD volume count - the number of CD's in the collection.
160    %c : The VCD volume num - the number of the CD in the collection.
161    %F : The VCD Format, e.g. VCD 1.0, VCD 1.1, VCD 2.0, or SVCD
162    %I : The current entry/segment/playback type, e.g. ENTRY, TRACK, SEGMENT...
163    %L : The playlist ID prefixed with " LID" if it exists
164    %M : MRL
165    %N : The current number of the %I - a decimal number
166    %P : The publisher ID
167    %p : The preparer ID
168    %S : If we are in a segment (menu), the kind of segment
169    %T : The track number
170    %V : The volume set ID
171    %v : The volume ID
172        A number between 1 and the volume count.
173    %% : a %
174 */
175 static char *
176 VCDFormatStr(vcdplayer_t *p_vcdplayer,
177              const char *format_str, const char *mrl,
178              const vcdinfo_itemid_t *itemid)
179 {
180 #define TEMP_STR_SIZE 256
181   char        temp_str[TEMP_STR_SIZE];
182   char       *tp = temp_str;
183   const char *te = tp+TEMP_STR_SIZE-1;
184   bool        saw_control_prefix = false;
185
186   memset(temp_str, 0, TEMP_STR_SIZE);
187
188   for (; *format_str && tp<te; ++format_str) {
189
190     if (!saw_control_prefix && *format_str != '%') {
191       *tp++ = *format_str;
192       saw_control_prefix = false;
193       continue;
194     }
195
196     switch(*format_str) {
197     case '%':
198       if (saw_control_prefix) {
199         *tp++ = '%';
200       }
201       saw_control_prefix = !saw_control_prefix;
202       break;
203     case 'A':
204       tp += snprintf(tp,te-tp,"%s",
205                    vcdinfo_strip_trail(vcdinfo_get_album_id(p_vcdplayer->vcd),
206                                                               MAX_ALBUM_LEN));
207       break;
208
209     case 'c':
210       tp += snprintf(tp,te-tp,"%d",vcdinfo_get_volume_num(p_vcdplayer->vcd));
211       break;
212
213     case 'C':
214       tp += snprintf(tp,te-tp,"%d",vcdinfo_get_volume_count(p_vcdplayer->vcd));
215       break;
216
217     case 'F':
218       tp += snprintf(tp,te-tp,"%s",
219                             vcdinfo_get_format_version_str(p_vcdplayer->vcd));
220       break;
221
222     case 'I':
223       {
224         switch (itemid->type) {
225         case VCDINFO_ITEM_TYPE_TRACK:
226           tp += snprintf(tp,te-tp,"%s",_("Track"));
227         break;
228         case VCDINFO_ITEM_TYPE_ENTRY:
229           tp += snprintf(tp,te-tp,"%s",_("Entry"));
230           break;
231         case VCDINFO_ITEM_TYPE_SEGMENT:
232           tp += snprintf(tp,te-tp,"%s",_("Segment"));
233           break;
234         case VCDINFO_ITEM_TYPE_LID:
235           tp += snprintf(tp,te-tp,"%s",_("List ID"));
236           break;
237         case VCDINFO_ITEM_TYPE_SPAREID2:
238           tp += snprintf(tp,te-tp,"%s",_("Navigation"));
239           break;
240         default:
241           /* What to do? */
242           ;
243         }
244         saw_control_prefix = false;
245       }
246       break;
247
248     case 'L':
249       if (vcdplayer_pbc_is_on(p_vcdplayer))
250         tp += snprintf(tp,te-tp,"%s %d",_("List ID"),p_vcdplayer->i_lid);
251       saw_control_prefix = false;
252       break;
253
254     case 'M':
255       tp += snprintf(tp,te-tp,"%s",mrl);
256       break;
257
258     case 'N':
259       tp += snprintf(tp,te-tp,"%d",itemid->num);
260       break;
261
262     case 'p':
263       tp += snprintf(tp,te-tp,"%s",vcdinfo_get_preparer_id(p_vcdplayer->vcd));
264       break;
265
266     case 'P':
267       tp += snprintf(tp,te-tp,"%s",vcdinfo_get_publisher_id(p_vcdplayer->vcd));
268       break;
269
270     case 'S':
271       if ( VCDINFO_ITEM_TYPE_SEGMENT==itemid->type ) {
272         tp += snprintf(tp,te-tp," %s",
273                 vcdinfo_video_type2str(p_vcdplayer->vcd, itemid->num));
274       }
275       saw_control_prefix = false;
276       break;
277
278     case 'T':
279       tp += snprintf(tp,te-tp,"%d",p_vcdplayer->i_track);
280       break;
281
282     case 'V':
283       tp += snprintf(tp,te-tp,"%s",vcdinfo_get_volumeset_id(p_vcdplayer->vcd));
284       break;
285
286     case 'v':
287       tp += snprintf(tp,te-tp,"%s",vcdinfo_get_volume_id(p_vcdplayer->vcd));
288       break;
289
290     default:
291       *tp++ = '%';
292       if(tp<te)
293         *tp++ = *format_str;
294       saw_control_prefix = false;
295     }
296   }
297   return strdup(temp_str);
298 }
299
300 void
301 VCDUpdateTitle( access_t *p_access )
302 {
303     vcdplayer_t *p_vcdplayer= (vcdplayer_t *)p_access->p_sys;
304
305     size_t psz_mrl_max = strlen(VCD_MRL_PREFIX)
306                        + strlen(p_vcdplayer->psz_source) + sizeof("@E999")+3;
307     char *psz_mrl = malloc( psz_mrl_max );
308
309     if( psz_mrl )
310     {
311         char *psz_name;
312         char *psz_tfmt = var_InheritString( p_access, MODULE_STRING "-title-format" );
313         snprintf( psz_mrl, psz_mrl_max, "%s%s",
314                   VCD_MRL_PREFIX, p_vcdplayer->psz_source );
315         if( psz_tfmt )
316         {
317             psz_name = VCDFormatStr( p_vcdplayer, psz_tfmt, psz_mrl,
318                                      &(p_vcdplayer->play_item) );
319             free(psz_tfmt);
320             input_Control( p_vcdplayer->p_input, INPUT_SET_NAME, psz_name );
321             free(psz_name);
322         }
323         free(psz_mrl);
324     }
325 }
326