# -*- coding: utf-8 -*-

## \package globals.ffmpeg
#  
#  Retrieves the FFmpeg executable

# MIT licensing
# See: LICENSE.txt


import subprocess
from subprocess import PIPE
from subprocess import STDOUT

from globals.system import PY_VER_MAJ


## Locates an executable
#  
#  \param cmd
#    \b \e unicode|str : Name of the executable to search for
#  \return
#    \b \e unicode|str : Absolute path to executable or None if not found
def GetExecutable(cmd):
    output, returncode = subprocess.Popen((u'which', cmd,), stdout=PIPE, stderr=STDOUT).communicate()
    
    # FIXME: subprocess is adding newline at end of output
    output = output.rstrip(u'\n')
    
    if returncode:
        return None
    
    if PY_VER_MAJ < 3:
        output = unicode(output)
    
    return output


CMD_ffmpeg = GetExecutable(u'ffmpeg')


# --- Check to see if ffmpeg supports xvid and x264
no_xvid = subprocess.call(u'{} -codecs | grep -i "libxvid"'.format(CMD_ffmpeg), stdout=PIPE, stderr=PIPE, shell=True)
if no_xvid:
    no_xvid = subprocess.call(u'{} -formats | grep -i "libxvid"'.format(CMD_ffmpeg), stdout=PIPE, stderr=PIPE, shell=True)

no_x264 = subprocess.call(u'{} -codecs | grep -i "libx264"'.format(CMD_ffmpeg), stdout=PIPE, stderr=PIPE, shell=True)
if no_x264:
    no_x264 = subprocess.call(u'{} -formats | grep -i "libx264"'.format(CMD_ffmpeg), stdout=PIPE, stderr=PIPE, shell=True)


## Retrieves a list of input devices
def GetFFmpegList(switch, t_filter=None, t_index=None, description=False):
    if not CMD_ffmpeg:
        print(u'Error: Cannot find ffmpeg executable')
        
        return
    
    output, returncode = subprocess.Popen((CMD_ffmpeg, u'-{}'.format(switch),), stdout=PIPE, stderr=STDOUT).communicate()
    
    if returncode:
        print(u'Error: Could not get list for option "-{}"'.format(switch))
        return
    
    output = output.strip().split(u'\n')
    
    output_list = []
    for LI in reversed(output):
        LI = LI.strip()
        
        if LI[:2] == u'--':
            break
        
        if description:
            LI = LI.split()
            
            s_types = LI[0]
            s_name = LI[1]
            s_desc = u' '.join(LI[2:])
            
            if u',' in s_name:
                s_name = s_name.split(u',')[0]
            
            if t_filter and t_filter in s_types:
                output_list.append((s_name, s_desc))
                
                continue
            
            output_list.append((s_name, s_desc,))
            
            continue
        
        LI = LI.split()[:2]
        
        if u',' in LI[1]:
            LI[1] = LI[1].split(u',')[0]
        
        if t_filter:
            if t_index == None:
                if t_filter in LI[0]:
                    output_list.append(LI[1])
            
            else:
                if LI[t_index] == t_filter:
                    output_list.append(LI[1])
            
            continue
        
        output_list.append(LI)
    
    return tuple(sorted(output_list))


## Get a list of containers available for file output
def GetContainers():
    mpeg_formats = (
        u'mpeg',
        u'mpeg1video',
        u'mpeg2video',
        u'mpegts',
        u'mpegtsraw',
        u'mpegvideo',
        )
    containers = list(GetFFmpegList(u'formats', u'E'))
    
    if u'mpg' not in containers:
        for MPG in mpeg_formats:
            if MPG in containers:
                containers.append(u'mpg')
                break
    
    return tuple(sorted(containers))


## Retrieves a list of usable encoders from FFmpeg
def GetEncoders():
    #codecs = GetFFmpegList(u'encoders', codec_type[0].upper())
    codec_list = GetFFmpegList(u'encoders')
    
    v_codecs = []
    a_codecs = []
    for C in codec_list:
        codec_type = C[0][0]
        codec = C[1]
        
        if codec_type == u'V':
            v_codecs.append(codec)
        
        elif codec_type == u'A':
            a_codecs.append(codec)
    
    return {u'video': tuple(sorted(v_codecs)), u'audio': tuple(sorted(a_codecs))}


## Get a list of available input devices
def GetInputDevices():
    devices = GetFFmpegList(u'devices', u'D', description=True)
    
    v_keywords = (u'video', u'a/v', u'dv', u'sdl', u'x11', u'screen',)
    a_keywords = (u'audio', u'a/v', u'sound', u'sdl',)
    
    v_devices = []
    a_devices = []
    
    for D in devices:
        for V in v_keywords:
            if V in D[1].lower():
                v_devices.append(D)
        
        for A in a_keywords:
            if A in D[1].lower():
                a_devices.append(D)
    
    devices = {
        u'video': tuple(sorted(v_devices)),
        u'audio': tuple(sorted(a_devices)),
        }
    
    return devices

@@ -4349,24 +4349,40 @@
 evices = %5B%5D%0A
+    v_defs = %5B%5D%0A
     a_device
@@ -4396,29 +4396,58 @@
     
-%0A    for D in 
+a_defs = %5B%5D%0A    %0A    for D, DEF in sorted(
 devices
+)
 :%0A  
@@ -4490,27 +4490,26 @@
    if V in D
-%5B1%5D
+EF
 .lower():%0A  
@@ -4538,24 +4538,81 @@
 s.append(D)%0A
+                v_defs.append(DEF)%0A                break%0A
         %0A   
@@ -4658,19 +4658,18 @@
 f A in D
-%5B1%5D
+EF
 .lower()
@@ -4702,24 +4702,81 @@
 s.append(D)%0A
+                a_defs.append(DEF)%0A                break%0A
     %0A    dev
@@ -4806,29 +4806,38 @@
 o': 
+(
 tuple(
-sorted
+v_devices), tuple
 (v_de
-vice
+f
 s)),
@@ -4859,29 +4859,38 @@
 o': 
+(
 tuple(
-sorted
+a_devices), tuple
 (a_de
-vice
+f
 s)),

Change format of returned dictionary in GetInputDevices