]>
Commit | Line | Data |
---|---|---|
1 | from __future__ import unicode_literals | |
2 | ||
3 | import os | |
4 | ||
5 | from ..compat import compat_str | |
6 | from ..utils import ( | |
7 | cli_configuration_args, | |
8 | encodeFilename, | |
9 | PostProcessingError, | |
10 | ) | |
11 | ||
12 | ||
13 | class PostProcessor(object): | |
14 | """Post Processor class. | |
15 | ||
16 | PostProcessor objects can be added to downloaders with their | |
17 | add_post_processor() method. When the downloader has finished a | |
18 | successful download, it will take its internal chain of PostProcessors | |
19 | and start calling the run() method on each one of them, first with | |
20 | an initial argument and then with the returned value of the previous | |
21 | PostProcessor. | |
22 | ||
23 | The chain will be stopped if one of them ever returns None or the end | |
24 | of the chain is reached. | |
25 | ||
26 | PostProcessor objects follow a "mutual registration" process similar | |
27 | to InfoExtractor objects. | |
28 | ||
29 | Optionally PostProcessor can use a list of additional command-line arguments | |
30 | with self._configuration_args. | |
31 | """ | |
32 | ||
33 | _downloader = None | |
34 | ||
35 | def __init__(self, downloader=None): | |
36 | self._downloader = downloader | |
37 | self.PP_NAME = self.pp_key() | |
38 | ||
39 | @classmethod | |
40 | def pp_key(cls): | |
41 | name = cls.__name__[:-2] | |
42 | return compat_str(name[6:]) if name[:6].lower() == 'ffmpeg' else name | |
43 | ||
44 | def to_screen(self, text, prefix=True, *args, **kwargs): | |
45 | tag = '[%s] ' % self.PP_NAME if prefix else '' | |
46 | if self._downloader: | |
47 | return self._downloader.to_screen('%s%s' % (tag, text), *args, **kwargs) | |
48 | ||
49 | def report_warning(self, text, *args, **kwargs): | |
50 | if self._downloader: | |
51 | return self._downloader.report_warning(text, *args, **kwargs) | |
52 | ||
53 | def report_error(self, text, *args, **kwargs): | |
54 | if self._downloader: | |
55 | return self._downloader.report_error(text, *args, **kwargs) | |
56 | ||
57 | def write_debug(self, text, *args, **kwargs): | |
58 | if self._downloader: | |
59 | return self._downloader.write_debug(text, *args, **kwargs) | |
60 | ||
61 | def get_param(self, name, default=None, *args, **kwargs): | |
62 | if self._downloader: | |
63 | return self._downloader.params.get(name, default, *args, **kwargs) | |
64 | return default | |
65 | ||
66 | def set_downloader(self, downloader): | |
67 | """Sets the downloader for this PP.""" | |
68 | self._downloader = downloader | |
69 | ||
70 | def run(self, information): | |
71 | """Run the PostProcessor. | |
72 | ||
73 | The "information" argument is a dictionary like the ones | |
74 | composed by InfoExtractors. The only difference is that this | |
75 | one has an extra field called "filepath" that points to the | |
76 | downloaded file. | |
77 | ||
78 | This method returns a tuple, the first element is a list of the files | |
79 | that can be deleted, and the second of which is the updated | |
80 | information. | |
81 | ||
82 | In addition, this method may raise a PostProcessingError | |
83 | exception if post processing fails. | |
84 | """ | |
85 | return [], information # by default, keep file and do nothing | |
86 | ||
87 | def try_utime(self, path, atime, mtime, errnote='Cannot update utime of file'): | |
88 | try: | |
89 | os.utime(encodeFilename(path), (atime, mtime)) | |
90 | except Exception: | |
91 | self.report_warning(errnote) | |
92 | ||
93 | def _configuration_args(self, exe, keys=None, default=[], use_compat=True): | |
94 | pp_key = self.pp_key().lower() | |
95 | exe = exe.lower() | |
96 | root_key = exe if pp_key == exe else '%s+%s' % (pp_key, exe) | |
97 | keys = ['%s%s' % (root_key, k) for k in (keys or [''])] | |
98 | if root_key in keys: | |
99 | keys += [root_key] + ([] if pp_key == exe else [(self.pp_key(), exe)]) + ['default'] | |
100 | else: | |
101 | use_compat = False | |
102 | return cli_configuration_args( | |
103 | self.get_param('postprocessor_args'), | |
104 | keys, default, use_compat) | |
105 | ||
106 | ||
107 | class AudioConversionError(PostProcessingError): | |
108 | pass |