diff --git a/youtube_dl/YoutubeDL.py b/youtube_dl/YoutubeDL.py index 9e5620eef..5f9653850 100755 --- a/youtube_dl/YoutubeDL.py +++ b/youtube_dl/YoutubeDL.py @@ -37,6 +37,7 @@ from .compat import ( compat_collections_chain_map as ChainMap, compat_filter as filter, compat_get_terminal_size, + compat_getenv, compat_http_client, compat_http_cookiejar_Cookie, compat_http_cookies_SimpleCookie, @@ -66,6 +67,7 @@ from .utils import ( determine_protocol, DownloadError, encode_compat_str, + encodeArgument, encodeFilename, error_to_compat_str, expand_path, @@ -387,6 +389,8 @@ class YoutubeDL(object): self._num_downloads = 0 self._screen_file = [sys.stdout, sys.stderr][params.get('logtostderr', False)] self._err_file = sys.stderr + self._tty_file = None # for --console-title + self._apple_terminal = None self.params = { # Default parameters 'nocheckcertificate': False, @@ -454,6 +458,17 @@ class YoutubeDL(object): 'Parameter outtmpl is bytes, but should be a unicode string. ' 'Put from __future__ import unicode_literals at the top of your code file or consider switching to Python 3.x.') + if (self.params.get('consoletitle', False) + and not self.params.get('simulate', False) + and compat_os_name != 'nt' and 'TERM' in os.environ): + if self._screen_file.isatty(): + self._tty_file = self._screen_file + elif self._err_file != self._screen_file and self._err_file.isatty(): + self._tty_file = self._err_file + else: + self.report_warning('Could not find a tty for output, ignoring --console-title. Either stdout or stderr must be a tty.') + self.params['consoletitle'] = False + self._setup_opener() if auto_init: @@ -573,7 +588,7 @@ class YoutubeDL(object): # already of type unicode() ctypes.windll.kernel32.SetConsoleTitleW(ctypes.c_wchar_p(message)) elif 'TERM' in os.environ: - self._write_string('\033]0;%s\007' % message, self._screen_file) + self._write_string('\033]0;%s\007' % message, self._tty_file) def save_console_title(self): if not self.params.get('consoletitle', False): @@ -581,8 +596,37 @@ class YoutubeDL(object): if self.params.get('simulate', False): return if compat_os_name != 'nt' and 'TERM' in os.environ: - # Save the title on stack - self._write_string('\033[22;0t', self._screen_file) + if not (sys.platform == 'darwin' and compat_getenv('TERM_PROGRAM') == 'Apple_Terminal'): + # Save the title on stack + self._write_string('\033[22;0t', self._tty_file) + else: + # macOS Terminal app + window_title = None + try: + ttyname = os.ttyname(self._tty_file.fileno()) + scpt = [ + 'tell app "Terminal"', + 'repeat with win in (every window)', + 'if tty of win is "%s" then' % ttyname, + 'return custom title of win', + 'end if', + 'end repeat', + 'end tell' + ] + scpt = '\n'.join(scpt).encode('utf-8') + cmd = [encodeFilename('osascript', True), encodeArgument('-')] + p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) + stdout, stderr = p.communicate(input=scpt) + if p.returncode == 0: + window_title = stdout.decode('utf-8').strip() + except EnvironmentError: + pass + if window_title is None or window_title and preferredencoding() != 'UTF-8': + self.report_warning('Window title may not be restored correctly') + if window_title is None: + self._apple_terminal = '' # reset on restore anyway + else: + self._apple_terminal = window_title def restore_console_title(self): if not self.params.get('consoletitle', False): @@ -590,8 +634,11 @@ class YoutubeDL(object): if self.params.get('simulate', False): return if compat_os_name != 'nt' and 'TERM' in os.environ: - # Restore the title from stack - self._write_string('\033[23;0t', self._screen_file) + if self._apple_terminal is None: + # Restore the title from stack + self._write_string('\033[23;0t', self._tty_file) + else: + self._write_string('\033]0;%s\007' % self._apple_terminal, self._tty_file) def __enter__(self): self.save_console_title()