autoProcessMovie.py calling Ember Media Manager problem

Come up with a useful post-processing script? Share it here!
Post Reply
User avatar
redglory
Newbie
Newbie
Posts: 9
Joined: August 31st, 2012, 8:53 am

autoProcessMovie.py calling Ember Media Manager problem

Post by redglory »

Hi,

I'm running an Windows 7 htpc (refer to my sig)

I've been trying to integrate clinton.hall's autoProcessMovie.py with Ember Media Manager, so that after CPS renames my movies, I than get extra scrapping data from it.

my autoProcessMovie.py looks like this for Ember calling:

Code: Select all

def run_ember():

	###########################################
	#### Ember Media Manager Auto Scraping ####
	###########################################
	### Command lines
	### -------------
	### -fullask
	### -fullauto
	### -missask
	### -missauto
	### -newask
	### -newauto
	### -markask
	### -markauto
	### -file
	### -folder
	### -export
	### -template
	### -resize
	### -all
	### -nfo
	### -posters
	### -fanart
	### -extra
	### -nowindow
	### -run
	###########################################

    # Lauch Ember Media Manager and store PID for future kill
    startTime = datetime.datetime.now()
    returnCode, stdOut, stdErr, sp = runCmd('"D:\EmberMM\Ember Media Manager.exe" -newauto -all -nowindow') 
    Logger.info('- Ember Media Manager: running on PID: (' + str(sp.pid) + ')' + ' started at: ' + str(startTime))
    endTime = datetime.datetime.now()
    # Kill Lauch Media Manager's PID
    subprocess.call("taskkill /F /T /PID %i"%sp.pid)	
    Logger.info('- Ember Media Manager ran for ' + str((endTime - startTime)))	
    Logger.info('- Killed Ember Media Manager on PID: (' + str(sp.pid) + ')' )	

def runCmd(cmd):
    proc = subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False)
    out, err = proc.communicate()
    ret = proc.returncode
    proc.wait()
    return (ret, out, err, proc)
my nzbToCouchpotato.py looks like this:

Code: Select all

#!/usr/bin/env python
#
##############################################################################
### NZBGET POST-PROCESSING SCRIPT                                          ###

# Post-Process to CouchPotato.
#
# This script sends the download to your automated media management servers.
#
# NOTE: This script requires Python to be installed on your system.

##############################################################################
### OPTIONS                                                                ###

## CouchPotato

# CouchPotato script category.
#
# category that gets called for post-processing with CouchPotatoServer.
#cpsCategory=movie

# CouchPotato api key.
#cpsapikey=

# CouchPotato host.
#cpshost=localhost

# CouchPotato port.
#cpsport=5050

# CouchPotato username.
#cpsusername= 

# CouchPotato password.
#cpspassword=

# CouchPotato uses ssl (0, 1).
#
# Set to 1 if using ssl, else set to 0.
#cpsssl=0

# CouchPotato URL_Base
#
# set this if using a reverse proxy.
#cpsweb_root=

# CouchPotato Postprocess Delay.
#
# must be at least 60 seconds.
#cpsdelay=65

# CouchPotato Postprocess Method (renamer, manage).
#
# use "renamer" for CPS renamer (default) or "manage" to call a manage update.
#cpsmethod=renamer

# CouchPotato Delete Failed Downloads (0, 1).
#
# set to 1 to delete failed, or 0 to leave files in place.
#cpsdelete_failed=0

## Extensions

# Media Extensions
#
# This is a list of media extensions that may be transcoded if transcoder is enabled below.
#mediaExtensions=.mkv,.avi,.divx,.xvid,.mov,.wmv,.mp4,.mpg,.mpeg,.vob,.iso

## Transcoder

# Transcode (0, 1).
#
# set to 1 to transcode, otherwise set to 0.
#transcode=0

# create a duplicate, or replace the original (0, 1).
#
# set to 1 to cretae a new file or 0 to replace the original
#duplicate=1

# ignore extensions
#
# list of extensions that won't be transcoded. 
#ignoreExtensions=.avi,.mkv

# ffmpeg output settings.
#outputVideoExtension=.mp4
#outputVideoCodec=libx264
#outputVideoPreset=medium
#outputVideoFramerate=24
#outputVideoBitrate=800k
#outputAudioCodec=libmp3lame
#outputAudioBitrate=128k
#outputSubtitleCodec=

## WakeOnLan

# use WOL (0, 1).
#
# set to 1 to send WOL broadcast to the mac and test the server (e.g. xbmc) on the host and port specified.
#wolwake=0

# WOL MAC
#
# enter the mac address of the system to be woken.
#wolmac=00:01:2e:2D:64:e1

# Set the Host and Port of a server to verify system has woken.
#wolhost=192.168.1.37
#wolport=80

### NZBGET POST-PROCESSING SCRIPT                                          ###
##############################################################################

import os
import sys
import logging

import autoProcess.migratecfg as migratecfg
import autoProcess.autoProcessMovie as autoProcessMovie
from autoProcess.nzbToMediaEnv import *
from autoProcess.nzbToMediaUtil import *

#check to migrate old cfg before trying to load.
if os.path.isfile(os.path.join(os.path.dirname(sys.argv[0]), "autoProcessMedia.cfg.sample")):
    migratecfg.migrate()

nzbtomedia_configure_logging(os.path.dirname(sys.argv[0]))
Logger = logging.getLogger(__name__)

Logger.info("====================") # Seperate old from new log
Logger.info("nzbToCouchPotato %s", VERSION)

WakeUp()

# SABnzbd
if len(sys.argv) == SABNZB_NO_OF_ARGUMENTS:
    # SABnzbd argv:
    # 1 The final directory of the job (full path)
    # 2 The original name of the NZB file
    # 3 Clean version of the job name (no path info and ".nzb" removed)
    # 4 Indexer's report number (if supported)
    # 5 User-defined category
    # 6 Group that the NZB was posted in e.g. alt.binaries.x
    # 7 Status of post processing. 0 = OK, 1=failed verification, 2=failed unpack, 3=1+2
    Logger.info("Script triggered from SABnzbd, starting autoProcessMovie...")
    clientAgent = "sabnzbd"
    Logger.info('Command-line: ' + str(command))	
    Logger.info('SABnzbd command-line arguments ( ' + str(len(sys.argv)) + ' ): ' + str(sys.argv))	
    result = autoProcessMovie.process(sys.argv[1], sys.argv[2], sys.argv[7], clientAgent)
else:
    Logger.warn("Invalid number of arguments received from client.")
    Logger.info("Running autoProcessMovie as a manual run...")
    clientAgent = "manual"
    result = autoProcessMovie.process('Manual Run', 'Manual Run', 0, clientAgent)

if result == 0:
    # Logger.info("Checking SABnzbd status...")
    # autoProcessMovie.check_sabnzbd()
	# Run Ember Media Manager to scrapre additional data
    Logger.info("Launching Ember Media Manager to scrape additional data...")
    autoProcessMovie.run_ember()
	# Update XBMC Video Library
    Logger.info("Update XBMC Video Library...")
    autoProcessMovie.update_library()
	# SUCCESS: autoProcessMovie script ran successfully!
    Logger.info("The autoProcessMovie script completed successfully.")
else:
    Logger.info("A problem was reported in the autoProcessMovie script.")
When I run this script from Git bash, everything works as expected, but when it gets invoked by nzbToCouchpotato.py it just hangs on Ember Media Manager.exe. This process starts, cpu increases for about 3 seconds and then gets to 0% and the script gets halted. I have to kill this process so that parent subprocess ends.

Can anyone help me with this?

Thanks
HTPC: LC-Power 1320mi :: Sapphire PURE WHITE Fusion E350 :: 4GB DDR3 :: SSD Corsair Nova 2 [SO] :: 3TB [Storage]
powered by Win7 :: XBMC Frodo :: SABnzbd :: CouchPotato :: SickBeard :: Headphones
User avatar
redglory
Newbie
Newbie
Posts: 9
Joined: August 31st, 2012, 8:53 am

Re: autoProcessMovie.py calling Ember Media Manager problem

Post by redglory »

Tried to open notepad.exe instead of Ember and same result... Process gets started and no notepad...

autoProcessMovie.py waits for notepad to close (returncode) so that it finishes its job.

I went to see how SABnzbd builds script command/arguments:

1st thing inside https://github.com/sabnzbd/sabnzbd/blob ... sunpack.py

Code: Select all

if sabnzbd.WIN32:
    try:
        import win32api
        from win32con import SW_HIDE
        from win32process import STARTF_USESHOWWINDOW, IDLE_PRIORITY_CLASS
    except ImportError:
        pass
else:
    # Define dummy WindowsError for non-Windows
    class WindowsError(Exception):
        def __init__(self, value):
            self.parameter = value
        def __str__(self):
            return repr(self.parameter)
As stated, external scripts get called from:

Code: Select all

def external_processing(extern_proc, complete_dir, filename, msgid, nicename, cat, group, status):
    """ Run a user postproc script, return console output and exit value
    """
    command = [str(extern_proc), str(complete_dir), str(filename),
               str(nicename), str(msgid), str(cat), str(group), str(status)]

    if extern_proc.endswith('.py') and (sabnzbd.WIN32 or not os.access(extern_proc, os.X_OK)):
        command.insert(0, 'python')
    stup, need_shell, command, creationflags = [b][u]build_command(command)[/u][/b]
    env = fix_env()

    logging.info('Running external script %s(%s, %s, %s, %s, %s, %s, %s)',
                 extern_proc, complete_dir, filename, nicename, msgid, cat, group, status)

    try:
        p = subprocess.Popen(command, shell=need_shell, stdin=subprocess.PIPE,
                            stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
                            startupinfo=stup, env=env, creationflags=creationflags)
    except:
        logging.debug("Failed script %s, Traceback: ", extern_proc, exc_info = True)
        return "Cannot run script %s\r\n" % extern_proc, -1

    output = p.stdout.read()
    ret = p.wait()
    return output, ret

#------------------------------------------------------------------------------
And these parameters get populated inside "build_command" function:

Code: Select all

def build_command(command):
    """ Prepare list from running an external program
    """
    if not sabnzbd.WIN32:
        if IONICE_COMMAND and cfg.ionice().strip():
            lst = cfg.ionice().split()
            lst.reverse()
            for arg in lst:
                command.insert(0, arg)
            command.insert(0, IONICE_COMMAND)
        if NICE_COMMAND and cfg.nice().strip():
            lst = cfg.nice().split()
            lst.reverse()
            for arg in lst:
                command.insert(0, arg)
            command.insert(0, NICE_COMMAND)
        need_shell = False
        stup = None
        creationflags = 0

    else:
        [b]need_shell = os.path.splitext(command[0])[1].lower() not in ('.exe', '.com')
        stup = subprocess.STARTUPINFO()
        stup.dwFlags = STARTF_USESHOWWINDOW
        stup.wShowWindow = SW_HIDE
        creationflags = IDLE_PRIORITY_CLASS[/b]

        # Work-around for bug in Python's Popen function,
        # scripts with spaces in the path don't work.
        if need_shell and ' ' in command[0]:
            command[0] = win32api.GetShortPathName(command[0])
        if need_shell:
            command = list2cmdline(command)

    return stup, need_shell, command, creationflags
If I understand correctly, in my case I get:
stup = subprocess.STARTUPINFO() - Populate handle with default structure parameters.
Info for STARTUPINFO structure

Code: Select all

Specifies the window station, desktop, standard handles, and appearance of the main window for a process at creation time.
stup.dwFlags = STARTF_USESHOWWINDOW

Code: Select all

STARTF_USESHOWWINDOW
0x00000001
The wShowWindow member contains additional information.
stup.wShowWindow = SW_HIDE

Code: Select all

wShowWindow
If dwFlags specifies STARTF_USESHOWWINDOW, this member can be any of the values that can be specified in the nCmdShow parameter for the ShowWindow function, except for SW_SHOWDEFAULT. Otherwise, this member is ignored.
For GUI processes, the first time ShowWindow is called, its nCmdShow parameter is ignored wShowWindow specifies the default value. In subsequent calls to ShowWindow, the wShowWindow member is used if the nCmdShow parameter of ShowWindow is set to SW_SHOWDEFAULT.
So I suppose this parameter prevents cmd window opening after running command?!

need_shell = True ('cause my script doesn't end in '.exe' or '.com'.) - default shell 'cmd' i suppose :)

creationflags = IDLE_PRIORITY_CLASS

Code: Select all

Processes that monitor the system, such as screen savers or applications that periodically update a display, should use IDLE_PRIORITY_CLASS. This prevents the threads of this process, which do not have high priority, from interfering with higher priority threads.
command = 'python nzbToCouchPotato.py [complete_dir] [filename] [nicename] [msgid] 'movies' [group] [status]'

Code: Select all

command = [str(extern_proc), str(complete_dir), str(filename),
               str(nicename), str(msgid), str(cat), str(group), str(status)]
Is the problem related to stup.wShowWindow = SW_HIDE ? I suppose the shell window influences how windows apps get opened?

Get crazy with this. Might have to change to NZBGet :D

Thanks for your help!
HTPC: LC-Power 1320mi :: Sapphire PURE WHITE Fusion E350 :: 4GB DDR3 :: SSD Corsair Nova 2 [SO] :: 3TB [Storage]
powered by Win7 :: XBMC Frodo :: SABnzbd :: CouchPotato :: SickBeard :: Headphones
User avatar
redglory
Newbie
Newbie
Posts: 9
Joined: August 31st, 2012, 8:53 am

Re: autoProcessMovie.py calling Ember Media Manager problem

Post by redglory »

I think i might have found the problem.

Refering to this property (UserInteractive) it indicates that:

Code: Select all

Property Value
Type: System.Boolean
true if the current process is running in user-interactive mode; otherwise, false.
Remarks
When the UserInteractive property is false, do not display any modal dialogs or message boxes, as there is no graphical user interface for the user to interact with.
[b]This property is false only when called from a [u]service process[/u] or from a Web application.[/b]
So, as Ember opens with a splash screen, if we can omit this it might work. Going to investigate this. :)
HTPC: LC-Power 1320mi :: Sapphire PURE WHITE Fusion E350 :: 4GB DDR3 :: SSD Corsair Nova 2 [SO] :: 3TB [Storage]
powered by Win7 :: XBMC Frodo :: SABnzbd :: CouchPotato :: SickBeard :: Headphones
User avatar
redglory
Newbie
Newbie
Posts: 9
Joined: August 31st, 2012, 8:53 am

Re: autoProcessMovie.py calling Ember Media Manager problem

Post by redglory »

EUREKA!

I've finally found how to launch Ember Media Manager from SABnzbd script.

Had to install Visual Studio on a VM, cloned DanCooper's Ember-MM-New repo and patched "Ember Media Manager.exe".

Here is the file to overwrite the original one: Patched "Ember Media Manager.exe"

Hope it helps!

EDIT: Need to test regular Ember functions. It's giving some errors!
HTPC: LC-Power 1320mi :: Sapphire PURE WHITE Fusion E350 :: 4GB DDR3 :: SSD Corsair Nova 2 [SO] :: 3TB [Storage]
powered by Win7 :: XBMC Frodo :: SABnzbd :: CouchPotato :: SickBeard :: Headphones
User avatar
redglory
Newbie
Newbie
Posts: 9
Joined: August 31st, 2012, 8:53 am

Re: autoProcessMovie.py calling Ember Media Manager problem

Post by redglory »

Tried with whole compiled version with my Media.emm, settings.xml and AdvancedSettigns.xml and all worked fine.

If anyone wants to try it, do at your own risk.

I've packed it: get it here!

Hope it helps!
HTPC: LC-Power 1320mi :: Sapphire PURE WHITE Fusion E350 :: 4GB DDR3 :: SSD Corsair Nova 2 [SO] :: 3TB [Storage]
powered by Win7 :: XBMC Frodo :: SABnzbd :: CouchPotato :: SickBeard :: Headphones
Post Reply