]> git.sesse.net Git - vlc/blob - share/lua/playlist/cue.lua
Cue: don't round the start values
[vlc] / share / lua / playlist / cue.lua
1 --[[
2    Parse CUE files
3
4  $Id$
5  Copyright (C) 2009 Laurent Aimar
6
7  This program is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation; either version 2 of the License, or
10  (at your option) any later version.
11
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  GNU General Public License for more details.
16
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
20 --]]
21
22 -- Probe function.
23 function probe()
24     if( not string.match( string.upper( vlc.path ), ".CUE$" ) ) then
25         return false
26     end
27     header = vlc.peek( 2048 )
28     return string.match( header, "FILE.*WAVE%s*[\r\n]+" ) or
29            string.match( header, "FILE.*AIFF%s*[\r\n]+" ) or
30            string.match( header, "FILE.*MP3%s*[\r\n]+" )
31 end
32
33 -- Helpers
34 function is_utf8( src )
35     return vlc.strings.from_charset( "UTF-8", src ) == src
36 end
37
38 function cue_string( src )
39     if not is_utf8( src ) then
40         -- Convert to UTF-8 since it's probably Latin1
41         src = vlc.strings.from_charset( "ISO_8859-1", src )
42     end
43     local sub = string.match( src, "^\"(.*)\".*$" );
44     if( sub ) then
45         return sub
46     end
47     return string.match( src, "^(%S+).*$" )
48 end
49
50 function cue_path( src )
51     if( string.match( src, "^/" ) or
52         string.match( src, "^\\" ) or
53         string.match( src, "^[%l%u]:\\" ) ) then
54         return vlc.strings.make_uri(src)
55     end
56
57     local slash = string.find( string.reverse( vlc.path ), '/' )
58         local prefix = vlc.access .. "://" .. string.sub( vlc.path, 1, -slash )
59         -- FIXME: postfix may not be encoded correctly (esp. slashes)
60         local postfix = vlc.strings.encode_uri_component(src)
61     return prefix .. postfix
62 end
63
64 function cue_track( global, track )
65     if( track.index01 == nil ) then
66         return nil
67     end
68
69     t = {}
70     t.path = cue_path( track.file or global.file )
71     t.title = track.title
72     t.album = global.title
73     t.artist = track.performer or global.performer
74     t.genre = track.genre or global.genre
75     t.date = track.date or global.date
76     t.description = global.comment
77     t.tracknum = track.num
78     t.options = { ":start-time=" .. track.index01}
79
80     return t
81 end
82
83 function cue_append( tracks, global, track )
84     local t = cue_track( global, track )
85     if( t ~= nil ) then
86         if( #tracks > 0 ) then
87             local prev = tracks[#tracks]
88             table.insert( prev.options, ":stop-time=" .. track.index01)
89         end
90         table.insert( tracks, t )
91     end
92 end
93
94 -- Parse function.
95 function parse()
96     p = {}
97     global_data = nil
98     data = {}
99     file = nil
100
101     while true
102     do 
103         line = vlc.readline()
104         if not line then break end
105
106         cmd, arg = string.match( line, "^%s*(%S+)%s*(.*)$" )
107
108         if(  cmd == "REM" and arg ) then
109             subcmd, value = string.match( arg, "^(%S+)%s*(.*)$" )
110             if( subcmd == "GENRE" and value ) then
111                 data.genre = cue_string( value )
112             elseif( subcmd == "DATE" and value ) then
113                 data.date = cue_string( value )
114             elseif( subcmd == "COMMENT" and value ) then
115                 data.comment = cue_string( value )
116             end
117         elseif( cmd == "PERFORMER" and arg ) then
118             data.performer = cue_string( arg )
119         elseif( cmd == "TITLE" and arg ) then
120             data.title = cue_string( arg )
121         elseif( cmd == "FILE" ) then
122             file = cue_string( arg )
123         elseif( cmd == "TRACK" ) then
124             if( not global_data ) then
125                 global_data = data
126             else
127                 cue_append( p, global_data, data )
128             end
129             data =  { file = file, num = string.match( arg, "^(%d+)" ) }
130         elseif( cmd == "INDEX" ) then
131             local idx, m, s, f = string.match( arg, "(%d+)%s+(%d+):(%d+):(%d+)" )
132             if( idx == "01" and m ~= nil and s ~= nil and f ~= nil ) then
133                 data.index01 = m * 60 + s + f / 75
134             end
135         end
136     end
137
138     cue_append( p, global_data, data )
139
140     return p
141 end
142