1# -*- coding: utf-8 -*-
2import logging
3import os
4import platform
5import subprocess
6
7from .constants import SUBSYNC_RESOURCES_ENV_MAGIC
8
9logging.basicConfig(level=logging.INFO)
10logger = logging.getLogger(__name__)
11
12
13# ref: https://github.com/pyinstaller/pyinstaller/wiki/Recipe-subprocess
14# Create a set of arguments which make a ``subprocess.Popen`` (and
15# variants) call work with or without Pyinstaller, ``--noconsole`` or
16# not, on Windows and Linux. Typical use::
17#
18#   subprocess.call(['program_to_run', 'arg_1'], **subprocess_args())
19#
20# When calling ``check_output``::
21#
22#   subprocess.check_output(['program_to_run', 'arg_1'],
23#                           **subprocess_args(False))
24def subprocess_args(include_stdout=True):
25    # The following is true only on Windows.
26    if hasattr(subprocess, 'STARTUPINFO'):
27        # On Windows, subprocess calls will pop up a command window by default
28        # when run from Pyinstaller with the ``--noconsole`` option. Avoid this
29        # distraction.
30        si = subprocess.STARTUPINFO()
31        si.dwFlags |= subprocess.STARTF_USESHOWWINDOW
32        # Windows doesn't search the path by default. Pass it an environment so
33        # it will.
34        env = os.environ
35    else:
36        si = None
37        env = None
38
39    # ``subprocess.check_output`` doesn't allow specifying ``stdout``::
40    #
41    #   Traceback (most recent call last):
42    #     File "test_subprocess.py", line 58, in <module>
43    #       **subprocess_args(stdout=None))
44    #     File "C:\Python27\lib\subprocess.py", line 567, in check_output
45    #       raise ValueError('stdout argument not allowed, it will be overridden.')
46    #   ValueError: stdout argument not allowed, it will be overridden.
47    #
48    # So, add it only if it's needed.
49    if include_stdout:
50        ret = {'stdout': subprocess.PIPE}
51    else:
52        ret = {}
53
54    # On Windows, running this from the binary produced by Pyinstaller
55    # with the ``--noconsole`` option requires redirecting everything
56    # (stdin, stdout, stderr) to avoid an OSError exception
57    # "[Error 6] the handle is invalid."
58    ret.update({'stdin': subprocess.PIPE,
59                'stderr': subprocess.PIPE,
60                'startupinfo': si,
61                'env': env})
62    return ret
63
64
65def ffmpeg_bin_path(bin_name, gui_mode, ffmpeg_resources_path=None):
66    if platform.system() == 'Windows':
67        bin_name = '{}.exe'.format(bin_name)
68    if ffmpeg_resources_path is not None:
69        return os.path.join(ffmpeg_resources_path, bin_name)
70    try:
71        resource_path = os.environ[SUBSYNC_RESOURCES_ENV_MAGIC]
72        if len(resource_path) > 0:
73            return os.path.join(resource_path, 'ffmpeg-bin', bin_name)
74    except KeyError:
75        if gui_mode:
76            logger.info("Couldn't find resource path; falling back to searching system path")
77    return bin_name
78