64
64
class MovieWriterRegistry (object ):
65
65
def __init__ (self ):
66
66
self .avail = dict ()
67
+ self ._registered = dict ()
68
+ self ._dirty = False
69
+
70
+ def set_dirty (self ):
71
+ """Sets a flag to re-setup the writers"""
72
+ self ._dirty = True
67
73
68
74
# Returns a decorator that can be used on classes to register them under
69
75
# a name. As in:
@@ -72,19 +78,36 @@ def __init__(self):
72
78
# pass
73
79
def register (self , name ):
74
80
def wrapper (writerClass ):
81
+ self ._registered [name ] = writerClass
75
82
if writerClass .isAvailable ():
76
83
self .avail [name ] = writerClass
77
84
return writerClass
78
85
return wrapper
79
86
87
+ def ensure_not_dirty (self ):
88
+ """If dirty, reasks the writers if they are available"""
89
+ if self ._dirty :
90
+ self .reset_available_writers ()
91
+
92
+ def reset_available_writers (self ):
93
+ """Reset the available state of all registered writers"""
94
+ self .avail = {}
95
+ for name , writerClass in self ._registered .items ():
96
+ if writerClass .isAvailable ():
97
+ self .avail [name ] = writerClass
98
+ self ._dirty = False
99
+
80
100
def list (self ):
81
101
''' Get a list of available MovieWriters.'''
102
+ self .ensure_not_dirty ()
82
103
return list (self .avail .keys ())
83
104
84
105
def is_available (self , name ):
106
+ self .ensure_not_dirty ()
85
107
return name in self .avail
86
108
87
109
def __getitem__ (self , name ):
110
+ self .ensure_not_dirty ()
88
111
if not self .avail :
89
112
raise RuntimeError ("No MovieWriters available!" )
90
113
return self .avail [name ]
@@ -275,10 +298,11 @@ def isAvailable(cls):
275
298
Check to see if a MovieWriter subclass is actually available by
276
299
running the commandline tool.
277
300
'''
278
- if not cls .bin_path ():
301
+ bin_path = cls .bin_path ()
302
+ if not bin_path :
279
303
return False
280
304
try :
281
- p = subprocess .Popen (cls . bin_path () ,
305
+ p = subprocess .Popen (bin_path ,
282
306
shell = False ,
283
307
stdout = subprocess .PIPE ,
284
308
stderr = subprocess .PIPE ,
@@ -397,9 +421,19 @@ def finish(self):
397
421
# Check error code for creating file here, since we just run
398
422
# the process here, rather than having an open pipe.
399
423
if self ._proc .returncode :
400
- raise RuntimeError ('Error creating movie, return code: '
401
- + str (self ._proc .returncode )
402
- + ' Try running with --verbose-debug' )
424
+ try :
425
+ stdout = [s .decode () for s in self ._proc ._stdout_buff ]
426
+ stderr = [s .decode () for s in self ._proc ._stderr_buff ]
427
+ verbose .report ("MovieWriter.finish: stdout: %s" % stdout ,
428
+ level = 'helpful' )
429
+ verbose .report ("MovieWriter.finish: stderr: %s" % stderr ,
430
+ level = 'helpful' )
431
+ except Exception as e :
432
+ pass
433
+ msg = ('Error creating movie, return code: ' +
434
+ str (self ._proc .returncode ) +
435
+ ' Try setting mpl.verbose.set_level("helpful")' )
436
+ raise RuntimeError (msg )
403
437
404
438
def cleanup (self ):
405
439
MovieWriter .cleanup (self )
@@ -584,12 +618,28 @@ def _init_from_registry(cls):
584
618
binpath = ''
585
619
rcParams [cls .exec_key ] = rcParamsDefault [cls .exec_key ] = binpath
586
620
621
+ @classmethod
622
+ def isAvailable (cls ):
623
+ '''
624
+ Check to see if a ImageMagickWriter is actually available
625
+
626
+ Done by first checking the windows registry (if applicable) and then
627
+ running the commandline tool.
628
+ '''
629
+ bin_path = cls .bin_path ()
630
+ if bin_path == "convert" :
631
+ cls ._init_from_registry ()
632
+ return super (ImageMagickBase , cls ).isAvailable ()
587
633
588
634
ImageMagickBase ._init_from_registry ()
589
635
590
636
637
+ # Note: the base classes need to be in that order to get
638
+ # isAvailable() from ImageMagickBase called and not the
639
+ # one from MovieWriter. The latter is then called by the
640
+ # former.
591
641
@writers .register ('imagemagick' )
592
- class ImageMagickWriter (MovieWriter , ImageMagickBase ):
642
+ class ImageMagickWriter (ImageMagickBase , MovieWriter ):
593
643
def _args (self ):
594
644
return ([self .bin_path (),
595
645
'-size' , '%ix%i' % self .frame_size , '-depth' , '8' ,
@@ -598,8 +648,12 @@ def _args(self):
598
648
+ self .output_args )
599
649
600
650
651
+ # Note: the base classes need to be in that order to get
652
+ # isAvailable() from ImageMagickBase called and not the
653
+ # one from MovieWriter. The latter is then called by the
654
+ # former.
601
655
@writers .register ('imagemagick_file' )
602
- class ImageMagickFileWriter (FileMovieWriter , ImageMagickBase ):
656
+ class ImageMagickFileWriter (ImageMagickBase , FileMovieWriter ):
603
657
supported_formats = ['png' , 'jpeg' , 'ppm' , 'tiff' , 'sgi' , 'bmp' ,
604
658
'pbm' , 'raw' , 'rgba' ]
605
659
0 commit comments