1 # Pyvconv - A simple frontend for ffmpeg/mencoder
2 # Copyright (C) 2008, Kristian Rumberg (kristianrumberg@gmail.com)
4 # Permission to use, copy, modify, and/or distribute this software for any
5 # purpose with or without fee is hereby granted, provided that the above
6 # copyright notice and this permission notice appear in all copies.
8 # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 class Error(Exception):
21 def __init__(self
, value
):
22 Exception.__init
__(self
)
25 return repr(self
.value
)
28 def __init__(self
, namestr
, defaultstr
, exprstr
= None):
29 self
.namestr
= namestr
30 self
.defaultstr
= defaultstr
31 self
.exprstr
= exprstr
37 return self
.defaultstr
!= None
40 if self
.defaultstr
== None:
41 raise Error("Error: Trying to eval variable " + self
.namestr
+ " with no value")
42 return self
.defaultstr
44 class OptionalSetting
:
45 def __init__(self
, namestr
, exprstr
):
46 self
.namestr
= namestr
47 self
.exprstr
= exprstr
52 def get_value(self
, var_list
):
55 if var_list
[var
].has_value():
56 p
= re
.compile( "\$\{" + var
+ "\}")
57 instr
= p
.sub( var_list
[var
].get_value(), instr
)
58 if instr
.find("$") != -1:
59 instr
= "" # if not all variables were found, return empty option
63 def __init__(self
, namestr
, callstr
, extstr
, var_list
, optset_list
):
64 self
.namestr
= namestr
65 self
.callstr
= callstr
67 self
.var_list
= var_list
68 self
.optset_list
= optset_list
73 def get_outfile_extension(self
):
76 def put_var(self
, var
):
77 self
.var_list
[str(var
)] = var
85 p
= re
.compile("\$\[(\w+)\]")
86 for o
in p
.findall(instr
):
87 if o
not in self
.optset_list
:
88 raise Error("Error: Optional variable not defined")
89 instr
= p
.sub(self
.optset_list
[o
].get_value(self
.var_list
), instr
)
91 p
= re
.compile("\$\{(\w+)\}")
92 for o
in p
.findall(instr
):
93 if o
not in self
.var_list
:
94 raise Error("Error: Variable \"" + o
+ "\" has not been assigned")
95 val
= self
.var_list
[o
].get_value()
96 instr
= instr
.replace("${" + o
+ "}", val
)
98 if instr
.find("$") != -1:
99 raise Error("Error: all variables were not expanded")
104 self
.cmdcall_dict
= {}
107 def _read_properties(self
, propnode
, mand_propnames
, opt_propnames
= []):
111 if p
.name
in mand_propnames
:
112 propdict
[p
.name
] = str(p
.content
)
113 elif p
.name
!= "text" and p
.name
not in opt_propnames
:
114 raise Error("Error parsing XML: only name and call are accepted properties in the element command, found " + str(p
.name
))
116 if len(mand_propnames
) != len(propdict
.keys()):
117 raise Error("Error parsing XML: must supply both name and call in element command")
120 if p
.name
in opt_propnames
:
121 propdict
[p
.name
] = str(p
.content
)
122 elif p
.name
!= "text" and p
.name
not in mand_propnames
:
123 raise Error("Error parsing XML: only name and call are accepted properties in the element command, found " + str(p
.name
))
127 def _get_config_path(self
):
128 homeconf
= os
.path
.expanduser("~") + "/.pyvconv/commands.xml"
129 if os
.path
.isfile("commands.xml"):
130 return "commands.xml"
131 elif os
.path
.isfile(homeconf
):
134 raise Error("Error: No config found")
136 def _cmd_program_found_in_path(self
, programstr
):
137 if not os
.environ
.has_key('PATH') or os
.environ
['PATH']=='':
140 p
= os
.environ
['PATH']
142 pathlist
= p
.split (os
.pathsep
)
143 for path
in pathlist
:
144 f
= os
.path
.join(path
, programstr
)
145 if os
.access(f
, os
.X_OK
):
149 def _read_config(self
):
150 doc
= libxml2
.parseFile(self
._get
_config
_path
())
151 cmd_xmllist
= doc
.xpathEval( '//command')
153 # read all commands from XML description
154 for cmdnode
in cmd_xmllist
:
155 if cmdnode
.type == "element" and cmdnode
.name
== "command":
161 for varsetnode
in cmdnode
.children
:
162 if varsetnode
.type == "element" and varsetnode
.name
== "variable":
163 props
= self
._read
_properties
(varsetnode
.properties
, ["name", "expr"], ["default"])
165 if "default" in props
:
166 defprop
= props
["default"]
167 var_list
[props
["name"]] = Variable(props
["name"], defprop
, props
["expr"])
169 elif varsetnode
.type == "element" and varsetnode
.name
== "optionalsetting":
170 props
= self
._read
_properties
(varsetnode
.properties
, ["name", "expr"])
171 optset_list
[props
["name"]] = OptionalSetting(props
["name"], props
["expr"])
173 elif varsetnode
.name
!= "text":
174 raise Error("Error parsing XML: only variable and optionalsetting elements allowed in command")
176 props
= self
._read
_properties
(cmdnode
.properties
, ["name", "call", "ext"])
178 if self
._cmd
_program
_found
_in
_path
( props
["call"].split()[0] ):
179 self
.cmdcall_dict
[props
["name"]] = Command(props
["name"], props
["call"], props
["ext"], var_list
, optset_list
)
182 raise Error("Error parsing XML: only command elements are supported")
185 return self
.cmdcall_dict
.values().__iter
__()
188 return len(self
.cmdcall_dict
)
190 def __getitem__(self
, name
):
191 return self
.cmdcall_dict
[name
]