]> git.sesse.net Git - vlc/blob - modules/access/vcdx/info.c
Cleanups towards getting this to a usable state.
[vlc] / modules / access / vcdx / info.c
1 /*****************************************************************************
2  * info.c : CD digital audio input information routines
3  *****************************************************************************
4  * Copyright (C) 2004 VideoLAN
5  * $Id: info.c 8845 2004-09-29 09:00:41Z rocky $
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., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 #include <vlc/vlc.h>
25 #include <vlc/input.h>
26
27 #include "vcd.h"
28 #include <vlc_playlist.h> 
29 #include "vcdplayer.h"
30 #include "vlc_keys.h"
31
32 #include <cdio/cdio.h>
33 #include <cdio/cd_types.h>
34 #include <cdio/logging.h>
35 #include <cdio/util.h>
36 #include <libvcd/info.h>
37 #include <libvcd/logging.h>
38
39 static char *VCDFormatStr(const access_t *p_access, access_vcd_data_t *p_vcd,
40                           const char format_str[], const char *mrl,
41                           const vcdinfo_itemid_t *itemid);
42
43 static inline void
44 MetaInfoAddStr(access_t *p_access, char *p_cat,
45                char *title, const char *str)
46 {
47   access_vcd_data_t *p_vcd = (access_vcd_data_t *) p_access->p_sys;
48   if ( str ) {
49     dbg_print( INPUT_DBG_META, "field: %s: %s", title, str);
50     input_Control( p_vcd->p_input, INPUT_ADD_INFO, p_cat, title, "%s", str);
51   }
52 }
53
54
55 static inline void
56 MetaInfoAddNum(access_t *p_access, char *psz_cat, char *title, int num)
57 {
58   access_vcd_data_t *p_vcd = (access_vcd_data_t *) p_access->p_sys;
59   dbg_print( INPUT_DBG_META, "field %s: %d", title, num);
60   input_Control( p_vcd->p_input, INPUT_ADD_INFO, psz_cat, title, "%d", num );
61 }
62
63 #define addstr(title, str) \
64   MetaInfoAddStr( p_access, psz_cat, title, str );
65
66 #define addnum(title, num) \
67   MetaInfoAddNum( p_access, psz_cat, title, num );
68
69 void 
70 VCDMetaInfo( access_t *p_access, /*const*/ char *psz_mrl )
71 {
72   access_vcd_data_t *p_vcd = (access_vcd_data_t *) p_access->p_sys;
73   unsigned int i_entries = vcdinfo_get_num_entries(p_vcd->vcd);
74   unsigned int last_entry = 0;
75   char *psz_cat;
76   track_t i_track;
77
78   psz_cat = _("General");
79
80   addstr( _("VCD Format"),  vcdinfo_get_format_version_str(p_vcd->vcd) );
81   addstr( _("Album"),       vcdinfo_get_album_id(p_vcd->vcd));
82   addstr( _("Application"), vcdinfo_get_application_id(p_vcd->vcd) );
83   addstr( _("Preparer"),    vcdinfo_get_preparer_id(p_vcd->vcd) );
84   addnum( _("Vol #"),       vcdinfo_get_volume_num(p_vcd->vcd) );
85   addnum( _("Vol max #"),   vcdinfo_get_volume_count(p_vcd->vcd) );
86   addstr( _("Volume Set"),  vcdinfo_get_volumeset_id(p_vcd->vcd) );
87   addstr( _("Volume"),      vcdinfo_get_volume_id(p_vcd->vcd) );
88   addstr( _("Publisher"),   vcdinfo_get_publisher_id(p_vcd->vcd) );
89   addstr( _("System Id"),   vcdinfo_get_system_id(p_vcd->vcd) );
90   addnum( "LIDs",           vcdinfo_get_num_LIDs(p_vcd->vcd) );
91   addnum( _("Entries"),     vcdinfo_get_num_entries(p_vcd->vcd) );
92   addnum( _("Segments"),    vcdinfo_get_num_segments(p_vcd->vcd) );
93   addnum( _("Tracks"),      vcdinfo_get_num_tracks(p_vcd->vcd) );
94
95   /* Spit out track information. Could also include MSF info.
96      Also build title table.
97    */
98
99 #define TITLE_MAX 30
100   for( i_track = 1 ; i_track < p_vcd->i_tracks ; i_track++ ) {
101     unsigned int audio_type = vcdinfo_get_track_audio_type(p_vcd->vcd, 
102                                                            i_track);
103     uint32_t i_secsize = vcdinfo_get_track_sect_count(p_vcd->vcd, i_track);
104
105     if (p_vcd->b_svd) {
106       addnum(_("Audio Channels"),  
107              vcdinfo_audio_type_num_channels(p_vcd->vcd, audio_type) );
108     }
109
110     addnum(_("First Entry Point"), last_entry );
111     for ( ; last_entry < i_entries 
112             && vcdinfo_get_track(p_vcd->vcd, last_entry) == i_track;
113           last_entry++ ) ;
114     addnum(_("Last Entry Point"), last_entry-1 );
115     addnum(_("Track size (in sectors)"), i_secsize );
116   }
117
118   if ( CDIO_INVALID_TRACK != i_track )
119   { 
120     char *psz_name = 
121       VCDFormatStr( p_access, p_vcd,
122                     config_GetPsz( p_access, MODULE_STRING "-title-format" ),
123                     psz_mrl, &(p_vcd->play_item) );
124     
125     input_Control( p_vcd->p_input, INPUT_SET_NAME, psz_name );
126   }
127
128 }
129
130 #define add_format_str_info(val)                               \
131   {                                                            \
132     const char *str = val;                                     \
133     unsigned int len;                                          \
134     if (val != NULL) {                                         \
135       len=strlen(str);                                         \
136       if (len != 0) {                                          \
137         strncat(tp, str, TEMP_STR_LEN-(tp-temp_str));          \
138         tp += len;                                             \
139       }                                                        \
140       saw_control_prefix = VLC_FALSE;                          \
141     }                                                          \
142   }
143
144 #define add_format_num_info( val, fmt )                        \
145   {                                                            \
146     char num_str[10];                                          \
147     unsigned int len;                                          \
148     sprintf(num_str, fmt, val);                                \
149     len = strlen(num_str);                                     \
150     if( len != 0 )                                             \
151     {                                                          \
152       strncat(tp, num_str, TEMP_STR_LEN-(tp-temp_str));        \
153       tp += len;                                               \
154     }                                                          \
155     saw_control_prefix = VLC_FALSE;                                \
156   }
157
158 /*!
159    Take a format string and expand escape sequences, that is sequences that
160    begin with %, with information from the current VCD.
161    The expanded string is returned. Here is a list of escape sequences:
162
163    %A : The album information
164    %C : The VCD volume count - the number of CD's in the collection.
165    %c : The VCD volume num - the number of the CD in the collection.
166    %F : The VCD Format, e.g. VCD 1.0, VCD 1.1, VCD 2.0, or SVCD
167    %I : The current entry/segment/playback type, e.g. ENTRY, TRACK, SEGMENT...
168    %L : The playlist ID prefixed with " LID" if it exists
169    %M : MRL
170    %N : The current number of the %I - a decimal number
171    %P : The publisher ID
172    %p : The preparer ID
173    %S : If we are in a segment (menu), the kind of segment
174    %T : The track number
175    %V : The volume set ID
176    %v : The volume ID
177        A number between 1 and the volume count.
178    %% : a %
179 */
180 char *
181 VCDFormatStr(const access_t *p_access, access_vcd_data_t *p_vcd,
182              const char format_str[], const char *mrl,
183              const vcdinfo_itemid_t *itemid)
184 {
185 #define TEMP_STR_SIZE 256
186 #define TEMP_STR_LEN (TEMP_STR_SIZE-1)
187   static char    temp_str[TEMP_STR_SIZE];
188   size_t         i;
189   char *         tp = temp_str;
190   vlc_bool_t     saw_control_prefix = VLC_FALSE;
191   size_t         format_len = strlen(format_str);
192
193   memset(temp_str, 0, TEMP_STR_SIZE);
194
195   for (i=0; i<format_len; i++) {
196
197     if (!saw_control_prefix && format_str[i] != '%') {
198       *tp++ = format_str[i];
199       saw_control_prefix = VLC_FALSE;
200       continue;
201     }
202
203     switch(format_str[i]) {
204     case '%':
205       if (saw_control_prefix) {
206         *tp++ = '%';
207       }
208       saw_control_prefix = !saw_control_prefix;
209       break;
210     case 'A':
211       add_format_str_info(vcdinfo_strip_trail(vcdinfo_get_album_id(p_vcd->vcd),
212                                               MAX_ALBUM_LEN));
213       break;
214
215     case 'c':
216       add_format_num_info(vcdinfo_get_volume_num(p_vcd->vcd), "%d");
217       break;
218
219     case 'C':
220       add_format_num_info(vcdinfo_get_volume_count(p_vcd->vcd), "%d");
221       break;
222
223     case 'F':
224       add_format_str_info(vcdinfo_get_format_version_str(p_vcd->vcd));
225       break;
226
227     case 'I':
228       {
229         switch (itemid->type) {
230         case VCDINFO_ITEM_TYPE_TRACK:
231           strncat(tp, _("Track"), TEMP_STR_LEN-(tp-temp_str));
232           tp += strlen(_("Track"));
233         break;
234         case VCDINFO_ITEM_TYPE_ENTRY:
235           strncat(tp, _("Entry"), TEMP_STR_LEN-(tp-temp_str));
236           tp += strlen(_("Entry"));
237           break;
238         case VCDINFO_ITEM_TYPE_SEGMENT:
239           strncat(tp, _("Segment"), TEMP_STR_LEN-(tp-temp_str));
240           tp += strlen(_("Segment"));
241           break;
242         case VCDINFO_ITEM_TYPE_LID:
243           strncat(tp, _("List ID"), TEMP_STR_LEN-(tp-temp_str));
244           tp += strlen(_("List ID"));
245           break;
246         case VCDINFO_ITEM_TYPE_SPAREID2:
247           strncat(tp, _("Navigation"), TEMP_STR_LEN-(tp-temp_str));
248           tp += strlen(_("Navigation"));
249           break;
250         default:
251           /* What to do? */
252           ;
253         }
254         saw_control_prefix = VLC_FALSE;
255       }
256       break;
257
258     case 'L':
259       if (vcdplayer_pbc_is_on(p_vcd)) {
260         char num_str[40];
261         sprintf(num_str, "%s %d", _("List ID"), p_vcd->i_lid);
262         strncat(tp, num_str, TEMP_STR_LEN-(tp-temp_str));
263         tp += strlen(num_str);
264       }
265       saw_control_prefix = VLC_FALSE;
266       break;
267
268     case 'M':
269       add_format_str_info(mrl);
270       break;
271
272     case 'N':
273       add_format_num_info(itemid->num, "%d");
274       break;
275
276     case 'p':
277       add_format_str_info(vcdinfo_get_preparer_id(p_vcd->vcd));
278       break;
279
280     case 'P':
281       add_format_str_info(vcdinfo_get_publisher_id(p_vcd->vcd));
282       break;
283
284     case 'S':
285       if ( VCDINFO_ITEM_TYPE_SEGMENT==itemid->type ) {
286         char seg_type_str[10];
287
288         sprintf(seg_type_str, " %s",
289                 vcdinfo_video_type2str(p_vcd->vcd, itemid->num));
290         strncat(tp, seg_type_str, TEMP_STR_LEN-(tp-temp_str));
291         tp += strlen(seg_type_str);
292       }
293       saw_control_prefix = VLC_FALSE;
294       break;
295
296     case 'T':
297       add_format_num_info(p_vcd->i_track, "%d");
298       break;
299
300     case 'V':
301       add_format_str_info(vcdinfo_get_volumeset_id(p_vcd->vcd));
302       break;
303
304     case 'v':
305       add_format_str_info(vcdinfo_get_volume_id(p_vcd->vcd));
306       break;
307
308     default:
309       *tp++ = '%';
310       *tp++ = format_str[i];
311       saw_control_prefix = VLC_FALSE;
312     }
313   }
314   return strdup(temp_str);
315 }
316
317 static void
318 VCDCreatePlayListItem(const access_t *p_access,
319                       access_vcd_data_t *p_vcd,
320                       playlist_t *p_playlist,
321                       const vcdinfo_itemid_t *itemid,
322                       char *psz_mrl, int psz_mrl_max,
323                       const char *psz_source, int playlist_operation,
324                       int i_pos)
325 {
326   char *p_author;
327   char *p_title;
328   char c_type;
329
330   switch(itemid->type) {
331   case VCDINFO_ITEM_TYPE_TRACK:
332     c_type='T';
333     break;
334   case VCDINFO_ITEM_TYPE_SEGMENT:
335     c_type='S';
336     break;
337   case VCDINFO_ITEM_TYPE_LID:
338     c_type='P';
339     break;
340   case VCDINFO_ITEM_TYPE_ENTRY:
341     c_type='E';
342     break;
343   default:
344     c_type='?';
345     break;
346   }
347
348   snprintf(psz_mrl, psz_mrl_max, "%s%s@%c%u", VCD_MRL_PREFIX, psz_source,
349            c_type, itemid->num);
350
351   p_title =
352     VCDFormatStr( p_access, p_vcd,
353                   config_GetPsz( p_access, MODULE_STRING "-title-format" ),
354                   psz_mrl, itemid );
355   
356   playlist_Add( p_playlist, psz_mrl, p_title, playlist_operation, i_pos );
357
358   p_author =
359     VCDFormatStr( p_access, p_vcd,
360                   config_GetPsz( p_access, MODULE_STRING "-author-format" ),
361                   psz_mrl, itemid );
362
363   if( i_pos == PLAYLIST_END ) i_pos = p_playlist->i_size - 1;
364   playlist_AddInfo(p_playlist, i_pos, _("General"), _("Author"), "%s",
365                    p_author);
366 }
367
368 int
369 VCDFixupPlayList( access_t *p_access, access_vcd_data_t *p_vcd,
370                   const char *psz_source, vcdinfo_itemid_t *itemid,
371                   vlc_bool_t b_single_item )
372 {
373   unsigned int i;
374   playlist_t * p_playlist;
375   char       * psz_mrl;
376   unsigned int psz_mrl_max = strlen(VCD_MRL_PREFIX) + strlen(psz_source) +
377     strlen("@T") + strlen("100") + 1;
378
379   psz_mrl = malloc( psz_mrl_max );
380
381   if( psz_mrl == NULL )
382     {
383       msg_Warn( p_access, "out of memory" );
384       return -1;
385     }
386
387   p_playlist = (playlist_t *) vlc_object_find( p_access, VLC_OBJECT_PLAYLIST,
388                                                FIND_ANYWHERE );
389   if( !p_playlist )
390     {
391       msg_Warn( p_access, "can't find playlist" );
392       free(psz_mrl);
393       return -1;
394     }
395
396   {
397     vcdinfo_itemid_t list_itemid;
398     list_itemid.type=VCDINFO_ITEM_TYPE_ENTRY;
399
400     playlist_LockDelete( p_playlist, p_playlist->i_index);
401
402     for( i = 0 ; i < p_vcd->i_entries ; i++ )
403       {
404         list_itemid.num=i;
405         VCDCreatePlayListItem(p_access, p_vcd, p_playlist, &list_itemid,
406                               psz_mrl, psz_mrl_max, psz_source,
407                               PLAYLIST_APPEND, PLAYLIST_END);
408       }
409
410 #if LOOKED_OVER
411     playlist_Command( p_playlist, PLAYLIST_GOTO, 0 );
412 #endif
413
414   }
415
416   vlc_object_release( p_playlist );
417   free(psz_mrl);
418   return 0;
419 }
420