8 import rtv_utils
, rtv_programmeinfo
10 allowed_chars_re
= re
.compile( "[a-zA-z0-9_-]" )
12 known_filetypes
= ( ".ts", ".audiots" )
14 def _sanitise_filename( fn
, max_len
):
18 if allowed_chars_re
.match( ch
):
22 return san_fn
[:max_len
]
24 def _get_flv_file_path_from_proginfo( proginfo
):
26 startTime
= proginfo
.startTime
.strftime( "%Y-%m-%d_%H_%M" )
28 if proginfo
.sub_title
:
29 unsan_file
= startTime
[:10] + "_" + str( proginfo
.sub_title
)
30 elif proginfo
.channel_pretty
:
31 unsan_file
= startTime
+ "_" + str( proginfo
.channel_pretty
)
33 unsan_file
= startTime
+ "_" + str( proginfo
.channel
)
35 progname_dir
= _sanitise_filename( proginfo
.title
, 40 )
37 if proginfo
.destination
and proginfo
.destination
!= "":
39 *( _sanitise_filename( fn
, 40 ) for fn
in
40 proginfo
.destination
.split( "/" ) )
42 ret_dir
= os
.path
.join( dest
, progname_dir
)
44 ret_dir
= progname_dir
47 os
.path
.join( ret_dir
, _sanitise_filename( unsan_file
, 40 ) ) )
52 def _get_flv_file_path( rtvinfo
, fallback_filename
):
53 if not os
.path
.isfile( rtvinfo
):
54 print "** Error: rtvinfo file '%s' not found. **" % rtvinfo
56 return ( "", fallback_filename
)
58 proginfo
= rtv_programmeinfo
.ProgrammeInfo()
59 proginfo
.load( rtvinfo
)
61 return _get_flv_file_path_from_proginfo( proginfo
)
63 def _delete_empty_dirs( config
):
65 print "Removing empty directories:"
67 for ( dirpath
, dirnames
, filenames
) in os
.walk(
68 config
.converted_progs_dir
):
69 if len( filenames
) == 0 and len( dirnames
) == 0:
71 # Don't delete the "deleted" dir
72 if ( dirpath
.endswith( "deleted" ) ):
75 empty_dir_name
= os
.path
.join(
76 config
.converted_progs_dir
, dirpath
)
78 os
.rmdir( empty_dir_name
)
81 def convert( config
):
86 for fn
in os
.listdir( config
.recorded_progs_dir
):
88 last_dot_loc
= fn
.rfind( "." )
89 fn_extn
= fn
[ last_dot_loc
: ]
90 fn_stem
= fn
[ : last_dot_loc
]
92 if fn_extn
not in known_filetypes
:
95 fn
= os
.path
.join( config
.recorded_progs_dir
, fn
)
97 rtvinfo
= os
.path
.join( config
.recorded_progs_dir
,
98 fn_stem
+ ".rtvinfo" )
100 (flv_dir
, flv_stem
) = _get_flv_file_path( rtvinfo
, fn_stem
)
102 if fn_extn
== ".audiots":
103 output_dir
= config
.converted_audio_dir
105 convert_command
= config
.audio_convert_command
107 output_dir
= config
.converted_progs_dir
109 convert_command
= config
.convert_command
111 rtv_utils
.ensure_dir_exists(
112 os
.path
.join( output_dir
, flv_dir
) )
114 flv_before
= os
.path
.join( output_dir
,
115 flv_stem
+ "_converting" + final_extn
)
117 flv_after
= os
.path
.join( output_dir
, flv_stem
+ final_extn
)
119 rtvinfo_new
= flv_stem
+ ".rtvinfo"
121 old_dir
= os
.path
.join( config
.recorded_progs_dir
, "old" )
124 retval
= os
.system( convert_command
% (
125 fn
, flv_before
, flv_after
, old_dir
) )
128 print "** Conversion of '%s' returned an error. **" % fn
131 if os
.path
.isfile( rtvinfo
):
132 shutil
.move( rtvinfo
,
133 os
.path
.join( output_dir
, rtvinfo_new
) )
135 _delete_empty_dirs( config
)
138 def rename( config
):
139 # TODO: only renames video, not audio
141 for ( dirpath
, dirnames
, filenames
) in os
.walk(
142 config
.converted_progs_dir
):
145 fn_extension
= fn
[-4:]
147 if fn_extension
not in ( ".flv", ".avi", ".mp4" ):
150 fn_stem
= os
.path
.join( dirpath
, fn
[ : fn
.rfind( "." ) ] )
152 rtvinfo_orig
= os
.path
.join( config
.converted_progs_dir
,
153 fn_stem
+ ".rtvinfo" )
155 flv_orig
= os
.path
.join( config
.converted_progs_dir
,
156 fn_stem
+ fn_extension
)
158 (flv_dir
, flv_stem
) = _get_flv_file_path( rtvinfo_orig
, fn_stem
)
160 rtv_utils
.ensure_dir_exists(
161 os
.path
.join( config
.converted_progs_dir
, flv_dir
) )
163 flv_after
= os
.path
.join( config
.converted_progs_dir
,
164 flv_stem
+ fn_extension
)
166 rtvinfo_after
= os
.path
.join( config
.converted_progs_dir
,
167 flv_stem
+ ".rtvinfo" )
169 if flv_orig
!= flv_after
:
170 print "Renaming %s -> %s" % ( flv_orig
, flv_after
)
171 shutil
.move( flv_orig
, flv_after
)
173 if rtvinfo_orig
!= rtvinfo_after
:
174 print "Renaming %s -> %s" % ( rtvinfo_orig
, rtvinfo_after
)
175 shutil
.move( rtvinfo_orig
, rtvinfo_after
)
177 _delete_empty_dirs( config
)
179 # ------ Test code -----
184 def test_path_from_title_datetime_and_channel():
185 proginfo
= FakeProgInfo()
186 from rtv_saxhandler
import SaxHandler
187 saxhandler
= SaxHandler( None )
188 xmltv_time
= "20091009094500 +0100"
189 proginfo
.startTime
= saxhandler
.parse_time( xmltv_time
)
190 proginfo
.sub_title
= None
191 proginfo
.channel_pretty
= "My Channel"
192 proginfo
.title
= "My Programme"
193 proginfo
.destination
= None
195 (flv_dir
, flv_stem
) = _get_flv_file_path_from_proginfo( proginfo
)
197 assert( flv_dir
== "My_Programme" )
198 assert( flv_stem
== "My_Programme/2009-10-09_09_45_My_Channel" )
200 def test_path_from_destination_title_datetime_and_channel():
201 proginfo
= FakeProgInfo()
202 from rtv_saxhandler
import SaxHandler
203 saxhandler
= SaxHandler( None )
204 xmltv_time
= "20091009094500 +0100"
205 proginfo
.startTime
= saxhandler
.parse_time( xmltv_time
)
206 proginfo
.sub_title
= None
207 proginfo
.channel_pretty
= "My Channel"
208 proginfo
.title
= "My Programme"
209 proginfo
.destination
= "grownups"
211 (flv_dir
, flv_stem
) = _get_flv_file_path_from_proginfo( proginfo
)
213 assert( flv_dir
== "grownups/My_Programme" )
214 assert( flv_stem
== "grownups/My_Programme/2009-10-09_09_45_My_Channel" )
217 def test_multi_destination():
218 proginfo
= FakeProgInfo()
219 from rtv_saxhandler
import SaxHandler
220 saxhandler
= SaxHandler( None )
221 xmltv_time
= "20091009094500 +0100"
222 proginfo
.startTime
= saxhandler
.parse_time( xmltv_time
)
223 proginfo
.sub_title
= None
224 proginfo
.channel_pretty
= "My Channel"
225 proginfo
.title
= "My Programme"
226 proginfo
.destination
= "grownups/movies"
228 (flv_dir
, flv_stem
) = _get_flv_file_path_from_proginfo( proginfo
)
230 assert( flv_dir
== "grownups/movies/My_Programme" )
232 flv_stem
== "grownups/movies/My_Programme/2009-10-09_09_45_My_Channel" )
236 test_path_from_title_datetime_and_channel()
237 test_path_from_destination_title_datetime_and_channel()
238 test_multi_destination()