mirror of https://github.com/python/cpython
Detabbed.
This commit is contained in:
parent
058a84f36a
commit
0ae3220736
|
@ -3,119 +3,119 @@ error='Audio_mac.error'
|
|||
|
||||
class Play_Audio_mac:
|
||||
|
||||
def __init__(self, qsize=QSIZE):
|
||||
self._chan = None
|
||||
self._qsize = qsize
|
||||
self._outrate = 22254
|
||||
self._sampwidth = 1
|
||||
self._nchannels = 1
|
||||
self._gc = []
|
||||
self._usercallback = None
|
||||
def __init__(self, qsize=QSIZE):
|
||||
self._chan = None
|
||||
self._qsize = qsize
|
||||
self._outrate = 22254
|
||||
self._sampwidth = 1
|
||||
self._nchannels = 1
|
||||
self._gc = []
|
||||
self._usercallback = None
|
||||
|
||||
def __del__(self):
|
||||
self.stop()
|
||||
self._usercallback = None
|
||||
def __del__(self):
|
||||
self.stop()
|
||||
self._usercallback = None
|
||||
|
||||
def wait(self):
|
||||
import time
|
||||
while self.getfilled():
|
||||
time.sleep(0.1)
|
||||
self._chan = None
|
||||
self._gc = []
|
||||
def wait(self):
|
||||
import time
|
||||
while self.getfilled():
|
||||
time.sleep(0.1)
|
||||
self._chan = None
|
||||
self._gc = []
|
||||
|
||||
def stop(self, quietNow = 1):
|
||||
##chan = self._chan
|
||||
self._chan = None
|
||||
##chan.SndDisposeChannel(1)
|
||||
self._gc = []
|
||||
def stop(self, quietNow = 1):
|
||||
##chan = self._chan
|
||||
self._chan = None
|
||||
##chan.SndDisposeChannel(1)
|
||||
self._gc = []
|
||||
|
||||
def setoutrate(self, outrate):
|
||||
self._outrate = outrate
|
||||
def setoutrate(self, outrate):
|
||||
self._outrate = outrate
|
||||
|
||||
def setsampwidth(self, sampwidth):
|
||||
self._sampwidth = sampwidth
|
||||
def setsampwidth(self, sampwidth):
|
||||
self._sampwidth = sampwidth
|
||||
|
||||
def setnchannels(self, nchannels):
|
||||
self._nchannels = nchannels
|
||||
def setnchannels(self, nchannels):
|
||||
self._nchannels = nchannels
|
||||
|
||||
def writeframes(self, data):
|
||||
import time
|
||||
from Carbon.Sound import bufferCmd, callBackCmd, extSH
|
||||
import struct
|
||||
import MacOS
|
||||
if not self._chan:
|
||||
from Carbon import Snd
|
||||
self._chan = Snd.SndNewChannel(5, 0, self._callback)
|
||||
nframes = len(data) / self._nchannels / self._sampwidth
|
||||
if len(data) != nframes * self._nchannels * self._sampwidth:
|
||||
raise error, 'data is not a whole number of frames'
|
||||
while self._gc and \
|
||||
self.getfilled() + nframes > \
|
||||
self._qsize / self._nchannels / self._sampwidth:
|
||||
time.sleep(0.1)
|
||||
if self._sampwidth == 1:
|
||||
import audioop
|
||||
data = audioop.add(data, '\x80'*len(data), 1)
|
||||
h1 = struct.pack('llHhllbbl',
|
||||
id(data)+MacOS.string_id_to_buffer,
|
||||
self._nchannels,
|
||||
self._outrate, 0,
|
||||
0,
|
||||
0,
|
||||
extSH,
|
||||
60,
|
||||
nframes)
|
||||
h2 = 22*'\0'
|
||||
h3 = struct.pack('hhlll',
|
||||
self._sampwidth*8,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0)
|
||||
header = h1+h2+h3
|
||||
self._gc.append((header, data))
|
||||
self._chan.SndDoCommand((bufferCmd, 0, header), 0)
|
||||
self._chan.SndDoCommand((callBackCmd, 0, 0), 0)
|
||||
def writeframes(self, data):
|
||||
import time
|
||||
from Carbon.Sound import bufferCmd, callBackCmd, extSH
|
||||
import struct
|
||||
import MacOS
|
||||
if not self._chan:
|
||||
from Carbon import Snd
|
||||
self._chan = Snd.SndNewChannel(5, 0, self._callback)
|
||||
nframes = len(data) / self._nchannels / self._sampwidth
|
||||
if len(data) != nframes * self._nchannels * self._sampwidth:
|
||||
raise error, 'data is not a whole number of frames'
|
||||
while self._gc and \
|
||||
self.getfilled() + nframes > \
|
||||
self._qsize / self._nchannels / self._sampwidth:
|
||||
time.sleep(0.1)
|
||||
if self._sampwidth == 1:
|
||||
import audioop
|
||||
data = audioop.add(data, '\x80'*len(data), 1)
|
||||
h1 = struct.pack('llHhllbbl',
|
||||
id(data)+MacOS.string_id_to_buffer,
|
||||
self._nchannels,
|
||||
self._outrate, 0,
|
||||
0,
|
||||
0,
|
||||
extSH,
|
||||
60,
|
||||
nframes)
|
||||
h2 = 22*'\0'
|
||||
h3 = struct.pack('hhlll',
|
||||
self._sampwidth*8,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0)
|
||||
header = h1+h2+h3
|
||||
self._gc.append((header, data))
|
||||
self._chan.SndDoCommand((bufferCmd, 0, header), 0)
|
||||
self._chan.SndDoCommand((callBackCmd, 0, 0), 0)
|
||||
|
||||
def _callback(self, *args):
|
||||
del self._gc[0]
|
||||
if self._usercallback:
|
||||
self._usercallback()
|
||||
|
||||
def setcallback(self, callback):
|
||||
self._usercallback = callback
|
||||
def _callback(self, *args):
|
||||
del self._gc[0]
|
||||
if self._usercallback:
|
||||
self._usercallback()
|
||||
|
||||
def setcallback(self, callback):
|
||||
self._usercallback = callback
|
||||
|
||||
def getfilled(self):
|
||||
filled = 0
|
||||
for header, data in self._gc:
|
||||
filled = filled + len(data)
|
||||
return filled / self._nchannels / self._sampwidth
|
||||
def getfilled(self):
|
||||
filled = 0
|
||||
for header, data in self._gc:
|
||||
filled = filled + len(data)
|
||||
return filled / self._nchannels / self._sampwidth
|
||||
|
||||
def getfillable(self):
|
||||
return (self._qsize / self._nchannels / self._sampwidth) - self.getfilled()
|
||||
def getfillable(self):
|
||||
return (self._qsize / self._nchannels / self._sampwidth) - self.getfilled()
|
||||
|
||||
def ulaw2lin(self, data):
|
||||
import audioop
|
||||
return audioop.ulaw2lin(data, 2)
|
||||
def ulaw2lin(self, data):
|
||||
import audioop
|
||||
return audioop.ulaw2lin(data, 2)
|
||||
|
||||
def test():
|
||||
import aifc
|
||||
import EasyDialogs
|
||||
fn = EasyDialogs.AskFileForOpen(message="Select an AIFF soundfile", typeList=("AIFF",))
|
||||
if not fn: return
|
||||
af = aifc.open(fn, 'r')
|
||||
print af.getparams()
|
||||
p = Play_Audio_mac()
|
||||
p.setoutrate(af.getframerate())
|
||||
p.setsampwidth(af.getsampwidth())
|
||||
p.setnchannels(af.getnchannels())
|
||||
BUFSIZ = 10000
|
||||
while 1:
|
||||
data = af.readframes(BUFSIZ)
|
||||
if not data: break
|
||||
p.writeframes(data)
|
||||
print 'wrote', len(data), 'space', p.getfillable()
|
||||
p.wait()
|
||||
import aifc
|
||||
import EasyDialogs
|
||||
fn = EasyDialogs.AskFileForOpen(message="Select an AIFF soundfile", typeList=("AIFF",))
|
||||
if not fn: return
|
||||
af = aifc.open(fn, 'r')
|
||||
print af.getparams()
|
||||
p = Play_Audio_mac()
|
||||
p.setoutrate(af.getframerate())
|
||||
p.setsampwidth(af.getsampwidth())
|
||||
p.setnchannels(af.getnchannels())
|
||||
BUFSIZ = 10000
|
||||
while 1:
|
||||
data = af.readframes(BUFSIZ)
|
||||
if not data: break
|
||||
p.writeframes(data)
|
||||
print 'wrote', len(data), 'space', p.getfillable()
|
||||
p.wait()
|
||||
|
||||
if __name__ == '__main__':
|
||||
test()
|
||||
test()
|
||||
|
|
|
@ -5,53 +5,53 @@ import struct
|
|||
|
||||
# These needn't go through this module, but are here for completeness
|
||||
def SetControlData_Handle(control, part, selector, data):
|
||||
control.SetControlData_Handle(part, selector, data)
|
||||
|
||||
control.SetControlData_Handle(part, selector, data)
|
||||
|
||||
def GetControlData_Handle(control, part, selector):
|
||||
return control.GetControlData_Handle(part, selector)
|
||||
|
||||
return control.GetControlData_Handle(part, selector)
|
||||
|
||||
_accessdict = {
|
||||
kControlPopupButtonMenuHandleTag: (SetControlData_Handle, GetControlData_Handle),
|
||||
kControlPopupButtonMenuHandleTag: (SetControlData_Handle, GetControlData_Handle),
|
||||
}
|
||||
|
||||
_codingdict = {
|
||||
kControlPushButtonDefaultTag : ("b", None, None),
|
||||
|
||||
kControlEditTextTextTag: (None, None, None),
|
||||
kControlEditTextPasswordTag: (None, None, None),
|
||||
|
||||
kControlPopupButtonMenuIDTag: ("h", None, None),
|
||||
|
||||
kControlListBoxDoubleClickTag: ("b", None, None),
|
||||
kControlPushButtonDefaultTag : ("b", None, None),
|
||||
|
||||
kControlEditTextTextTag: (None, None, None),
|
||||
kControlEditTextPasswordTag: (None, None, None),
|
||||
|
||||
kControlPopupButtonMenuIDTag: ("h", None, None),
|
||||
|
||||
kControlListBoxDoubleClickTag: ("b", None, None),
|
||||
}
|
||||
|
||||
def SetControlData(control, part, selector, data):
|
||||
if _accessdict.has_key(selector):
|
||||
setfunc, getfunc = _accessdict[selector]
|
||||
setfunc(control, part, selector, data)
|
||||
return
|
||||
if not _codingdict.has_key(selector):
|
||||
raise KeyError, ('Unknown control selector', selector)
|
||||
structfmt, coder, decoder = _codingdict[selector]
|
||||
if coder:
|
||||
data = coder(data)
|
||||
if structfmt:
|
||||
data = struct.pack(structfmt, data)
|
||||
control.SetControlData(part, selector, data)
|
||||
|
||||
if _accessdict.has_key(selector):
|
||||
setfunc, getfunc = _accessdict[selector]
|
||||
setfunc(control, part, selector, data)
|
||||
return
|
||||
if not _codingdict.has_key(selector):
|
||||
raise KeyError, ('Unknown control selector', selector)
|
||||
structfmt, coder, decoder = _codingdict[selector]
|
||||
if coder:
|
||||
data = coder(data)
|
||||
if structfmt:
|
||||
data = struct.pack(structfmt, data)
|
||||
control.SetControlData(part, selector, data)
|
||||
|
||||
def GetControlData(control, part, selector):
|
||||
if _accessdict.has_key(selector):
|
||||
setfunc, getfunc = _accessdict[selector]
|
||||
return getfunc(control, part, selector, data)
|
||||
if not _codingdict.has_key(selector):
|
||||
raise KeyError, ('Unknown control selector', selector)
|
||||
structfmt, coder, decoder = _codingdict[selector]
|
||||
data = control.GetControlData(part, selector)
|
||||
if structfmt:
|
||||
data = struct.unpack(structfmt, data)
|
||||
if decoder:
|
||||
data = decoder(data)
|
||||
if type(data) == type(()) and len(data) == 1:
|
||||
data = data[0]
|
||||
return data
|
||||
|
||||
if _accessdict.has_key(selector):
|
||||
setfunc, getfunc = _accessdict[selector]
|
||||
return getfunc(control, part, selector, data)
|
||||
if not _codingdict.has_key(selector):
|
||||
raise KeyError, ('Unknown control selector', selector)
|
||||
structfmt, coder, decoder = _codingdict[selector]
|
||||
data = control.GetControlData(part, selector)
|
||||
if structfmt:
|
||||
data = struct.unpack(structfmt, data)
|
||||
if decoder:
|
||||
data = decoder(data)
|
||||
if type(data) == type(()) and len(data) == 1:
|
||||
data = data[0]
|
||||
return data
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
try:
|
||||
from OverrideFrom23._Res import *
|
||||
from OverrideFrom23._Res import *
|
||||
except ImportError:
|
||||
from _Res import *
|
||||
from _Res import *
|
||||
|
|
|
@ -14,202 +14,202 @@ import imgformat
|
|||
|
||||
# PixMap data structure element format (as used with struct)
|
||||
_pmElemFormat = {
|
||||
'baseAddr':'l', # address of pixel data
|
||||
'rowBytes':'H', # bytes per row, plus 0x8000
|
||||
'bounds':'hhhh', # coordinates imposed over pixel data
|
||||
'top':'h',
|
||||
'left':'h',
|
||||
'bottom':'h',
|
||||
'right':'h',
|
||||
'pmVersion':'h', # flags for Color QuickDraw
|
||||
'packType':'h', # format of compression algorithm
|
||||
'packSize':'l', # size after compression
|
||||
'hRes':'l', # horizontal pixels per inch
|
||||
'vRes':'l', # vertical pixels per inch
|
||||
'pixelType':'h', # pixel format
|
||||
'pixelSize':'h', # bits per pixel
|
||||
'cmpCount':'h', # color components per pixel
|
||||
'cmpSize':'h', # bits per component
|
||||
'planeBytes':'l', # offset in bytes to next plane
|
||||
'pmTable':'l', # handle to color table
|
||||
'pmReserved':'l' # reserved for future use
|
||||
'baseAddr':'l', # address of pixel data
|
||||
'rowBytes':'H', # bytes per row, plus 0x8000
|
||||
'bounds':'hhhh', # coordinates imposed over pixel data
|
||||
'top':'h',
|
||||
'left':'h',
|
||||
'bottom':'h',
|
||||
'right':'h',
|
||||
'pmVersion':'h', # flags for Color QuickDraw
|
||||
'packType':'h', # format of compression algorithm
|
||||
'packSize':'l', # size after compression
|
||||
'hRes':'l', # horizontal pixels per inch
|
||||
'vRes':'l', # vertical pixels per inch
|
||||
'pixelType':'h', # pixel format
|
||||
'pixelSize':'h', # bits per pixel
|
||||
'cmpCount':'h', # color components per pixel
|
||||
'cmpSize':'h', # bits per component
|
||||
'planeBytes':'l', # offset in bytes to next plane
|
||||
'pmTable':'l', # handle to color table
|
||||
'pmReserved':'l' # reserved for future use
|
||||
}
|
||||
|
||||
# PixMap data structure element offset
|
||||
_pmElemOffset = {
|
||||
'baseAddr':0,
|
||||
'rowBytes':4,
|
||||
'bounds':6,
|
||||
'top':6,
|
||||
'left':8,
|
||||
'bottom':10,
|
||||
'right':12,
|
||||
'pmVersion':14,
|
||||
'packType':16,
|
||||
'packSize':18,
|
||||
'hRes':22,
|
||||
'vRes':26,
|
||||
'pixelType':30,
|
||||
'pixelSize':32,
|
||||
'cmpCount':34,
|
||||
'cmpSize':36,
|
||||
'planeBytes':38,
|
||||
'pmTable':42,
|
||||
'pmReserved':46
|
||||
'baseAddr':0,
|
||||
'rowBytes':4,
|
||||
'bounds':6,
|
||||
'top':6,
|
||||
'left':8,
|
||||
'bottom':10,
|
||||
'right':12,
|
||||
'pmVersion':14,
|
||||
'packType':16,
|
||||
'packSize':18,
|
||||
'hRes':22,
|
||||
'vRes':26,
|
||||
'pixelType':30,
|
||||
'pixelSize':32,
|
||||
'cmpCount':34,
|
||||
'cmpSize':36,
|
||||
'planeBytes':38,
|
||||
'pmTable':42,
|
||||
'pmReserved':46
|
||||
}
|
||||
|
||||
class PixMapWrapper:
|
||||
"""PixMapWrapper -- wraps the QD PixMap object in a Python class,
|
||||
with methods to easily get/set various pixmap fields. Note: Use the
|
||||
PixMap() method when passing to QD calls."""
|
||||
"""PixMapWrapper -- wraps the QD PixMap object in a Python class,
|
||||
with methods to easily get/set various pixmap fields. Note: Use the
|
||||
PixMap() method when passing to QD calls."""
|
||||
|
||||
def __init__(self):
|
||||
self.__dict__['data'] = ''
|
||||
self._header = struct.pack("lhhhhhhhlllhhhhlll",
|
||||
id(self.data)+MacOS.string_id_to_buffer,
|
||||
0, # rowBytes
|
||||
0, 0, 0, 0, # bounds
|
||||
0, # pmVersion
|
||||
0, 0, # packType, packSize
|
||||
72<<16, 72<<16, # hRes, vRes
|
||||
QuickDraw.RGBDirect, # pixelType
|
||||
16, # pixelSize
|
||||
2, 5, # cmpCount, cmpSize,
|
||||
0, 0, 0) # planeBytes, pmTable, pmReserved
|
||||
self.__dict__['_pm'] = Qd.RawBitMap(self._header)
|
||||
|
||||
def _stuff(self, element, bytes):
|
||||
offset = _pmElemOffset[element]
|
||||
fmt = _pmElemFormat[element]
|
||||
self._header = self._header[:offset] \
|
||||
+ struct.pack(fmt, bytes) \
|
||||
+ self._header[offset + struct.calcsize(fmt):]
|
||||
self.__dict__['_pm'] = None
|
||||
|
||||
def _unstuff(self, element):
|
||||
offset = _pmElemOffset[element]
|
||||
fmt = _pmElemFormat[element]
|
||||
return struct.unpack(fmt, self._header[offset:offset+struct.calcsize(fmt)])[0]
|
||||
def __init__(self):
|
||||
self.__dict__['data'] = ''
|
||||
self._header = struct.pack("lhhhhhhhlllhhhhlll",
|
||||
id(self.data)+MacOS.string_id_to_buffer,
|
||||
0, # rowBytes
|
||||
0, 0, 0, 0, # bounds
|
||||
0, # pmVersion
|
||||
0, 0, # packType, packSize
|
||||
72<<16, 72<<16, # hRes, vRes
|
||||
QuickDraw.RGBDirect, # pixelType
|
||||
16, # pixelSize
|
||||
2, 5, # cmpCount, cmpSize,
|
||||
0, 0, 0) # planeBytes, pmTable, pmReserved
|
||||
self.__dict__['_pm'] = Qd.RawBitMap(self._header)
|
||||
|
||||
def _stuff(self, element, bytes):
|
||||
offset = _pmElemOffset[element]
|
||||
fmt = _pmElemFormat[element]
|
||||
self._header = self._header[:offset] \
|
||||
+ struct.pack(fmt, bytes) \
|
||||
+ self._header[offset + struct.calcsize(fmt):]
|
||||
self.__dict__['_pm'] = None
|
||||
|
||||
def _unstuff(self, element):
|
||||
offset = _pmElemOffset[element]
|
||||
fmt = _pmElemFormat[element]
|
||||
return struct.unpack(fmt, self._header[offset:offset+struct.calcsize(fmt)])[0]
|
||||
|
||||
def __setattr__(self, attr, val):
|
||||
if attr == 'baseAddr':
|
||||
raise 'UseErr', "don't assign to .baseAddr -- assign to .data instead"
|
||||
elif attr == 'data':
|
||||
self.__dict__['data'] = val
|
||||
self._stuff('baseAddr', id(self.data) + MacOS.string_id_to_buffer)
|
||||
elif attr == 'rowBytes':
|
||||
# high bit is always set for some odd reason
|
||||
self._stuff('rowBytes', val | 0x8000)
|
||||
elif attr == 'bounds':
|
||||
# assume val is in official Left, Top, Right, Bottom order!
|
||||
self._stuff('left',val[0])
|
||||
self._stuff('top',val[1])
|
||||
self._stuff('right',val[2])
|
||||
self._stuff('bottom',val[3])
|
||||
elif attr == 'hRes' or attr == 'vRes':
|
||||
# 16.16 fixed format, so just shift 16 bits
|
||||
self._stuff(attr, int(val) << 16)
|
||||
elif attr in _pmElemFormat.keys():
|
||||
# any other pm attribute -- just stuff
|
||||
self._stuff(attr, val)
|
||||
else:
|
||||
self.__dict__[attr] = val
|
||||
def __setattr__(self, attr, val):
|
||||
if attr == 'baseAddr':
|
||||
raise 'UseErr', "don't assign to .baseAddr -- assign to .data instead"
|
||||
elif attr == 'data':
|
||||
self.__dict__['data'] = val
|
||||
self._stuff('baseAddr', id(self.data) + MacOS.string_id_to_buffer)
|
||||
elif attr == 'rowBytes':
|
||||
# high bit is always set for some odd reason
|
||||
self._stuff('rowBytes', val | 0x8000)
|
||||
elif attr == 'bounds':
|
||||
# assume val is in official Left, Top, Right, Bottom order!
|
||||
self._stuff('left',val[0])
|
||||
self._stuff('top',val[1])
|
||||
self._stuff('right',val[2])
|
||||
self._stuff('bottom',val[3])
|
||||
elif attr == 'hRes' or attr == 'vRes':
|
||||
# 16.16 fixed format, so just shift 16 bits
|
||||
self._stuff(attr, int(val) << 16)
|
||||
elif attr in _pmElemFormat.keys():
|
||||
# any other pm attribute -- just stuff
|
||||
self._stuff(attr, val)
|
||||
else:
|
||||
self.__dict__[attr] = val
|
||||
|
||||
def __getattr__(self, attr):
|
||||
if attr == 'rowBytes':
|
||||
# high bit is always set for some odd reason
|
||||
return self._unstuff('rowBytes') & 0x7FFF
|
||||
elif attr == 'bounds':
|
||||
# return bounds in official Left, Top, Right, Bottom order!
|
||||
return ( \
|
||||
self._unstuff('left'),
|
||||
self._unstuff('top'),
|
||||
self._unstuff('right'),
|
||||
self._unstuff('bottom') )
|
||||
elif attr == 'hRes' or attr == 'vRes':
|
||||
# 16.16 fixed format, so just shift 16 bits
|
||||
return self._unstuff(attr) >> 16
|
||||
elif attr in _pmElemFormat.keys():
|
||||
# any other pm attribute -- just unstuff
|
||||
return self._unstuff(attr)
|
||||
else:
|
||||
return self.__dict__[attr]
|
||||
def __getattr__(self, attr):
|
||||
if attr == 'rowBytes':
|
||||
# high bit is always set for some odd reason
|
||||
return self._unstuff('rowBytes') & 0x7FFF
|
||||
elif attr == 'bounds':
|
||||
# return bounds in official Left, Top, Right, Bottom order!
|
||||
return ( \
|
||||
self._unstuff('left'),
|
||||
self._unstuff('top'),
|
||||
self._unstuff('right'),
|
||||
self._unstuff('bottom') )
|
||||
elif attr == 'hRes' or attr == 'vRes':
|
||||
# 16.16 fixed format, so just shift 16 bits
|
||||
return self._unstuff(attr) >> 16
|
||||
elif attr in _pmElemFormat.keys():
|
||||
# any other pm attribute -- just unstuff
|
||||
return self._unstuff(attr)
|
||||
else:
|
||||
return self.__dict__[attr]
|
||||
|
||||
|
||||
def PixMap(self):
|
||||
"Return a QuickDraw PixMap corresponding to this data."
|
||||
if not self.__dict__['_pm']:
|
||||
self.__dict__['_pm'] = Qd.RawBitMap(self._header)
|
||||
return self.__dict__['_pm']
|
||||
|
||||
def PixMap(self):
|
||||
"Return a QuickDraw PixMap corresponding to this data."
|
||||
if not self.__dict__['_pm']:
|
||||
self.__dict__['_pm'] = Qd.RawBitMap(self._header)
|
||||
return self.__dict__['_pm']
|
||||
|
||||
def blit(self, x1=0,y1=0,x2=None,y2=None, port=None):
|
||||
"""Draw this pixmap into the given (default current) grafport."""
|
||||
src = self.bounds
|
||||
dest = [x1,y1,x2,y2]
|
||||
if x2 == None:
|
||||
dest[2] = x1 + src[2]-src[0]
|
||||
if y2 == None:
|
||||
dest[3] = y1 + src[3]-src[1]
|
||||
if not port: port = Qd.GetPort()
|
||||
Qd.CopyBits(self.PixMap(), port.GetPortBitMapForCopyBits(), src, tuple(dest),
|
||||
QuickDraw.srcCopy, None)
|
||||
|
||||
def fromstring(self,s,width,height,format=imgformat.macrgb):
|
||||
"""Stuff this pixmap with raw pixel data from a string.
|
||||
Supply width, height, and one of the imgformat specifiers."""
|
||||
# we only support 16- and 32-bit mac rgb...
|
||||
# so convert if necessary
|
||||
if format != imgformat.macrgb and format != imgformat.macrgb16:
|
||||
# (LATER!)
|
||||
raise "NotImplementedError", "conversion to macrgb or macrgb16"
|
||||
self.data = s
|
||||
self.bounds = (0,0,width,height)
|
||||
self.cmpCount = 3
|
||||
self.pixelType = QuickDraw.RGBDirect
|
||||
if format == imgformat.macrgb:
|
||||
self.pixelSize = 32
|
||||
self.cmpSize = 8
|
||||
else:
|
||||
self.pixelSize = 16
|
||||
self.cmpSize = 5
|
||||
self.rowBytes = width*self.pixelSize/8
|
||||
def blit(self, x1=0,y1=0,x2=None,y2=None, port=None):
|
||||
"""Draw this pixmap into the given (default current) grafport."""
|
||||
src = self.bounds
|
||||
dest = [x1,y1,x2,y2]
|
||||
if x2 == None:
|
||||
dest[2] = x1 + src[2]-src[0]
|
||||
if y2 == None:
|
||||
dest[3] = y1 + src[3]-src[1]
|
||||
if not port: port = Qd.GetPort()
|
||||
Qd.CopyBits(self.PixMap(), port.GetPortBitMapForCopyBits(), src, tuple(dest),
|
||||
QuickDraw.srcCopy, None)
|
||||
|
||||
def fromstring(self,s,width,height,format=imgformat.macrgb):
|
||||
"""Stuff this pixmap with raw pixel data from a string.
|
||||
Supply width, height, and one of the imgformat specifiers."""
|
||||
# we only support 16- and 32-bit mac rgb...
|
||||
# so convert if necessary
|
||||
if format != imgformat.macrgb and format != imgformat.macrgb16:
|
||||
# (LATER!)
|
||||
raise "NotImplementedError", "conversion to macrgb or macrgb16"
|
||||
self.data = s
|
||||
self.bounds = (0,0,width,height)
|
||||
self.cmpCount = 3
|
||||
self.pixelType = QuickDraw.RGBDirect
|
||||
if format == imgformat.macrgb:
|
||||
self.pixelSize = 32
|
||||
self.cmpSize = 8
|
||||
else:
|
||||
self.pixelSize = 16
|
||||
self.cmpSize = 5
|
||||
self.rowBytes = width*self.pixelSize/8
|
||||
|
||||
def tostring(self, format=imgformat.macrgb):
|
||||
"""Return raw data as a string in the specified format."""
|
||||
# is the native format requested? if so, just return data
|
||||
if (format == imgformat.macrgb and self.pixelSize == 32) or \
|
||||
(format == imgformat.macrgb16 and self.pixelsize == 16):
|
||||
return self.data
|
||||
# otherwise, convert to the requested format
|
||||
# (LATER!)
|
||||
raise "NotImplementedError", "data format conversion"
|
||||
def tostring(self, format=imgformat.macrgb):
|
||||
"""Return raw data as a string in the specified format."""
|
||||
# is the native format requested? if so, just return data
|
||||
if (format == imgformat.macrgb and self.pixelSize == 32) or \
|
||||
(format == imgformat.macrgb16 and self.pixelsize == 16):
|
||||
return self.data
|
||||
# otherwise, convert to the requested format
|
||||
# (LATER!)
|
||||
raise "NotImplementedError", "data format conversion"
|
||||
|
||||
def fromImage(self,im):
|
||||
"""Initialize this PixMap from a PIL Image object."""
|
||||
# We need data in ARGB format; PIL can't currently do that,
|
||||
# but it can do RGBA, which we can use by inserting one null
|
||||
# up frontpm =
|
||||
if im.mode != 'RGBA': im = im.convert('RGBA')
|
||||
data = chr(0) + im.tostring()
|
||||
self.fromstring(data, im.size[0], im.size[1])
|
||||
def fromImage(self,im):
|
||||
"""Initialize this PixMap from a PIL Image object."""
|
||||
# We need data in ARGB format; PIL can't currently do that,
|
||||
# but it can do RGBA, which we can use by inserting one null
|
||||
# up frontpm =
|
||||
if im.mode != 'RGBA': im = im.convert('RGBA')
|
||||
data = chr(0) + im.tostring()
|
||||
self.fromstring(data, im.size[0], im.size[1])
|
||||
|
||||
def toImage(self):
|
||||
"""Return the contents of this PixMap as a PIL Image object."""
|
||||
import Image
|
||||
# our tostring() method returns data in ARGB format,
|
||||
# whereas Image uses RGBA; a bit of slicing fixes this...
|
||||
data = self.tostring()[1:] + chr(0)
|
||||
bounds = self.bounds
|
||||
return Image.fromstring('RGBA',(bounds[2]-bounds[0],bounds[3]-bounds[1]),data)
|
||||
def toImage(self):
|
||||
"""Return the contents of this PixMap as a PIL Image object."""
|
||||
import Image
|
||||
# our tostring() method returns data in ARGB format,
|
||||
# whereas Image uses RGBA; a bit of slicing fixes this...
|
||||
data = self.tostring()[1:] + chr(0)
|
||||
bounds = self.bounds
|
||||
return Image.fromstring('RGBA',(bounds[2]-bounds[0],bounds[3]-bounds[1]),data)
|
||||
|
||||
def test():
|
||||
import MacOS
|
||||
import EasyDialogs
|
||||
import Image
|
||||
path = EasyDialogs.AskFileForOpen("Image File:")
|
||||
if not path: return
|
||||
pm = PixMapWrapper()
|
||||
pm.fromImage( Image.open(path) )
|
||||
pm.blit(20,20)
|
||||
return pm
|
||||
import MacOS
|
||||
import EasyDialogs
|
||||
import Image
|
||||
path = EasyDialogs.AskFileForOpen("Image File:")
|
||||
if not path: return
|
||||
pm = PixMapWrapper()
|
||||
pm.fromImage( Image.open(path) )
|
||||
pm.blit(20,20)
|
||||
return pm
|
||||
|
||||
|
|
|
@ -44,15 +44,15 @@ import os
|
|||
# we like better (and which is equivalent)
|
||||
#
|
||||
unpacker_coercions = {
|
||||
typeComp : typeFloat,
|
||||
typeColorTable : typeAEList,
|
||||
typeDrawingArea : typeAERecord,
|
||||
typeFixed : typeFloat,
|
||||
typeExtended : typeFloat,
|
||||
typePixelMap : typeAERecord,
|
||||
typeRotation : typeAERecord,
|
||||
typeStyledText : typeAERecord,
|
||||
typeTextStyles : typeAERecord,
|
||||
typeComp : typeFloat,
|
||||
typeColorTable : typeAEList,
|
||||
typeDrawingArea : typeAERecord,
|
||||
typeFixed : typeFloat,
|
||||
typeExtended : typeFloat,
|
||||
typePixelMap : typeAERecord,
|
||||
typeRotation : typeAERecord,
|
||||
typeStyledText : typeAERecord,
|
||||
typeTextStyles : typeAERecord,
|
||||
};
|
||||
|
||||
#
|
||||
|
@ -64,303 +64,303 @@ FSRefType = Carbon.File.FSRefType
|
|||
AliasType = Carbon.File.AliasType
|
||||
|
||||
def packkey(ae, key, value):
|
||||
if hasattr(key, 'which'):
|
||||
keystr = key.which
|
||||
elif hasattr(key, 'want'):
|
||||
keystr = key.want
|
||||
else:
|
||||
keystr = key
|
||||
ae.AEPutParamDesc(keystr, pack(value))
|
||||
if hasattr(key, 'which'):
|
||||
keystr = key.which
|
||||
elif hasattr(key, 'want'):
|
||||
keystr = key.want
|
||||
else:
|
||||
keystr = key
|
||||
ae.AEPutParamDesc(keystr, pack(value))
|
||||
|
||||
def pack(x, forcetype = None):
|
||||
"""Pack a python object into an AE descriptor"""
|
||||
|
||||
if forcetype:
|
||||
if type(x) is StringType:
|
||||
return AE.AECreateDesc(forcetype, x)
|
||||
else:
|
||||
return pack(x).AECoerceDesc(forcetype)
|
||||
|
||||
if x == None:
|
||||
return AE.AECreateDesc('null', '')
|
||||
|
||||
if isinstance(x, AEDescType):
|
||||
return x
|
||||
if isinstance(x, FSSType):
|
||||
return AE.AECreateDesc('fss ', x.data)
|
||||
if isinstance(x, FSRefType):
|
||||
return AE.AECreateDesc('fsrf', x.data)
|
||||
if isinstance(x, AliasType):
|
||||
return AE.AECreateDesc('alis', x.data)
|
||||
if isinstance(x, IntType):
|
||||
return AE.AECreateDesc('long', struct.pack('l', x))
|
||||
if isinstance(x, FloatType):
|
||||
return AE.AECreateDesc('doub', struct.pack('d', x))
|
||||
if isinstance(x, StringType):
|
||||
return AE.AECreateDesc('TEXT', x)
|
||||
if isinstance(x, UnicodeType):
|
||||
data = x.encode('utf16')
|
||||
if data[:2] == '\xfe\xff':
|
||||
data = data[2:]
|
||||
return AE.AECreateDesc('utxt', data)
|
||||
if isinstance(x, ListType):
|
||||
list = AE.AECreateList('', 0)
|
||||
for item in x:
|
||||
list.AEPutDesc(0, pack(item))
|
||||
return list
|
||||
if isinstance(x, DictionaryType):
|
||||
record = AE.AECreateList('', 1)
|
||||
for key, value in x.items():
|
||||
packkey(record, key, value)
|
||||
#record.AEPutParamDesc(key, pack(value))
|
||||
return record
|
||||
if type(x) == types.ClassType and issubclass(x, ObjectSpecifier):
|
||||
# Note: we are getting a class object here, not an instance
|
||||
return AE.AECreateDesc('type', x.want)
|
||||
if hasattr(x, '__aepack__'):
|
||||
return x.__aepack__()
|
||||
if hasattr(x, 'which'):
|
||||
return AE.AECreateDesc('TEXT', x.which)
|
||||
if hasattr(x, 'want'):
|
||||
return AE.AECreateDesc('TEXT', x.want)
|
||||
return AE.AECreateDesc('TEXT', repr(x)) # Copout
|
||||
"""Pack a python object into an AE descriptor"""
|
||||
|
||||
if forcetype:
|
||||
if type(x) is StringType:
|
||||
return AE.AECreateDesc(forcetype, x)
|
||||
else:
|
||||
return pack(x).AECoerceDesc(forcetype)
|
||||
|
||||
if x == None:
|
||||
return AE.AECreateDesc('null', '')
|
||||
|
||||
if isinstance(x, AEDescType):
|
||||
return x
|
||||
if isinstance(x, FSSType):
|
||||
return AE.AECreateDesc('fss ', x.data)
|
||||
if isinstance(x, FSRefType):
|
||||
return AE.AECreateDesc('fsrf', x.data)
|
||||
if isinstance(x, AliasType):
|
||||
return AE.AECreateDesc('alis', x.data)
|
||||
if isinstance(x, IntType):
|
||||
return AE.AECreateDesc('long', struct.pack('l', x))
|
||||
if isinstance(x, FloatType):
|
||||
return AE.AECreateDesc('doub', struct.pack('d', x))
|
||||
if isinstance(x, StringType):
|
||||
return AE.AECreateDesc('TEXT', x)
|
||||
if isinstance(x, UnicodeType):
|
||||
data = x.encode('utf16')
|
||||
if data[:2] == '\xfe\xff':
|
||||
data = data[2:]
|
||||
return AE.AECreateDesc('utxt', data)
|
||||
if isinstance(x, ListType):
|
||||
list = AE.AECreateList('', 0)
|
||||
for item in x:
|
||||
list.AEPutDesc(0, pack(item))
|
||||
return list
|
||||
if isinstance(x, DictionaryType):
|
||||
record = AE.AECreateList('', 1)
|
||||
for key, value in x.items():
|
||||
packkey(record, key, value)
|
||||
#record.AEPutParamDesc(key, pack(value))
|
||||
return record
|
||||
if type(x) == types.ClassType and issubclass(x, ObjectSpecifier):
|
||||
# Note: we are getting a class object here, not an instance
|
||||
return AE.AECreateDesc('type', x.want)
|
||||
if hasattr(x, '__aepack__'):
|
||||
return x.__aepack__()
|
||||
if hasattr(x, 'which'):
|
||||
return AE.AECreateDesc('TEXT', x.which)
|
||||
if hasattr(x, 'want'):
|
||||
return AE.AECreateDesc('TEXT', x.want)
|
||||
return AE.AECreateDesc('TEXT', repr(x)) # Copout
|
||||
|
||||
def unpack(desc, formodulename=""):
|
||||
"""Unpack an AE descriptor to a python object"""
|
||||
t = desc.type
|
||||
|
||||
if unpacker_coercions.has_key(t):
|
||||
desc = desc.AECoerceDesc(unpacker_coercions[t])
|
||||
t = desc.type # This is a guess by Jack....
|
||||
|
||||
if t == typeAEList:
|
||||
l = []
|
||||
for i in range(desc.AECountItems()):
|
||||
keyword, item = desc.AEGetNthDesc(i+1, '****')
|
||||
l.append(unpack(item, formodulename))
|
||||
return l
|
||||
if t == typeAERecord:
|
||||
d = {}
|
||||
for i in range(desc.AECountItems()):
|
||||
keyword, item = desc.AEGetNthDesc(i+1, '****')
|
||||
d[keyword] = unpack(item, formodulename)
|
||||
return d
|
||||
if t == typeAEText:
|
||||
record = desc.AECoerceDesc('reco')
|
||||
return mkaetext(unpack(record, formodulename))
|
||||
if t == typeAlias:
|
||||
return Carbon.File.Alias(rawdata=desc.data)
|
||||
# typeAppleEvent returned as unknown
|
||||
if t == typeBoolean:
|
||||
return struct.unpack('b', desc.data)[0]
|
||||
if t == typeChar:
|
||||
return desc.data
|
||||
if t == typeUnicodeText:
|
||||
return unicode(desc.data, 'utf16')
|
||||
# typeColorTable coerced to typeAEList
|
||||
# typeComp coerced to extended
|
||||
# typeData returned as unknown
|
||||
# typeDrawingArea coerced to typeAERecord
|
||||
if t == typeEnumeration:
|
||||
return mkenum(desc.data)
|
||||
# typeEPS returned as unknown
|
||||
if t == typeFalse:
|
||||
return 0
|
||||
if t == typeFloat:
|
||||
data = desc.data
|
||||
return struct.unpack('d', data)[0]
|
||||
if t == typeFSS:
|
||||
return Carbon.File.FSSpec(rawdata=desc.data)
|
||||
if t == typeFSRef:
|
||||
return Carbon.File.FSRef(rawdata=desc.data)
|
||||
if t == typeInsertionLoc:
|
||||
record = desc.AECoerceDesc('reco')
|
||||
return mkinsertionloc(unpack(record, formodulename))
|
||||
# typeInteger equal to typeLongInteger
|
||||
if t == typeIntlText:
|
||||
script, language = struct.unpack('hh', desc.data[:4])
|
||||
return aetypes.IntlText(script, language, desc.data[4:])
|
||||
if t == typeIntlWritingCode:
|
||||
script, language = struct.unpack('hh', desc.data)
|
||||
return aetypes.IntlWritingCode(script, language)
|
||||
if t == typeKeyword:
|
||||
return mkkeyword(desc.data)
|
||||
if t == typeLongInteger:
|
||||
return struct.unpack('l', desc.data)[0]
|
||||
if t == typeLongDateTime:
|
||||
a, b = struct.unpack('lL', desc.data)
|
||||
return (long(a) << 32) + b
|
||||
if t == typeNull:
|
||||
return None
|
||||
if t == typeMagnitude:
|
||||
v = struct.unpack('l', desc.data)
|
||||
if v < 0:
|
||||
v = 0x100000000L + v
|
||||
return v
|
||||
if t == typeObjectSpecifier:
|
||||
record = desc.AECoerceDesc('reco')
|
||||
# If we have been told the name of the module we are unpacking aedescs for,
|
||||
# we can attempt to create the right type of python object from that module.
|
||||
if formodulename:
|
||||
return mkobjectfrommodule(unpack(record, formodulename), formodulename)
|
||||
return mkobject(unpack(record, formodulename))
|
||||
# typePict returned as unknown
|
||||
# typePixelMap coerced to typeAERecord
|
||||
# typePixelMapMinus returned as unknown
|
||||
# typeProcessSerialNumber returned as unknown
|
||||
if t == typeQDPoint:
|
||||
v, h = struct.unpack('hh', desc.data)
|
||||
return aetypes.QDPoint(v, h)
|
||||
if t == typeQDRectangle:
|
||||
v0, h0, v1, h1 = struct.unpack('hhhh', desc.data)
|
||||
return aetypes.QDRectangle(v0, h0, v1, h1)
|
||||
if t == typeRGBColor:
|
||||
r, g, b = struct.unpack('hhh', desc.data)
|
||||
return aetypes.RGBColor(r, g, b)
|
||||
# typeRotation coerced to typeAERecord
|
||||
# typeScrapStyles returned as unknown
|
||||
# typeSessionID returned as unknown
|
||||
if t == typeShortFloat:
|
||||
return struct.unpack('f', desc.data)[0]
|
||||
if t == typeShortInteger:
|
||||
return struct.unpack('h', desc.data)[0]
|
||||
# typeSMFloat identical to typeShortFloat
|
||||
# typeSMInt indetical to typeShortInt
|
||||
# typeStyledText coerced to typeAERecord
|
||||
if t == typeTargetID:
|
||||
return mktargetid(desc.data)
|
||||
# typeTextStyles coerced to typeAERecord
|
||||
# typeTIFF returned as unknown
|
||||
if t == typeTrue:
|
||||
return 1
|
||||
if t == typeType:
|
||||
return mktype(desc.data, formodulename)
|
||||
#
|
||||
# The following are special
|
||||
#
|
||||
if t == 'rang':
|
||||
record = desc.AECoerceDesc('reco')
|
||||
return mkrange(unpack(record, formodulename))
|
||||
if t == 'cmpd':
|
||||
record = desc.AECoerceDesc('reco')
|
||||
return mkcomparison(unpack(record, formodulename))
|
||||
if t == 'logi':
|
||||
record = desc.AECoerceDesc('reco')
|
||||
return mklogical(unpack(record, formodulename))
|
||||
return mkunknown(desc.type, desc.data)
|
||||
|
||||
"""Unpack an AE descriptor to a python object"""
|
||||
t = desc.type
|
||||
|
||||
if unpacker_coercions.has_key(t):
|
||||
desc = desc.AECoerceDesc(unpacker_coercions[t])
|
||||
t = desc.type # This is a guess by Jack....
|
||||
|
||||
if t == typeAEList:
|
||||
l = []
|
||||
for i in range(desc.AECountItems()):
|
||||
keyword, item = desc.AEGetNthDesc(i+1, '****')
|
||||
l.append(unpack(item, formodulename))
|
||||
return l
|
||||
if t == typeAERecord:
|
||||
d = {}
|
||||
for i in range(desc.AECountItems()):
|
||||
keyword, item = desc.AEGetNthDesc(i+1, '****')
|
||||
d[keyword] = unpack(item, formodulename)
|
||||
return d
|
||||
if t == typeAEText:
|
||||
record = desc.AECoerceDesc('reco')
|
||||
return mkaetext(unpack(record, formodulename))
|
||||
if t == typeAlias:
|
||||
return Carbon.File.Alias(rawdata=desc.data)
|
||||
# typeAppleEvent returned as unknown
|
||||
if t == typeBoolean:
|
||||
return struct.unpack('b', desc.data)[0]
|
||||
if t == typeChar:
|
||||
return desc.data
|
||||
if t == typeUnicodeText:
|
||||
return unicode(desc.data, 'utf16')
|
||||
# typeColorTable coerced to typeAEList
|
||||
# typeComp coerced to extended
|
||||
# typeData returned as unknown
|
||||
# typeDrawingArea coerced to typeAERecord
|
||||
if t == typeEnumeration:
|
||||
return mkenum(desc.data)
|
||||
# typeEPS returned as unknown
|
||||
if t == typeFalse:
|
||||
return 0
|
||||
if t == typeFloat:
|
||||
data = desc.data
|
||||
return struct.unpack('d', data)[0]
|
||||
if t == typeFSS:
|
||||
return Carbon.File.FSSpec(rawdata=desc.data)
|
||||
if t == typeFSRef:
|
||||
return Carbon.File.FSRef(rawdata=desc.data)
|
||||
if t == typeInsertionLoc:
|
||||
record = desc.AECoerceDesc('reco')
|
||||
return mkinsertionloc(unpack(record, formodulename))
|
||||
# typeInteger equal to typeLongInteger
|
||||
if t == typeIntlText:
|
||||
script, language = struct.unpack('hh', desc.data[:4])
|
||||
return aetypes.IntlText(script, language, desc.data[4:])
|
||||
if t == typeIntlWritingCode:
|
||||
script, language = struct.unpack('hh', desc.data)
|
||||
return aetypes.IntlWritingCode(script, language)
|
||||
if t == typeKeyword:
|
||||
return mkkeyword(desc.data)
|
||||
if t == typeLongInteger:
|
||||
return struct.unpack('l', desc.data)[0]
|
||||
if t == typeLongDateTime:
|
||||
a, b = struct.unpack('lL', desc.data)
|
||||
return (long(a) << 32) + b
|
||||
if t == typeNull:
|
||||
return None
|
||||
if t == typeMagnitude:
|
||||
v = struct.unpack('l', desc.data)
|
||||
if v < 0:
|
||||
v = 0x100000000L + v
|
||||
return v
|
||||
if t == typeObjectSpecifier:
|
||||
record = desc.AECoerceDesc('reco')
|
||||
# If we have been told the name of the module we are unpacking aedescs for,
|
||||
# we can attempt to create the right type of python object from that module.
|
||||
if formodulename:
|
||||
return mkobjectfrommodule(unpack(record, formodulename), formodulename)
|
||||
return mkobject(unpack(record, formodulename))
|
||||
# typePict returned as unknown
|
||||
# typePixelMap coerced to typeAERecord
|
||||
# typePixelMapMinus returned as unknown
|
||||
# typeProcessSerialNumber returned as unknown
|
||||
if t == typeQDPoint:
|
||||
v, h = struct.unpack('hh', desc.data)
|
||||
return aetypes.QDPoint(v, h)
|
||||
if t == typeQDRectangle:
|
||||
v0, h0, v1, h1 = struct.unpack('hhhh', desc.data)
|
||||
return aetypes.QDRectangle(v0, h0, v1, h1)
|
||||
if t == typeRGBColor:
|
||||
r, g, b = struct.unpack('hhh', desc.data)
|
||||
return aetypes.RGBColor(r, g, b)
|
||||
# typeRotation coerced to typeAERecord
|
||||
# typeScrapStyles returned as unknown
|
||||
# typeSessionID returned as unknown
|
||||
if t == typeShortFloat:
|
||||
return struct.unpack('f', desc.data)[0]
|
||||
if t == typeShortInteger:
|
||||
return struct.unpack('h', desc.data)[0]
|
||||
# typeSMFloat identical to typeShortFloat
|
||||
# typeSMInt indetical to typeShortInt
|
||||
# typeStyledText coerced to typeAERecord
|
||||
if t == typeTargetID:
|
||||
return mktargetid(desc.data)
|
||||
# typeTextStyles coerced to typeAERecord
|
||||
# typeTIFF returned as unknown
|
||||
if t == typeTrue:
|
||||
return 1
|
||||
if t == typeType:
|
||||
return mktype(desc.data, formodulename)
|
||||
#
|
||||
# The following are special
|
||||
#
|
||||
if t == 'rang':
|
||||
record = desc.AECoerceDesc('reco')
|
||||
return mkrange(unpack(record, formodulename))
|
||||
if t == 'cmpd':
|
||||
record = desc.AECoerceDesc('reco')
|
||||
return mkcomparison(unpack(record, formodulename))
|
||||
if t == 'logi':
|
||||
record = desc.AECoerceDesc('reco')
|
||||
return mklogical(unpack(record, formodulename))
|
||||
return mkunknown(desc.type, desc.data)
|
||||
|
||||
def coerce(data, egdata):
|
||||
"""Coerce a python object to another type using the AE coercers"""
|
||||
pdata = pack(data)
|
||||
pegdata = pack(egdata)
|
||||
pdata = pdata.AECoerceDesc(pegdata.type)
|
||||
return unpack(pdata)
|
||||
"""Coerce a python object to another type using the AE coercers"""
|
||||
pdata = pack(data)
|
||||
pegdata = pack(egdata)
|
||||
pdata = pdata.AECoerceDesc(pegdata.type)
|
||||
return unpack(pdata)
|
||||
|
||||
#
|
||||
# Helper routines for unpack
|
||||
#
|
||||
def mktargetid(data):
|
||||
sessionID = getlong(data[:4])
|
||||
name = mkppcportrec(data[4:4+72])
|
||||
location = mklocationnamerec(data[76:76+36])
|
||||
rcvrName = mkppcportrec(data[112:112+72])
|
||||
return sessionID, name, location, rcvrName
|
||||
sessionID = getlong(data[:4])
|
||||
name = mkppcportrec(data[4:4+72])
|
||||
location = mklocationnamerec(data[76:76+36])
|
||||
rcvrName = mkppcportrec(data[112:112+72])
|
||||
return sessionID, name, location, rcvrName
|
||||
|
||||
def mkppcportrec(rec):
|
||||
namescript = getword(rec[:2])
|
||||
name = getpstr(rec[2:2+33])
|
||||
portkind = getword(rec[36:38])
|
||||
if portkind == 1:
|
||||
ctor = rec[38:42]
|
||||
type = rec[42:46]
|
||||
identity = (ctor, type)
|
||||
else:
|
||||
identity = getpstr(rec[38:38+33])
|
||||
return namescript, name, portkind, identity
|
||||
namescript = getword(rec[:2])
|
||||
name = getpstr(rec[2:2+33])
|
||||
portkind = getword(rec[36:38])
|
||||
if portkind == 1:
|
||||
ctor = rec[38:42]
|
||||
type = rec[42:46]
|
||||
identity = (ctor, type)
|
||||
else:
|
||||
identity = getpstr(rec[38:38+33])
|
||||
return namescript, name, portkind, identity
|
||||
|
||||
def mklocationnamerec(rec):
|
||||
kind = getword(rec[:2])
|
||||
stuff = rec[2:]
|
||||
if kind == 0: stuff = None
|
||||
if kind == 2: stuff = getpstr(stuff)
|
||||
return kind, stuff
|
||||
kind = getword(rec[:2])
|
||||
stuff = rec[2:]
|
||||
if kind == 0: stuff = None
|
||||
if kind == 2: stuff = getpstr(stuff)
|
||||
return kind, stuff
|
||||
|
||||
def mkunknown(type, data):
|
||||
return aetypes.Unknown(type, data)
|
||||
return aetypes.Unknown(type, data)
|
||||
|
||||
def getpstr(s):
|
||||
return s[1:1+ord(s[0])]
|
||||
return s[1:1+ord(s[0])]
|
||||
|
||||
def getlong(s):
|
||||
return (ord(s[0])<<24) | (ord(s[1])<<16) | (ord(s[2])<<8) | ord(s[3])
|
||||
return (ord(s[0])<<24) | (ord(s[1])<<16) | (ord(s[2])<<8) | ord(s[3])
|
||||
|
||||
def getword(s):
|
||||
return (ord(s[0])<<8) | (ord(s[1])<<0)
|
||||
return (ord(s[0])<<8) | (ord(s[1])<<0)
|
||||
|
||||
def mkkeyword(keyword):
|
||||
return aetypes.Keyword(keyword)
|
||||
return aetypes.Keyword(keyword)
|
||||
|
||||
def mkrange(dict):
|
||||
return aetypes.Range(dict['star'], dict['stop'])
|
||||
return aetypes.Range(dict['star'], dict['stop'])
|
||||
|
||||
def mkcomparison(dict):
|
||||
return aetypes.Comparison(dict['obj1'], dict['relo'].enum, dict['obj2'])
|
||||
return aetypes.Comparison(dict['obj1'], dict['relo'].enum, dict['obj2'])
|
||||
|
||||
def mklogical(dict):
|
||||
return aetypes.Logical(dict['logc'], dict['term'])
|
||||
return aetypes.Logical(dict['logc'], dict['term'])
|
||||
|
||||
def mkstyledtext(dict):
|
||||
return aetypes.StyledText(dict['ksty'], dict['ktxt'])
|
||||
|
||||
return aetypes.StyledText(dict['ksty'], dict['ktxt'])
|
||||
|
||||
def mkaetext(dict):
|
||||
return aetypes.AEText(dict[keyAEScriptTag], dict[keyAEStyles], dict[keyAEText])
|
||||
|
||||
return aetypes.AEText(dict[keyAEScriptTag], dict[keyAEStyles], dict[keyAEText])
|
||||
|
||||
def mkinsertionloc(dict):
|
||||
return aetypes.InsertionLoc(dict[keyAEObject], dict[keyAEPosition])
|
||||
return aetypes.InsertionLoc(dict[keyAEObject], dict[keyAEPosition])
|
||||
|
||||
def mkobject(dict):
|
||||
want = dict['want'].type
|
||||
form = dict['form'].enum
|
||||
seld = dict['seld']
|
||||
fr = dict['from']
|
||||
if form in ('name', 'indx', 'rang', 'test'):
|
||||
if want == 'text': return aetypes.Text(seld, fr)
|
||||
if want == 'cha ': return aetypes.Character(seld, fr)
|
||||
if want == 'cwor': return aetypes.Word(seld, fr)
|
||||
if want == 'clin': return aetypes.Line(seld, fr)
|
||||
if want == 'cpar': return aetypes.Paragraph(seld, fr)
|
||||
if want == 'cwin': return aetypes.Window(seld, fr)
|
||||
if want == 'docu': return aetypes.Document(seld, fr)
|
||||
if want == 'file': return aetypes.File(seld, fr)
|
||||
if want == 'cins': return aetypes.InsertionPoint(seld, fr)
|
||||
if want == 'prop' and form == 'prop' and aetypes.IsType(seld):
|
||||
return aetypes.Property(seld.type, fr)
|
||||
return aetypes.ObjectSpecifier(want, form, seld, fr)
|
||||
want = dict['want'].type
|
||||
form = dict['form'].enum
|
||||
seld = dict['seld']
|
||||
fr = dict['from']
|
||||
if form in ('name', 'indx', 'rang', 'test'):
|
||||
if want == 'text': return aetypes.Text(seld, fr)
|
||||
if want == 'cha ': return aetypes.Character(seld, fr)
|
||||
if want == 'cwor': return aetypes.Word(seld, fr)
|
||||
if want == 'clin': return aetypes.Line(seld, fr)
|
||||
if want == 'cpar': return aetypes.Paragraph(seld, fr)
|
||||
if want == 'cwin': return aetypes.Window(seld, fr)
|
||||
if want == 'docu': return aetypes.Document(seld, fr)
|
||||
if want == 'file': return aetypes.File(seld, fr)
|
||||
if want == 'cins': return aetypes.InsertionPoint(seld, fr)
|
||||
if want == 'prop' and form == 'prop' and aetypes.IsType(seld):
|
||||
return aetypes.Property(seld.type, fr)
|
||||
return aetypes.ObjectSpecifier(want, form, seld, fr)
|
||||
|
||||
# Note by Jack: I'm not 100% sure of the following code. This was
|
||||
# provided by Donovan Preston, but I wonder whether the assignment
|
||||
# to __class__ is safe. Moreover, shouldn't there be a better
|
||||
# initializer for the classes in the suites?
|
||||
def mkobjectfrommodule(dict, modulename):
|
||||
if type(dict['want']) == types.ClassType and issubclass(dict['want'], ObjectSpecifier):
|
||||
# The type has already been converted to Python. Convert back:-(
|
||||
classtype = dict['want']
|
||||
dict['want'] = aetypes.mktype(classtype.want)
|
||||
want = dict['want'].type
|
||||
module = __import__(modulename)
|
||||
codenamemapper = module._classdeclarations
|
||||
classtype = codenamemapper.get(want, None)
|
||||
newobj = mkobject(dict)
|
||||
if classtype:
|
||||
assert issubclass(classtype, ObjectSpecifier)
|
||||
newobj.__class__ = classtype
|
||||
return newobj
|
||||
|
||||
if type(dict['want']) == types.ClassType and issubclass(dict['want'], ObjectSpecifier):
|
||||
# The type has already been converted to Python. Convert back:-(
|
||||
classtype = dict['want']
|
||||
dict['want'] = aetypes.mktype(classtype.want)
|
||||
want = dict['want'].type
|
||||
module = __import__(modulename)
|
||||
codenamemapper = module._classdeclarations
|
||||
classtype = codenamemapper.get(want, None)
|
||||
newobj = mkobject(dict)
|
||||
if classtype:
|
||||
assert issubclass(classtype, ObjectSpecifier)
|
||||
newobj.__class__ = classtype
|
||||
return newobj
|
||||
|
||||
def mktype(typecode, modulename=None):
|
||||
if modulename:
|
||||
module = __import__(modulename)
|
||||
codenamemapper = module._classdeclarations
|
||||
classtype = codenamemapper.get(typecode, None)
|
||||
if classtype:
|
||||
return classtype
|
||||
return aetypes.mktype(typecode)
|
||||
if modulename:
|
||||
module = __import__(modulename)
|
||||
codenamemapper = module._classdeclarations
|
||||
classtype = codenamemapper.get(typecode, None)
|
||||
if classtype:
|
||||
return classtype
|
||||
return aetypes.mktype(typecode)
|
||||
|
|
|
@ -9,11 +9,11 @@ unpackevent(event) returns the parameters and attributes from an AEAppleEvent re
|
|||
Plus... Lots of classes and routines that help representing AE objects,
|
||||
ranges, conditionals, logicals, etc., so you can write, e.g.:
|
||||
|
||||
x = Character(1, Document("foobar"))
|
||||
x = Character(1, Document("foobar"))
|
||||
|
||||
and pack(x) will create an AE object reference equivalent to AppleScript's
|
||||
|
||||
character 1 of document "foobar"
|
||||
character 1 of document "foobar"
|
||||
|
||||
Some of the stuff that appears to be exported from this module comes from other
|
||||
files: the pack stuff from aepack, the objects from aetypes.
|
||||
|
@ -41,306 +41,306 @@ LAUNCH_MAX_WAIT_TIME=10
|
|||
# Note by Jack: No??!? If I read the docs correctly it *is*....
|
||||
|
||||
aekeywords = [
|
||||
'tran',
|
||||
'rtid',
|
||||
'evcl',
|
||||
'evid',
|
||||
'addr',
|
||||
'optk',
|
||||
'timo',
|
||||
'inte', # this attribute is read only - will be set in AESend
|
||||
'esrc', # this attribute is read only
|
||||
'miss', # this attribute is read only
|
||||
'from' # new in 1.0.1
|
||||
'tran',
|
||||
'rtid',
|
||||
'evcl',
|
||||
'evid',
|
||||
'addr',
|
||||
'optk',
|
||||
'timo',
|
||||
'inte', # this attribute is read only - will be set in AESend
|
||||
'esrc', # this attribute is read only
|
||||
'miss', # this attribute is read only
|
||||
'from' # new in 1.0.1
|
||||
]
|
||||
|
||||
def missed(ae):
|
||||
try:
|
||||
desc = ae.AEGetAttributeDesc('miss', 'keyw')
|
||||
except AE.Error, msg:
|
||||
return None
|
||||
return desc.data
|
||||
try:
|
||||
desc = ae.AEGetAttributeDesc('miss', 'keyw')
|
||||
except AE.Error, msg:
|
||||
return None
|
||||
return desc.data
|
||||
|
||||
def unpackevent(ae, formodulename=""):
|
||||
parameters = {}
|
||||
try:
|
||||
dirobj = ae.AEGetParamDesc('----', '****')
|
||||
except AE.Error:
|
||||
pass
|
||||
else:
|
||||
parameters['----'] = unpack(dirobj, formodulename)
|
||||
del dirobj
|
||||
# Workaround for what I feel is a bug in OSX 10.2: 'errn' won't show up in missed...
|
||||
try:
|
||||
dirobj = ae.AEGetParamDesc('errn', '****')
|
||||
except AE.Error:
|
||||
pass
|
||||
else:
|
||||
parameters['errn'] = unpack(dirobj, formodulename)
|
||||
del dirobj
|
||||
while 1:
|
||||
key = missed(ae)
|
||||
if not key: break
|
||||
parameters[key] = unpack(ae.AEGetParamDesc(key, '****'), formodulename)
|
||||
attributes = {}
|
||||
for key in aekeywords:
|
||||
try:
|
||||
desc = ae.AEGetAttributeDesc(key, '****')
|
||||
except (AE.Error, MacOS.Error), msg:
|
||||
if msg[0] != -1701 and msg[0] != -1704:
|
||||
raise
|
||||
continue
|
||||
attributes[key] = unpack(desc, formodulename)
|
||||
return parameters, attributes
|
||||
parameters = {}
|
||||
try:
|
||||
dirobj = ae.AEGetParamDesc('----', '****')
|
||||
except AE.Error:
|
||||
pass
|
||||
else:
|
||||
parameters['----'] = unpack(dirobj, formodulename)
|
||||
del dirobj
|
||||
# Workaround for what I feel is a bug in OSX 10.2: 'errn' won't show up in missed...
|
||||
try:
|
||||
dirobj = ae.AEGetParamDesc('errn', '****')
|
||||
except AE.Error:
|
||||
pass
|
||||
else:
|
||||
parameters['errn'] = unpack(dirobj, formodulename)
|
||||
del dirobj
|
||||
while 1:
|
||||
key = missed(ae)
|
||||
if not key: break
|
||||
parameters[key] = unpack(ae.AEGetParamDesc(key, '****'), formodulename)
|
||||
attributes = {}
|
||||
for key in aekeywords:
|
||||
try:
|
||||
desc = ae.AEGetAttributeDesc(key, '****')
|
||||
except (AE.Error, MacOS.Error), msg:
|
||||
if msg[0] != -1701 and msg[0] != -1704:
|
||||
raise
|
||||
continue
|
||||
attributes[key] = unpack(desc, formodulename)
|
||||
return parameters, attributes
|
||||
|
||||
def packevent(ae, parameters = {}, attributes = {}):
|
||||
for key, value in parameters.items():
|
||||
packkey(ae, key, value)
|
||||
for key, value in attributes.items():
|
||||
ae.AEPutAttributeDesc(key, pack(value))
|
||||
for key, value in parameters.items():
|
||||
packkey(ae, key, value)
|
||||
for key, value in attributes.items():
|
||||
ae.AEPutAttributeDesc(key, pack(value))
|
||||
|
||||
#
|
||||
# Support routine for automatically generated Suite interfaces
|
||||
# These routines are also useable for the reverse function.
|
||||
#
|
||||
def keysubst(arguments, keydict):
|
||||
"""Replace long name keys by their 4-char counterparts, and check"""
|
||||
ok = keydict.values()
|
||||
for k in arguments.keys():
|
||||
if keydict.has_key(k):
|
||||
v = arguments[k]
|
||||
del arguments[k]
|
||||
arguments[keydict[k]] = v
|
||||
elif k != '----' and k not in ok:
|
||||
raise TypeError, 'Unknown keyword argument: %s'%k
|
||||
|
||||
"""Replace long name keys by their 4-char counterparts, and check"""
|
||||
ok = keydict.values()
|
||||
for k in arguments.keys():
|
||||
if keydict.has_key(k):
|
||||
v = arguments[k]
|
||||
del arguments[k]
|
||||
arguments[keydict[k]] = v
|
||||
elif k != '----' and k not in ok:
|
||||
raise TypeError, 'Unknown keyword argument: %s'%k
|
||||
|
||||
def enumsubst(arguments, key, edict):
|
||||
"""Substitute a single enum keyword argument, if it occurs"""
|
||||
if not arguments.has_key(key) or edict is None:
|
||||
return
|
||||
v = arguments[key]
|
||||
ok = edict.values()
|
||||
if edict.has_key(v):
|
||||
arguments[key] = Enum(edict[v])
|
||||
elif not v in ok:
|
||||
raise TypeError, 'Unknown enumerator: %s'%v
|
||||
|
||||
"""Substitute a single enum keyword argument, if it occurs"""
|
||||
if not arguments.has_key(key) or edict is None:
|
||||
return
|
||||
v = arguments[key]
|
||||
ok = edict.values()
|
||||
if edict.has_key(v):
|
||||
arguments[key] = Enum(edict[v])
|
||||
elif not v in ok:
|
||||
raise TypeError, 'Unknown enumerator: %s'%v
|
||||
|
||||
def decodeerror(arguments):
|
||||
"""Create the 'best' argument for a raise MacOS.Error"""
|
||||
errn = arguments['errn']
|
||||
err_a1 = errn
|
||||
if arguments.has_key('errs'):
|
||||
err_a2 = arguments['errs']
|
||||
else:
|
||||
err_a2 = MacOS.GetErrorString(errn)
|
||||
if arguments.has_key('erob'):
|
||||
err_a3 = arguments['erob']
|
||||
else:
|
||||
err_a3 = None
|
||||
|
||||
return (err_a1, err_a2, err_a3)
|
||||
"""Create the 'best' argument for a raise MacOS.Error"""
|
||||
errn = arguments['errn']
|
||||
err_a1 = errn
|
||||
if arguments.has_key('errs'):
|
||||
err_a2 = arguments['errs']
|
||||
else:
|
||||
err_a2 = MacOS.GetErrorString(errn)
|
||||
if arguments.has_key('erob'):
|
||||
err_a3 = arguments['erob']
|
||||
else:
|
||||
err_a3 = None
|
||||
|
||||
return (err_a1, err_a2, err_a3)
|
||||
|
||||
class TalkTo:
|
||||
"""An AE connection to an application"""
|
||||
_signature = None # Can be overridden by subclasses
|
||||
_moduleName = None # Can be overridden by subclasses
|
||||
|
||||
__eventloop_initialized = 0
|
||||
def __ensure_WMAvailable(klass):
|
||||
if klass.__eventloop_initialized: return 1
|
||||
if not MacOS.WMAvailable(): return 0
|
||||
# Workaround for a but in MacOSX 10.2: we must have an event
|
||||
# loop before we can call AESend.
|
||||
Evt.WaitNextEvent(0,0)
|
||||
return 1
|
||||
__ensure_WMAvailable = classmethod(__ensure_WMAvailable)
|
||||
"""An AE connection to an application"""
|
||||
_signature = None # Can be overridden by subclasses
|
||||
_moduleName = None # Can be overridden by subclasses
|
||||
|
||||
__eventloop_initialized = 0
|
||||
def __ensure_WMAvailable(klass):
|
||||
if klass.__eventloop_initialized: return 1
|
||||
if not MacOS.WMAvailable(): return 0
|
||||
# Workaround for a but in MacOSX 10.2: we must have an event
|
||||
# loop before we can call AESend.
|
||||
Evt.WaitNextEvent(0,0)
|
||||
return 1
|
||||
__ensure_WMAvailable = classmethod(__ensure_WMAvailable)
|
||||
|
||||
def __init__(self, signature=None, start=0, timeout=0):
|
||||
"""Create a communication channel with a particular application.
|
||||
|
||||
Addressing the application is done by specifying either a
|
||||
4-byte signature, an AEDesc or an object that will __aepack__
|
||||
to an AEDesc.
|
||||
"""
|
||||
self.target_signature = None
|
||||
if signature is None:
|
||||
signature = self._signature
|
||||
if type(signature) == AEDescType:
|
||||
self.target = signature
|
||||
elif type(signature) == InstanceType and hasattr(signature, '__aepack__'):
|
||||
self.target = signature.__aepack__()
|
||||
elif type(signature) == StringType and len(signature) == 4:
|
||||
self.target = AE.AECreateDesc(AppleEvents.typeApplSignature, signature)
|
||||
self.target_signature = signature
|
||||
else:
|
||||
raise TypeError, "signature should be 4-char string or AEDesc"
|
||||
self.send_flags = AppleEvents.kAEWaitReply
|
||||
self.send_priority = AppleEvents.kAENormalPriority
|
||||
if timeout:
|
||||
self.send_timeout = timeout
|
||||
else:
|
||||
self.send_timeout = AppleEvents.kAEDefaultTimeout
|
||||
if start:
|
||||
self._start()
|
||||
|
||||
def _start(self):
|
||||
"""Start the application, if it is not running yet"""
|
||||
try:
|
||||
self.send('ascr', 'noop')
|
||||
except AE.Error:
|
||||
_launch(self.target_signature)
|
||||
for i in range(LAUNCH_MAX_WAIT_TIME):
|
||||
try:
|
||||
self.send('ascr', 'noop')
|
||||
except AE.Error:
|
||||
pass
|
||||
else:
|
||||
break
|
||||
time.sleep(1)
|
||||
|
||||
def start(self):
|
||||
"""Deprecated, used _start()"""
|
||||
self._start()
|
||||
|
||||
def newevent(self, code, subcode, parameters = {}, attributes = {}):
|
||||
"""Create a complete structure for an apple event"""
|
||||
|
||||
event = AE.AECreateAppleEvent(code, subcode, self.target,
|
||||
AppleEvents.kAutoGenerateReturnID, AppleEvents.kAnyTransactionID)
|
||||
packevent(event, parameters, attributes)
|
||||
return event
|
||||
|
||||
def sendevent(self, event):
|
||||
"""Send a pre-created appleevent, await the reply and unpack it"""
|
||||
if not self.__ensure_WMAvailable():
|
||||
raise RuntimeError, "No window manager access, cannot send AppleEvent"
|
||||
reply = event.AESend(self.send_flags, self.send_priority,
|
||||
self.send_timeout)
|
||||
parameters, attributes = unpackevent(reply, self._moduleName)
|
||||
return reply, parameters, attributes
|
||||
|
||||
def send(self, code, subcode, parameters = {}, attributes = {}):
|
||||
"""Send an appleevent given code/subcode/pars/attrs and unpack the reply"""
|
||||
return self.sendevent(self.newevent(code, subcode, parameters, attributes))
|
||||
|
||||
#
|
||||
# The following events are somehow "standard" and don't seem to appear in any
|
||||
# suite...
|
||||
#
|
||||
def activate(self):
|
||||
"""Send 'activate' command"""
|
||||
self.send('misc', 'actv')
|
||||
def __init__(self, signature=None, start=0, timeout=0):
|
||||
"""Create a communication channel with a particular application.
|
||||
|
||||
Addressing the application is done by specifying either a
|
||||
4-byte signature, an AEDesc or an object that will __aepack__
|
||||
to an AEDesc.
|
||||
"""
|
||||
self.target_signature = None
|
||||
if signature is None:
|
||||
signature = self._signature
|
||||
if type(signature) == AEDescType:
|
||||
self.target = signature
|
||||
elif type(signature) == InstanceType and hasattr(signature, '__aepack__'):
|
||||
self.target = signature.__aepack__()
|
||||
elif type(signature) == StringType and len(signature) == 4:
|
||||
self.target = AE.AECreateDesc(AppleEvents.typeApplSignature, signature)
|
||||
self.target_signature = signature
|
||||
else:
|
||||
raise TypeError, "signature should be 4-char string or AEDesc"
|
||||
self.send_flags = AppleEvents.kAEWaitReply
|
||||
self.send_priority = AppleEvents.kAENormalPriority
|
||||
if timeout:
|
||||
self.send_timeout = timeout
|
||||
else:
|
||||
self.send_timeout = AppleEvents.kAEDefaultTimeout
|
||||
if start:
|
||||
self._start()
|
||||
|
||||
def _start(self):
|
||||
"""Start the application, if it is not running yet"""
|
||||
try:
|
||||
self.send('ascr', 'noop')
|
||||
except AE.Error:
|
||||
_launch(self.target_signature)
|
||||
for i in range(LAUNCH_MAX_WAIT_TIME):
|
||||
try:
|
||||
self.send('ascr', 'noop')
|
||||
except AE.Error:
|
||||
pass
|
||||
else:
|
||||
break
|
||||
time.sleep(1)
|
||||
|
||||
def start(self):
|
||||
"""Deprecated, used _start()"""
|
||||
self._start()
|
||||
|
||||
def newevent(self, code, subcode, parameters = {}, attributes = {}):
|
||||
"""Create a complete structure for an apple event"""
|
||||
|
||||
event = AE.AECreateAppleEvent(code, subcode, self.target,
|
||||
AppleEvents.kAutoGenerateReturnID, AppleEvents.kAnyTransactionID)
|
||||
packevent(event, parameters, attributes)
|
||||
return event
|
||||
|
||||
def sendevent(self, event):
|
||||
"""Send a pre-created appleevent, await the reply and unpack it"""
|
||||
if not self.__ensure_WMAvailable():
|
||||
raise RuntimeError, "No window manager access, cannot send AppleEvent"
|
||||
reply = event.AESend(self.send_flags, self.send_priority,
|
||||
self.send_timeout)
|
||||
parameters, attributes = unpackevent(reply, self._moduleName)
|
||||
return reply, parameters, attributes
|
||||
|
||||
def send(self, code, subcode, parameters = {}, attributes = {}):
|
||||
"""Send an appleevent given code/subcode/pars/attrs and unpack the reply"""
|
||||
return self.sendevent(self.newevent(code, subcode, parameters, attributes))
|
||||
|
||||
#
|
||||
# The following events are somehow "standard" and don't seem to appear in any
|
||||
# suite...
|
||||
#
|
||||
def activate(self):
|
||||
"""Send 'activate' command"""
|
||||
self.send('misc', 'actv')
|
||||
|
||||
def _get(self, _object, as=None, _attributes={}):
|
||||
"""_get: get data from an object
|
||||
Required argument: the object
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
Returns: the data
|
||||
"""
|
||||
_code = 'core'
|
||||
_subcode = 'getd'
|
||||
def _get(self, _object, as=None, _attributes={}):
|
||||
"""_get: get data from an object
|
||||
Required argument: the object
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
Returns: the data
|
||||
"""
|
||||
_code = 'core'
|
||||
_subcode = 'getd'
|
||||
|
||||
_arguments = {'----':_object}
|
||||
if as:
|
||||
_arguments['rtyp'] = mktype(as)
|
||||
_arguments = {'----':_object}
|
||||
if as:
|
||||
_arguments['rtyp'] = mktype(as)
|
||||
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.has_key('errn'):
|
||||
raise Error, decodeerror(_arguments)
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.has_key('errn'):
|
||||
raise Error, decodeerror(_arguments)
|
||||
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
if as:
|
||||
item.__class__ = as
|
||||
return item
|
||||
|
||||
get = _get
|
||||
|
||||
_argmap_set = {
|
||||
'to' : 'data',
|
||||
}
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
if as:
|
||||
item.__class__ = as
|
||||
return item
|
||||
|
||||
get = _get
|
||||
|
||||
_argmap_set = {
|
||||
'to' : 'data',
|
||||
}
|
||||
|
||||
def _set(self, _object, _attributes={}, **_arguments):
|
||||
"""set: Set an object's data.
|
||||
Required argument: the object for the command
|
||||
Keyword argument to: The new value.
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
"""
|
||||
_code = 'core'
|
||||
_subcode = 'setd'
|
||||
def _set(self, _object, _attributes={}, **_arguments):
|
||||
"""set: Set an object's data.
|
||||
Required argument: the object for the command
|
||||
Keyword argument to: The new value.
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
"""
|
||||
_code = 'core'
|
||||
_subcode = 'setd'
|
||||
|
||||
keysubst(_arguments, self._argmap_set)
|
||||
_arguments['----'] = _object
|
||||
keysubst(_arguments, self._argmap_set)
|
||||
_arguments['----'] = _object
|
||||
|
||||
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.get('errn', 0):
|
||||
raise Error, decodeerror(_arguments)
|
||||
# XXXX Optionally decode result
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
|
||||
set = _set
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.get('errn', 0):
|
||||
raise Error, decodeerror(_arguments)
|
||||
# XXXX Optionally decode result
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
|
||||
set = _set
|
||||
|
||||
# Tiny Finder class, for local use only
|
||||
|
||||
class _miniFinder(TalkTo):
|
||||
def open(self, _object, _attributes={}, **_arguments):
|
||||
"""open: Open the specified object(s)
|
||||
Required argument: list of objects to open
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
"""
|
||||
_code = 'aevt'
|
||||
_subcode = 'odoc'
|
||||
def open(self, _object, _attributes={}, **_arguments):
|
||||
"""open: Open the specified object(s)
|
||||
Required argument: list of objects to open
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
"""
|
||||
_code = 'aevt'
|
||||
_subcode = 'odoc'
|
||||
|
||||
if _arguments: raise TypeError, 'No optional args expected'
|
||||
_arguments['----'] = _object
|
||||
if _arguments: raise TypeError, 'No optional args expected'
|
||||
_arguments['----'] = _object
|
||||
|
||||
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.has_key('errn'):
|
||||
raise Error, decodeerror(_arguments)
|
||||
# XXXX Optionally decode result
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.has_key('errn'):
|
||||
raise Error, decodeerror(_arguments)
|
||||
# XXXX Optionally decode result
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
#pass
|
||||
|
||||
|
||||
_finder = _miniFinder('MACS')
|
||||
|
||||
def _launch(appfile):
|
||||
"""Open a file thru the finder. Specify file by name or fsspec"""
|
||||
_finder.open(_application_file(('ID ', appfile)))
|
||||
"""Open a file thru the finder. Specify file by name or fsspec"""
|
||||
_finder.open(_application_file(('ID ', appfile)))
|
||||
|
||||
|
||||
class _application_file(ComponentItem):
|
||||
"""application file - An application's file on disk"""
|
||||
want = 'appf'
|
||||
|
||||
"""application file - An application's file on disk"""
|
||||
want = 'appf'
|
||||
|
||||
_application_file._propdict = {
|
||||
}
|
||||
_application_file._elemdict = {
|
||||
}
|
||||
|
||||
|
||||
# Test program
|
||||
# XXXX Should test more, really...
|
||||
|
||||
def test():
|
||||
target = AE.AECreateDesc('sign', 'quil')
|
||||
ae = AE.AECreateAppleEvent('aevt', 'oapp', target, -1, 0)
|
||||
print unpackevent(ae)
|
||||
raw_input(":")
|
||||
ae = AE.AECreateAppleEvent('core', 'getd', target, -1, 0)
|
||||
obj = Character(2, Word(1, Document(1)))
|
||||
print obj
|
||||
print repr(obj)
|
||||
packevent(ae, {'----': obj})
|
||||
params, attrs = unpackevent(ae)
|
||||
print params['----']
|
||||
raw_input(":")
|
||||
target = AE.AECreateDesc('sign', 'quil')
|
||||
ae = AE.AECreateAppleEvent('aevt', 'oapp', target, -1, 0)
|
||||
print unpackevent(ae)
|
||||
raw_input(":")
|
||||
ae = AE.AECreateAppleEvent('core', 'getd', target, -1, 0)
|
||||
obj = Character(2, Word(1, Document(1)))
|
||||
print obj
|
||||
print repr(obj)
|
||||
packevent(ae, {'----': obj})
|
||||
params, attrs = unpackevent(ae)
|
||||
print params['----']
|
||||
raw_input(":")
|
||||
|
||||
if __name__ == '__main__':
|
||||
test()
|
||||
sys.exit(1)
|
||||
test()
|
||||
sys.exit(1)
|
||||
|
|
|
@ -10,549 +10,549 @@ import string
|
|||
# aetools_convert.
|
||||
#
|
||||
def pack(*args, **kwargs):
|
||||
from aepack import pack
|
||||
return pack( *args, **kwargs)
|
||||
|
||||
from aepack import pack
|
||||
return pack( *args, **kwargs)
|
||||
|
||||
def nice(s):
|
||||
"""'nice' representation of an object"""
|
||||
if type(s) is StringType: return repr(s)
|
||||
else: return str(s)
|
||||
"""'nice' representation of an object"""
|
||||
if type(s) is StringType: return repr(s)
|
||||
else: return str(s)
|
||||
|
||||
class Unknown:
|
||||
"""An uninterpreted AE object"""
|
||||
|
||||
def __init__(self, type, data):
|
||||
self.type = type
|
||||
self.data = data
|
||||
|
||||
def __repr__(self):
|
||||
return "Unknown(%s, %s)" % (`self.type`, `self.data`)
|
||||
|
||||
def __aepack__(self):
|
||||
return pack(self.data, self.type)
|
||||
"""An uninterpreted AE object"""
|
||||
|
||||
def __init__(self, type, data):
|
||||
self.type = type
|
||||
self.data = data
|
||||
|
||||
def __repr__(self):
|
||||
return "Unknown(%s, %s)" % (`self.type`, `self.data`)
|
||||
|
||||
def __aepack__(self):
|
||||
return pack(self.data, self.type)
|
||||
|
||||
class Enum:
|
||||
"""An AE enumeration value"""
|
||||
|
||||
def __init__(self, enum):
|
||||
self.enum = "%-4.4s" % str(enum)
|
||||
|
||||
def __repr__(self):
|
||||
return "Enum(%s)" % `self.enum`
|
||||
|
||||
def __str__(self):
|
||||
return string.strip(self.enum)
|
||||
|
||||
def __aepack__(self):
|
||||
return pack(self.enum, typeEnumeration)
|
||||
"""An AE enumeration value"""
|
||||
|
||||
def __init__(self, enum):
|
||||
self.enum = "%-4.4s" % str(enum)
|
||||
|
||||
def __repr__(self):
|
||||
return "Enum(%s)" % `self.enum`
|
||||
|
||||
def __str__(self):
|
||||
return string.strip(self.enum)
|
||||
|
||||
def __aepack__(self):
|
||||
return pack(self.enum, typeEnumeration)
|
||||
|
||||
def IsEnum(x):
|
||||
return isinstance(x, Enum)
|
||||
return isinstance(x, Enum)
|
||||
|
||||
def mkenum(enum):
|
||||
if IsEnum(enum): return enum
|
||||
return Enum(enum)
|
||||
if IsEnum(enum): return enum
|
||||
return Enum(enum)
|
||||
|
||||
# Jack changed the way this is done
|
||||
class InsertionLoc:
|
||||
def __init__(self, of, pos):
|
||||
self.of = of
|
||||
self.pos = pos
|
||||
|
||||
def __repr__(self):
|
||||
return "InsertionLoc(%s, %s)" % (`self.of`, `self.pos`)
|
||||
|
||||
def __aepack__(self):
|
||||
rec = {'kobj': self.of, 'kpos': self.pos}
|
||||
return pack(rec, forcetype='insl')
|
||||
|
||||
def __init__(self, of, pos):
|
||||
self.of = of
|
||||
self.pos = pos
|
||||
|
||||
def __repr__(self):
|
||||
return "InsertionLoc(%s, %s)" % (`self.of`, `self.pos`)
|
||||
|
||||
def __aepack__(self):
|
||||
rec = {'kobj': self.of, 'kpos': self.pos}
|
||||
return pack(rec, forcetype='insl')
|
||||
|
||||
# Convenience functions for dsp:
|
||||
def beginning(of):
|
||||
return InsertionLoc(of, Enum('bgng'))
|
||||
|
||||
return InsertionLoc(of, Enum('bgng'))
|
||||
|
||||
def end(of):
|
||||
return InsertionLoc(of, Enum('end '))
|
||||
return InsertionLoc(of, Enum('end '))
|
||||
|
||||
class Boolean:
|
||||
"""An AE boolean value"""
|
||||
|
||||
def __init__(self, bool):
|
||||
self.bool = (not not bool)
|
||||
|
||||
def __repr__(self):
|
||||
return "Boolean(%s)" % `self.bool`
|
||||
|
||||
def __str__(self):
|
||||
if self.bool:
|
||||
return "True"
|
||||
else:
|
||||
return "False"
|
||||
|
||||
def __aepack__(self):
|
||||
return pack(struct.pack('b', self.bool), 'bool')
|
||||
"""An AE boolean value"""
|
||||
|
||||
def __init__(self, bool):
|
||||
self.bool = (not not bool)
|
||||
|
||||
def __repr__(self):
|
||||
return "Boolean(%s)" % `self.bool`
|
||||
|
||||
def __str__(self):
|
||||
if self.bool:
|
||||
return "True"
|
||||
else:
|
||||
return "False"
|
||||
|
||||
def __aepack__(self):
|
||||
return pack(struct.pack('b', self.bool), 'bool')
|
||||
|
||||
def IsBoolean(x):
|
||||
return isinstance(x, Boolean)
|
||||
return isinstance(x, Boolean)
|
||||
|
||||
def mkboolean(bool):
|
||||
if IsBoolean(bool): return bool
|
||||
return Boolean(bool)
|
||||
if IsBoolean(bool): return bool
|
||||
return Boolean(bool)
|
||||
|
||||
class Type:
|
||||
"""An AE 4-char typename object"""
|
||||
|
||||
def __init__(self, type):
|
||||
self.type = "%-4.4s" % str(type)
|
||||
|
||||
def __repr__(self):
|
||||
return "Type(%s)" % `self.type`
|
||||
|
||||
def __str__(self):
|
||||
return string.strip(self.type)
|
||||
|
||||
def __aepack__(self):
|
||||
return pack(self.type, typeType)
|
||||
"""An AE 4-char typename object"""
|
||||
|
||||
def __init__(self, type):
|
||||
self.type = "%-4.4s" % str(type)
|
||||
|
||||
def __repr__(self):
|
||||
return "Type(%s)" % `self.type`
|
||||
|
||||
def __str__(self):
|
||||
return string.strip(self.type)
|
||||
|
||||
def __aepack__(self):
|
||||
return pack(self.type, typeType)
|
||||
|
||||
def IsType(x):
|
||||
return isinstance(x, Type)
|
||||
return isinstance(x, Type)
|
||||
|
||||
def mktype(type):
|
||||
if IsType(type): return type
|
||||
return Type(type)
|
||||
if IsType(type): return type
|
||||
return Type(type)
|
||||
|
||||
|
||||
class Keyword:
|
||||
"""An AE 4-char keyword object"""
|
||||
|
||||
def __init__(self, keyword):
|
||||
self.keyword = "%-4.4s" % str(keyword)
|
||||
|
||||
def __repr__(self):
|
||||
return "Keyword(%s)" % `self.keyword`
|
||||
|
||||
def __str__(self):
|
||||
return string.strip(self.keyword)
|
||||
|
||||
def __aepack__(self):
|
||||
return pack(self.keyword, typeKeyword)
|
||||
"""An AE 4-char keyword object"""
|
||||
|
||||
def __init__(self, keyword):
|
||||
self.keyword = "%-4.4s" % str(keyword)
|
||||
|
||||
def __repr__(self):
|
||||
return "Keyword(%s)" % `self.keyword`
|
||||
|
||||
def __str__(self):
|
||||
return string.strip(self.keyword)
|
||||
|
||||
def __aepack__(self):
|
||||
return pack(self.keyword, typeKeyword)
|
||||
|
||||
def IsKeyword(x):
|
||||
return isinstance(x, Keyword)
|
||||
return isinstance(x, Keyword)
|
||||
|
||||
class Range:
|
||||
"""An AE range object"""
|
||||
|
||||
def __init__(self, start, stop):
|
||||
self.start = start
|
||||
self.stop = stop
|
||||
|
||||
def __repr__(self):
|
||||
return "Range(%s, %s)" % (`self.start`, `self.stop`)
|
||||
|
||||
def __str__(self):
|
||||
return "%s thru %s" % (nice(self.start), nice(self.stop))
|
||||
|
||||
def __aepack__(self):
|
||||
return pack({'star': self.start, 'stop': self.stop}, 'rang')
|
||||
"""An AE range object"""
|
||||
|
||||
def __init__(self, start, stop):
|
||||
self.start = start
|
||||
self.stop = stop
|
||||
|
||||
def __repr__(self):
|
||||
return "Range(%s, %s)" % (`self.start`, `self.stop`)
|
||||
|
||||
def __str__(self):
|
||||
return "%s thru %s" % (nice(self.start), nice(self.stop))
|
||||
|
||||
def __aepack__(self):
|
||||
return pack({'star': self.start, 'stop': self.stop}, 'rang')
|
||||
|
||||
def IsRange(x):
|
||||
return isinstance(x, Range)
|
||||
return isinstance(x, Range)
|
||||
|
||||
class Comparison:
|
||||
"""An AE Comparison"""
|
||||
|
||||
def __init__(self, obj1, relo, obj2):
|
||||
self.obj1 = obj1
|
||||
self.relo = "%-4.4s" % str(relo)
|
||||
self.obj2 = obj2
|
||||
|
||||
def __repr__(self):
|
||||
return "Comparison(%s, %s, %s)" % (`self.obj1`, `self.relo`, `self.obj2`)
|
||||
|
||||
def __str__(self):
|
||||
return "%s %s %s" % (nice(self.obj1), string.strip(self.relo), nice(self.obj2))
|
||||
|
||||
def __aepack__(self):
|
||||
return pack({'obj1': self.obj1,
|
||||
'relo': mkenum(self.relo),
|
||||
'obj2': self.obj2},
|
||||
'cmpd')
|
||||
"""An AE Comparison"""
|
||||
|
||||
def __init__(self, obj1, relo, obj2):
|
||||
self.obj1 = obj1
|
||||
self.relo = "%-4.4s" % str(relo)
|
||||
self.obj2 = obj2
|
||||
|
||||
def __repr__(self):
|
||||
return "Comparison(%s, %s, %s)" % (`self.obj1`, `self.relo`, `self.obj2`)
|
||||
|
||||
def __str__(self):
|
||||
return "%s %s %s" % (nice(self.obj1), string.strip(self.relo), nice(self.obj2))
|
||||
|
||||
def __aepack__(self):
|
||||
return pack({'obj1': self.obj1,
|
||||
'relo': mkenum(self.relo),
|
||||
'obj2': self.obj2},
|
||||
'cmpd')
|
||||
|
||||
def IsComparison(x):
|
||||
return isinstance(x, Comparison)
|
||||
|
||||
return isinstance(x, Comparison)
|
||||
|
||||
class NComparison(Comparison):
|
||||
# The class attribute 'relo' must be set in a subclass
|
||||
|
||||
def __init__(self, obj1, obj2):
|
||||
Comparison.__init__(obj1, self.relo, obj2)
|
||||
# The class attribute 'relo' must be set in a subclass
|
||||
|
||||
def __init__(self, obj1, obj2):
|
||||
Comparison.__init__(obj1, self.relo, obj2)
|
||||
|
||||
class Ordinal:
|
||||
"""An AE Ordinal"""
|
||||
|
||||
def __init__(self, abso):
|
||||
# self.obj1 = obj1
|
||||
self.abso = "%-4.4s" % str(abso)
|
||||
|
||||
def __repr__(self):
|
||||
return "Ordinal(%s)" % (`self.abso`)
|
||||
|
||||
def __str__(self):
|
||||
return "%s" % (string.strip(self.abso))
|
||||
|
||||
def __aepack__(self):
|
||||
return pack(self.abso, 'abso')
|
||||
"""An AE Ordinal"""
|
||||
|
||||
def __init__(self, abso):
|
||||
# self.obj1 = obj1
|
||||
self.abso = "%-4.4s" % str(abso)
|
||||
|
||||
def __repr__(self):
|
||||
return "Ordinal(%s)" % (`self.abso`)
|
||||
|
||||
def __str__(self):
|
||||
return "%s" % (string.strip(self.abso))
|
||||
|
||||
def __aepack__(self):
|
||||
return pack(self.abso, 'abso')
|
||||
|
||||
def IsOrdinal(x):
|
||||
return isinstance(x, Ordinal)
|
||||
|
||||
return isinstance(x, Ordinal)
|
||||
|
||||
class NOrdinal(Ordinal):
|
||||
# The class attribute 'abso' must be set in a subclass
|
||||
|
||||
def __init__(self):
|
||||
Ordinal.__init__(self, self.abso)
|
||||
# The class attribute 'abso' must be set in a subclass
|
||||
|
||||
def __init__(self):
|
||||
Ordinal.__init__(self, self.abso)
|
||||
|
||||
class Logical:
|
||||
"""An AE logical expression object"""
|
||||
|
||||
def __init__(self, logc, term):
|
||||
self.logc = "%-4.4s" % str(logc)
|
||||
self.term = term
|
||||
|
||||
def __repr__(self):
|
||||
return "Logical(%s, %s)" % (`self.logc`, `self.term`)
|
||||
|
||||
def __str__(self):
|
||||
if type(self.term) == ListType and len(self.term) == 2:
|
||||
return "%s %s %s" % (nice(self.term[0]),
|
||||
string.strip(self.logc),
|
||||
nice(self.term[1]))
|
||||
else:
|
||||
return "%s(%s)" % (string.strip(self.logc), nice(self.term))
|
||||
|
||||
def __aepack__(self):
|
||||
return pack({'logc': mkenum(self.logc), 'term': self.term}, 'logi')
|
||||
"""An AE logical expression object"""
|
||||
|
||||
def __init__(self, logc, term):
|
||||
self.logc = "%-4.4s" % str(logc)
|
||||
self.term = term
|
||||
|
||||
def __repr__(self):
|
||||
return "Logical(%s, %s)" % (`self.logc`, `self.term`)
|
||||
|
||||
def __str__(self):
|
||||
if type(self.term) == ListType and len(self.term) == 2:
|
||||
return "%s %s %s" % (nice(self.term[0]),
|
||||
string.strip(self.logc),
|
||||
nice(self.term[1]))
|
||||
else:
|
||||
return "%s(%s)" % (string.strip(self.logc), nice(self.term))
|
||||
|
||||
def __aepack__(self):
|
||||
return pack({'logc': mkenum(self.logc), 'term': self.term}, 'logi')
|
||||
|
||||
def IsLogical(x):
|
||||
return isinstance(x, Logical)
|
||||
return isinstance(x, Logical)
|
||||
|
||||
class StyledText:
|
||||
"""An AE object respresenting text in a certain style"""
|
||||
|
||||
def __init__(self, style, text):
|
||||
self.style = style
|
||||
self.text = text
|
||||
|
||||
def __repr__(self):
|
||||
return "StyledText(%s, %s)" % (`self.style`, `self.text`)
|
||||
|
||||
def __str__(self):
|
||||
return self.text
|
||||
|
||||
def __aepack__(self):
|
||||
return pack({'ksty': self.style, 'ktxt': self.text}, 'STXT')
|
||||
"""An AE object respresenting text in a certain style"""
|
||||
|
||||
def __init__(self, style, text):
|
||||
self.style = style
|
||||
self.text = text
|
||||
|
||||
def __repr__(self):
|
||||
return "StyledText(%s, %s)" % (`self.style`, `self.text`)
|
||||
|
||||
def __str__(self):
|
||||
return self.text
|
||||
|
||||
def __aepack__(self):
|
||||
return pack({'ksty': self.style, 'ktxt': self.text}, 'STXT')
|
||||
|
||||
def IsStyledText(x):
|
||||
return isinstance(x, StyledText)
|
||||
return isinstance(x, StyledText)
|
||||
|
||||
class AEText:
|
||||
"""An AE text object with style, script and language specified"""
|
||||
|
||||
def __init__(self, script, style, text):
|
||||
self.script = script
|
||||
self.style = style
|
||||
self.text = text
|
||||
|
||||
def __repr__(self):
|
||||
return "AEText(%s, %s, %s)" % (`self.script`, `self.style`, `self.text`)
|
||||
|
||||
def __str__(self):
|
||||
return self.text
|
||||
|
||||
def __aepack__(self):
|
||||
return pack({keyAEScriptTag: self.script, keyAEStyles: self.style,
|
||||
keyAEText: self.text}, typeAEText)
|
||||
"""An AE text object with style, script and language specified"""
|
||||
|
||||
def __init__(self, script, style, text):
|
||||
self.script = script
|
||||
self.style = style
|
||||
self.text = text
|
||||
|
||||
def __repr__(self):
|
||||
return "AEText(%s, %s, %s)" % (`self.script`, `self.style`, `self.text`)
|
||||
|
||||
def __str__(self):
|
||||
return self.text
|
||||
|
||||
def __aepack__(self):
|
||||
return pack({keyAEScriptTag: self.script, keyAEStyles: self.style,
|
||||
keyAEText: self.text}, typeAEText)
|
||||
|
||||
def IsAEText(x):
|
||||
return isinstance(x, AEText)
|
||||
return isinstance(x, AEText)
|
||||
|
||||
class IntlText:
|
||||
"""A text object with script and language specified"""
|
||||
|
||||
def __init__(self, script, language, text):
|
||||
self.script = script
|
||||
self.language = language
|
||||
self.text = text
|
||||
|
||||
def __repr__(self):
|
||||
return "IntlText(%s, %s, %s)" % (`self.script`, `self.language`, `self.text`)
|
||||
|
||||
def __str__(self):
|
||||
return self.text
|
||||
|
||||
def __aepack__(self):
|
||||
return pack(struct.pack('hh', self.script, self.language)+self.text,
|
||||
typeIntlText)
|
||||
"""A text object with script and language specified"""
|
||||
|
||||
def __init__(self, script, language, text):
|
||||
self.script = script
|
||||
self.language = language
|
||||
self.text = text
|
||||
|
||||
def __repr__(self):
|
||||
return "IntlText(%s, %s, %s)" % (`self.script`, `self.language`, `self.text`)
|
||||
|
||||
def __str__(self):
|
||||
return self.text
|
||||
|
||||
def __aepack__(self):
|
||||
return pack(struct.pack('hh', self.script, self.language)+self.text,
|
||||
typeIntlText)
|
||||
|
||||
def IsIntlText(x):
|
||||
return isinstance(x, IntlText)
|
||||
return isinstance(x, IntlText)
|
||||
|
||||
class IntlWritingCode:
|
||||
"""An object representing script and language"""
|
||||
|
||||
def __init__(self, script, language):
|
||||
self.script = script
|
||||
self.language = language
|
||||
|
||||
def __repr__(self):
|
||||
return "IntlWritingCode(%s, %s)" % (`self.script`, `self.language`)
|
||||
|
||||
def __str__(self):
|
||||
return "script system %d, language %d"%(self.script, self.language)
|
||||
|
||||
def __aepack__(self):
|
||||
return pack(struct.pack('hh', self.script, self.language),
|
||||
typeIntlWritingCode)
|
||||
"""An object representing script and language"""
|
||||
|
||||
def __init__(self, script, language):
|
||||
self.script = script
|
||||
self.language = language
|
||||
|
||||
def __repr__(self):
|
||||
return "IntlWritingCode(%s, %s)" % (`self.script`, `self.language`)
|
||||
|
||||
def __str__(self):
|
||||
return "script system %d, language %d"%(self.script, self.language)
|
||||
|
||||
def __aepack__(self):
|
||||
return pack(struct.pack('hh', self.script, self.language),
|
||||
typeIntlWritingCode)
|
||||
|
||||
def IsIntlWritingCode(x):
|
||||
return isinstance(x, IntlWritingCode)
|
||||
return isinstance(x, IntlWritingCode)
|
||||
|
||||
class QDPoint:
|
||||
"""A point"""
|
||||
|
||||
def __init__(self, v, h):
|
||||
self.v = v
|
||||
self.h = h
|
||||
|
||||
def __repr__(self):
|
||||
return "QDPoint(%s, %s)" % (`self.v`, `self.h`)
|
||||
|
||||
def __str__(self):
|
||||
return "(%d, %d)"%(self.v, self.h)
|
||||
|
||||
def __aepack__(self):
|
||||
return pack(struct.pack('hh', self.v, self.h),
|
||||
typeQDPoint)
|
||||
"""A point"""
|
||||
|
||||
def __init__(self, v, h):
|
||||
self.v = v
|
||||
self.h = h
|
||||
|
||||
def __repr__(self):
|
||||
return "QDPoint(%s, %s)" % (`self.v`, `self.h`)
|
||||
|
||||
def __str__(self):
|
||||
return "(%d, %d)"%(self.v, self.h)
|
||||
|
||||
def __aepack__(self):
|
||||
return pack(struct.pack('hh', self.v, self.h),
|
||||
typeQDPoint)
|
||||
|
||||
def IsQDPoint(x):
|
||||
return isinstance(x, QDPoint)
|
||||
return isinstance(x, QDPoint)
|
||||
|
||||
class QDRectangle:
|
||||
"""A rectangle"""
|
||||
|
||||
def __init__(self, v0, h0, v1, h1):
|
||||
self.v0 = v0
|
||||
self.h0 = h0
|
||||
self.v1 = v1
|
||||
self.h1 = h1
|
||||
|
||||
def __repr__(self):
|
||||
return "QDRectangle(%s, %s, %s, %s)" % (`self.v0`, `self.h0`,
|
||||
`self.v1`, `self.h1`)
|
||||
|
||||
def __str__(self):
|
||||
return "(%d, %d)-(%d, %d)"%(self.v0, self.h0, self.v1, self.h1)
|
||||
|
||||
def __aepack__(self):
|
||||
return pack(struct.pack('hhhh', self.v0, self.h0, self.v1, self.h1),
|
||||
typeQDRectangle)
|
||||
"""A rectangle"""
|
||||
|
||||
def __init__(self, v0, h0, v1, h1):
|
||||
self.v0 = v0
|
||||
self.h0 = h0
|
||||
self.v1 = v1
|
||||
self.h1 = h1
|
||||
|
||||
def __repr__(self):
|
||||
return "QDRectangle(%s, %s, %s, %s)" % (`self.v0`, `self.h0`,
|
||||
`self.v1`, `self.h1`)
|
||||
|
||||
def __str__(self):
|
||||
return "(%d, %d)-(%d, %d)"%(self.v0, self.h0, self.v1, self.h1)
|
||||
|
||||
def __aepack__(self):
|
||||
return pack(struct.pack('hhhh', self.v0, self.h0, self.v1, self.h1),
|
||||
typeQDRectangle)
|
||||
|
||||
def IsQDRectangle(x):
|
||||
return isinstance(x, QDRectangle)
|
||||
return isinstance(x, QDRectangle)
|
||||
|
||||
class RGBColor:
|
||||
"""An RGB color"""
|
||||
|
||||
def __init__(self, r, g, b):
|
||||
self.r = r
|
||||
self.g = g
|
||||
self.b = b
|
||||
|
||||
def __repr__(self):
|
||||
return "RGBColor(%s, %s, %s)" % (`self.r`, `self.g`, `self.b`)
|
||||
|
||||
def __str__(self):
|
||||
return "0x%x red, 0x%x green, 0x%x blue"% (self.r, self.g, self.b)
|
||||
|
||||
def __aepack__(self):
|
||||
return pack(struct.pack('hhh', self.r, self.g, self.b),
|
||||
typeRGBColor)
|
||||
"""An RGB color"""
|
||||
|
||||
def __init__(self, r, g, b):
|
||||
self.r = r
|
||||
self.g = g
|
||||
self.b = b
|
||||
|
||||
def __repr__(self):
|
||||
return "RGBColor(%s, %s, %s)" % (`self.r`, `self.g`, `self.b`)
|
||||
|
||||
def __str__(self):
|
||||
return "0x%x red, 0x%x green, 0x%x blue"% (self.r, self.g, self.b)
|
||||
|
||||
def __aepack__(self):
|
||||
return pack(struct.pack('hhh', self.r, self.g, self.b),
|
||||
typeRGBColor)
|
||||
|
||||
def IsRGBColor(x):
|
||||
return isinstance(x, RGBColor)
|
||||
return isinstance(x, RGBColor)
|
||||
|
||||
class ObjectSpecifier:
|
||||
|
||||
"""A class for constructing and manipulation AE object specifiers in python.
|
||||
|
||||
An object specifier is actually a record with four fields:
|
||||
|
||||
key type description
|
||||
--- ---- -----------
|
||||
|
||||
'want' type 4-char class code of thing we want,
|
||||
e.g. word, paragraph or property
|
||||
|
||||
'form' enum how we specify which 'want' thing(s) we want,
|
||||
e.g. by index, by range, by name, or by property specifier
|
||||
|
||||
'seld' any which thing(s) we want,
|
||||
e.g. its index, its name, or its property specifier
|
||||
|
||||
'from' object the object in which it is contained,
|
||||
or null, meaning look for it in the application
|
||||
|
||||
Note that we don't call this class plain "Object", since that name
|
||||
is likely to be used by the application.
|
||||
"""
|
||||
|
||||
def __init__(self, want, form, seld, fr = None):
|
||||
self.want = want
|
||||
self.form = form
|
||||
self.seld = seld
|
||||
self.fr = fr
|
||||
|
||||
def __repr__(self):
|
||||
s = "ObjectSpecifier(%s, %s, %s" % (`self.want`, `self.form`, `self.seld`)
|
||||
if self.fr:
|
||||
s = s + ", %s)" % `self.fr`
|
||||
else:
|
||||
s = s + ")"
|
||||
return s
|
||||
|
||||
def __aepack__(self):
|
||||
return pack({'want': mktype(self.want),
|
||||
'form': mkenum(self.form),
|
||||
'seld': self.seld,
|
||||
'from': self.fr},
|
||||
'obj ')
|
||||
|
||||
"""A class for constructing and manipulation AE object specifiers in python.
|
||||
|
||||
An object specifier is actually a record with four fields:
|
||||
|
||||
key type description
|
||||
--- ---- -----------
|
||||
|
||||
'want' type 4-char class code of thing we want,
|
||||
e.g. word, paragraph or property
|
||||
|
||||
'form' enum how we specify which 'want' thing(s) we want,
|
||||
e.g. by index, by range, by name, or by property specifier
|
||||
|
||||
'seld' any which thing(s) we want,
|
||||
e.g. its index, its name, or its property specifier
|
||||
|
||||
'from' object the object in which it is contained,
|
||||
or null, meaning look for it in the application
|
||||
|
||||
Note that we don't call this class plain "Object", since that name
|
||||
is likely to be used by the application.
|
||||
"""
|
||||
|
||||
def __init__(self, want, form, seld, fr = None):
|
||||
self.want = want
|
||||
self.form = form
|
||||
self.seld = seld
|
||||
self.fr = fr
|
||||
|
||||
def __repr__(self):
|
||||
s = "ObjectSpecifier(%s, %s, %s" % (`self.want`, `self.form`, `self.seld`)
|
||||
if self.fr:
|
||||
s = s + ", %s)" % `self.fr`
|
||||
else:
|
||||
s = s + ")"
|
||||
return s
|
||||
|
||||
def __aepack__(self):
|
||||
return pack({'want': mktype(self.want),
|
||||
'form': mkenum(self.form),
|
||||
'seld': self.seld,
|
||||
'from': self.fr},
|
||||
'obj ')
|
||||
|
||||
def IsObjectSpecifier(x):
|
||||
return isinstance(x, ObjectSpecifier)
|
||||
return isinstance(x, ObjectSpecifier)
|
||||
|
||||
|
||||
# Backwards compatability, sigh...
|
||||
class Property(ObjectSpecifier):
|
||||
|
||||
def __init__(self, which, fr = None, want='prop'):
|
||||
ObjectSpecifier.__init__(self, want, 'prop', mktype(which), fr)
|
||||
def __init__(self, which, fr = None, want='prop'):
|
||||
ObjectSpecifier.__init__(self, want, 'prop', mktype(which), fr)
|
||||
|
||||
def __repr__(self):
|
||||
if self.fr:
|
||||
return "Property(%s, %s)" % (`self.seld.type`, `self.fr`)
|
||||
else:
|
||||
return "Property(%s)" % `self.seld.type`
|
||||
|
||||
def __str__(self):
|
||||
if self.fr:
|
||||
return "Property %s of %s" % (str(self.seld), str(self.fr))
|
||||
else:
|
||||
return "Property %s" % str(self.seld)
|
||||
def __repr__(self):
|
||||
if self.fr:
|
||||
return "Property(%s, %s)" % (`self.seld.type`, `self.fr`)
|
||||
else:
|
||||
return "Property(%s)" % `self.seld.type`
|
||||
|
||||
def __str__(self):
|
||||
if self.fr:
|
||||
return "Property %s of %s" % (str(self.seld), str(self.fr))
|
||||
else:
|
||||
return "Property %s" % str(self.seld)
|
||||
|
||||
|
||||
class NProperty(ObjectSpecifier):
|
||||
# Subclasses *must* self baseclass attributes:
|
||||
# want is the type of this property
|
||||
# which is the property name of this property
|
||||
# Subclasses *must* self baseclass attributes:
|
||||
# want is the type of this property
|
||||
# which is the property name of this property
|
||||
|
||||
def __init__(self, fr = None):
|
||||
#try:
|
||||
# dummy = self.want
|
||||
#except:
|
||||
# self.want = 'prop'
|
||||
self.want = 'prop'
|
||||
ObjectSpecifier.__init__(self, self.want, 'prop',
|
||||
mktype(self.which), fr)
|
||||
def __init__(self, fr = None):
|
||||
#try:
|
||||
# dummy = self.want
|
||||
#except:
|
||||
# self.want = 'prop'
|
||||
self.want = 'prop'
|
||||
ObjectSpecifier.__init__(self, self.want, 'prop',
|
||||
mktype(self.which), fr)
|
||||
|
||||
def __repr__(self):
|
||||
rv = "Property(%s"%`self.seld.type`
|
||||
if self.fr:
|
||||
rv = rv + ", fr=%s" % `self.fr`
|
||||
if self.want != 'prop':
|
||||
rv = rv + ", want=%s" % `self.want`
|
||||
return rv + ")"
|
||||
|
||||
def __str__(self):
|
||||
if self.fr:
|
||||
return "Property %s of %s" % (str(self.seld), str(self.fr))
|
||||
else:
|
||||
return "Property %s" % str(self.seld)
|
||||
def __repr__(self):
|
||||
rv = "Property(%s"%`self.seld.type`
|
||||
if self.fr:
|
||||
rv = rv + ", fr=%s" % `self.fr`
|
||||
if self.want != 'prop':
|
||||
rv = rv + ", want=%s" % `self.want`
|
||||
return rv + ")"
|
||||
|
||||
def __str__(self):
|
||||
if self.fr:
|
||||
return "Property %s of %s" % (str(self.seld), str(self.fr))
|
||||
else:
|
||||
return "Property %s" % str(self.seld)
|
||||
|
||||
|
||||
class SelectableItem(ObjectSpecifier):
|
||||
|
||||
def __init__(self, want, seld, fr = None):
|
||||
t = type(seld)
|
||||
if t == StringType:
|
||||
form = 'name'
|
||||
elif IsRange(seld):
|
||||
form = 'rang'
|
||||
elif IsComparison(seld) or IsLogical(seld):
|
||||
form = 'test'
|
||||
elif t == TupleType:
|
||||
# Breakout: specify both form and seld in a tuple
|
||||
# (if you want ID or rele or somesuch)
|
||||
form, seld = seld
|
||||
else:
|
||||
form = 'indx'
|
||||
ObjectSpecifier.__init__(self, want, form, seld, fr)
|
||||
|
||||
def __init__(self, want, seld, fr = None):
|
||||
t = type(seld)
|
||||
if t == StringType:
|
||||
form = 'name'
|
||||
elif IsRange(seld):
|
||||
form = 'rang'
|
||||
elif IsComparison(seld) or IsLogical(seld):
|
||||
form = 'test'
|
||||
elif t == TupleType:
|
||||
# Breakout: specify both form and seld in a tuple
|
||||
# (if you want ID or rele or somesuch)
|
||||
form, seld = seld
|
||||
else:
|
||||
form = 'indx'
|
||||
ObjectSpecifier.__init__(self, want, form, seld, fr)
|
||||
|
||||
|
||||
class ComponentItem(SelectableItem):
|
||||
# Derived classes *must* set the *class attribute* 'want' to some constant
|
||||
# Also, dictionaries _propdict and _elemdict must be set to map property
|
||||
# and element names to the correct classes
|
||||
# Derived classes *must* set the *class attribute* 'want' to some constant
|
||||
# Also, dictionaries _propdict and _elemdict must be set to map property
|
||||
# and element names to the correct classes
|
||||
|
||||
_propdict = {}
|
||||
_elemdict = {}
|
||||
def __init__(self, which, fr = None):
|
||||
SelectableItem.__init__(self, self.want, which, fr)
|
||||
|
||||
def __repr__(self):
|
||||
if not self.fr:
|
||||
return "%s(%s)" % (self.__class__.__name__, `self.seld`)
|
||||
return "%s(%s, %s)" % (self.__class__.__name__, `self.seld`, `self.fr`)
|
||||
|
||||
def __str__(self):
|
||||
seld = self.seld
|
||||
if type(seld) == StringType:
|
||||
ss = repr(seld)
|
||||
elif IsRange(seld):
|
||||
start, stop = seld.start, seld.stop
|
||||
if type(start) == InstanceType == type(stop) and \
|
||||
start.__class__ == self.__class__ == stop.__class__:
|
||||
ss = str(start.seld) + " thru " + str(stop.seld)
|
||||
else:
|
||||
ss = str(seld)
|
||||
else:
|
||||
ss = str(seld)
|
||||
s = "%s %s" % (self.__class__.__name__, ss)
|
||||
if self.fr: s = s + " of %s" % str(self.fr)
|
||||
return s
|
||||
|
||||
def __getattr__(self, name):
|
||||
if self._elemdict.has_key(name):
|
||||
cls = self._elemdict[name]
|
||||
return DelayedComponentItem(cls, self)
|
||||
if self._propdict.has_key(name):
|
||||
cls = self._propdict[name]
|
||||
return cls(self)
|
||||
raise AttributeError, name
|
||||
|
||||
|
||||
_propdict = {}
|
||||
_elemdict = {}
|
||||
def __init__(self, which, fr = None):
|
||||
SelectableItem.__init__(self, self.want, which, fr)
|
||||
|
||||
def __repr__(self):
|
||||
if not self.fr:
|
||||
return "%s(%s)" % (self.__class__.__name__, `self.seld`)
|
||||
return "%s(%s, %s)" % (self.__class__.__name__, `self.seld`, `self.fr`)
|
||||
|
||||
def __str__(self):
|
||||
seld = self.seld
|
||||
if type(seld) == StringType:
|
||||
ss = repr(seld)
|
||||
elif IsRange(seld):
|
||||
start, stop = seld.start, seld.stop
|
||||
if type(start) == InstanceType == type(stop) and \
|
||||
start.__class__ == self.__class__ == stop.__class__:
|
||||
ss = str(start.seld) + " thru " + str(stop.seld)
|
||||
else:
|
||||
ss = str(seld)
|
||||
else:
|
||||
ss = str(seld)
|
||||
s = "%s %s" % (self.__class__.__name__, ss)
|
||||
if self.fr: s = s + " of %s" % str(self.fr)
|
||||
return s
|
||||
|
||||
def __getattr__(self, name):
|
||||
if self._elemdict.has_key(name):
|
||||
cls = self._elemdict[name]
|
||||
return DelayedComponentItem(cls, self)
|
||||
if self._propdict.has_key(name):
|
||||
cls = self._propdict[name]
|
||||
return cls(self)
|
||||
raise AttributeError, name
|
||||
|
||||
|
||||
class DelayedComponentItem:
|
||||
def __init__(self, compclass, fr):
|
||||
self.compclass = compclass
|
||||
self.fr = fr
|
||||
|
||||
def __call__(self, which):
|
||||
return self.compclass(which, self.fr)
|
||||
|
||||
def __repr__(self):
|
||||
return "%s(???, %s)" % (self.__class__.__name__, `self.fr`)
|
||||
|
||||
def __str__(self):
|
||||
return "selector for element %s of %s"%(self.__class__.__name__, str(self.fr))
|
||||
def __init__(self, compclass, fr):
|
||||
self.compclass = compclass
|
||||
self.fr = fr
|
||||
|
||||
def __call__(self, which):
|
||||
return self.compclass(which, self.fr)
|
||||
|
||||
def __repr__(self):
|
||||
return "%s(???, %s)" % (self.__class__.__name__, `self.fr`)
|
||||
|
||||
def __str__(self):
|
||||
return "selector for element %s of %s"%(self.__class__.__name__, str(self.fr))
|
||||
|
||||
template = """
|
||||
class %s(ComponentItem): want = '%s'
|
||||
|
|
|
@ -24,77 +24,77 @@ AS_RESOURCEFORK=2
|
|||
AS_IGNORE=(3,4,5,6,8,9,10,11,12,13,14,15)
|
||||
|
||||
def decode(input, output, resonly=0):
|
||||
if type(input) == type(''):
|
||||
input = open(input, 'rb')
|
||||
# Should we also test for FSSpecs or FSRefs?
|
||||
header = input.read(AS_HEADER_LENGTH)
|
||||
try:
|
||||
magic, version, dummy, nentry = struct.unpack(AS_HEADER_FORMAT, header)
|
||||
except ValueError, arg:
|
||||
raise Error, "Unpack header error: %s"%arg
|
||||
if verbose:
|
||||
print 'Magic: 0x%8.8x'%magic
|
||||
print 'Version: 0x%8.8x'%version
|
||||
print 'Entries: %d'%nentry
|
||||
if magic != AS_MAGIC:
|
||||
raise Error, 'Unknown AppleSingle magic number 0x%8.8x'%magic
|
||||
if version != AS_VERSION:
|
||||
raise Error, 'Unknown AppleSingle version number 0x%8.8x'%version
|
||||
if nentry <= 0:
|
||||
raise Error, "AppleSingle file contains no forks"
|
||||
headers = [input.read(AS_ENTRY_LENGTH) for i in range(nentry)]
|
||||
didwork = 0
|
||||
for hdr in headers:
|
||||
try:
|
||||
id, offset, length = struct.unpack(AS_ENTRY_FORMAT, hdr)
|
||||
except ValueError, arg:
|
||||
raise Error, "Unpack entry error: %s"%arg
|
||||
if verbose:
|
||||
print 'Fork %d, offset %d, length %d'%(id, offset, length)
|
||||
input.seek(offset)
|
||||
if length == 0:
|
||||
data = ''
|
||||
else:
|
||||
data = input.read(length)
|
||||
if len(data) != length:
|
||||
raise Error, 'Short read: expected %d bytes got %d'%(length, len(data))
|
||||
if id == AS_DATAFORK:
|
||||
if verbose:
|
||||
print ' (data fork)'
|
||||
if not resonly:
|
||||
didwork = 1
|
||||
fp = open(output, 'wb')
|
||||
fp.write(data)
|
||||
fp.close()
|
||||
elif id == AS_RESOURCEFORK:
|
||||
didwork = 1
|
||||
if verbose:
|
||||
print ' (resource fork)'
|
||||
if resonly:
|
||||
fp = open(output, 'wb')
|
||||
else:
|
||||
fp = MacOS.openrf(output, 'wb')
|
||||
fp.write(data)
|
||||
fp.close()
|
||||
elif id in AS_IGNORE:
|
||||
if verbose:
|
||||
print ' (ignored)'
|
||||
else:
|
||||
raise Error, 'Unknown fork type %d'%id
|
||||
if not didwork:
|
||||
raise Error, 'No useful forks found'
|
||||
if type(input) == type(''):
|
||||
input = open(input, 'rb')
|
||||
# Should we also test for FSSpecs or FSRefs?
|
||||
header = input.read(AS_HEADER_LENGTH)
|
||||
try:
|
||||
magic, version, dummy, nentry = struct.unpack(AS_HEADER_FORMAT, header)
|
||||
except ValueError, arg:
|
||||
raise Error, "Unpack header error: %s"%arg
|
||||
if verbose:
|
||||
print 'Magic: 0x%8.8x'%magic
|
||||
print 'Version: 0x%8.8x'%version
|
||||
print 'Entries: %d'%nentry
|
||||
if magic != AS_MAGIC:
|
||||
raise Error, 'Unknown AppleSingle magic number 0x%8.8x'%magic
|
||||
if version != AS_VERSION:
|
||||
raise Error, 'Unknown AppleSingle version number 0x%8.8x'%version
|
||||
if nentry <= 0:
|
||||
raise Error, "AppleSingle file contains no forks"
|
||||
headers = [input.read(AS_ENTRY_LENGTH) for i in range(nentry)]
|
||||
didwork = 0
|
||||
for hdr in headers:
|
||||
try:
|
||||
id, offset, length = struct.unpack(AS_ENTRY_FORMAT, hdr)
|
||||
except ValueError, arg:
|
||||
raise Error, "Unpack entry error: %s"%arg
|
||||
if verbose:
|
||||
print 'Fork %d, offset %d, length %d'%(id, offset, length)
|
||||
input.seek(offset)
|
||||
if length == 0:
|
||||
data = ''
|
||||
else:
|
||||
data = input.read(length)
|
||||
if len(data) != length:
|
||||
raise Error, 'Short read: expected %d bytes got %d'%(length, len(data))
|
||||
if id == AS_DATAFORK:
|
||||
if verbose:
|
||||
print ' (data fork)'
|
||||
if not resonly:
|
||||
didwork = 1
|
||||
fp = open(output, 'wb')
|
||||
fp.write(data)
|
||||
fp.close()
|
||||
elif id == AS_RESOURCEFORK:
|
||||
didwork = 1
|
||||
if verbose:
|
||||
print ' (resource fork)'
|
||||
if resonly:
|
||||
fp = open(output, 'wb')
|
||||
else:
|
||||
fp = MacOS.openrf(output, 'wb')
|
||||
fp.write(data)
|
||||
fp.close()
|
||||
elif id in AS_IGNORE:
|
||||
if verbose:
|
||||
print ' (ignored)'
|
||||
else:
|
||||
raise Error, 'Unknown fork type %d'%id
|
||||
if not didwork:
|
||||
raise Error, 'No useful forks found'
|
||||
|
||||
def _test():
|
||||
if len(sys.argv) < 3 or sys.argv[1] == '-r' and len(sys.argv) != 4:
|
||||
print 'Usage: applesingle.py [-r] applesinglefile decodedfile'
|
||||
sys.exit(1)
|
||||
if sys.argv[1] == '-r':
|
||||
resonly = 1
|
||||
del sys.argv[1]
|
||||
else:
|
||||
resonly = 0
|
||||
decode(sys.argv[1], sys.argv[2], resonly=resonly)
|
||||
|
||||
if len(sys.argv) < 3 or sys.argv[1] == '-r' and len(sys.argv) != 4:
|
||||
print 'Usage: applesingle.py [-r] applesinglefile decodedfile'
|
||||
sys.exit(1)
|
||||
if sys.argv[1] == '-r':
|
||||
resonly = 1
|
||||
del sys.argv[1]
|
||||
else:
|
||||
resonly = 0
|
||||
decode(sys.argv[1], sys.argv[2], resonly=resonly)
|
||||
|
||||
if __name__ == '__main__':
|
||||
_test()
|
||||
|
||||
_test()
|
||||
|
|
@ -14,13 +14,13 @@ import marshal
|
|||
# directory.
|
||||
#
|
||||
if not sys.argv or sys.argv[0][:1] == '-':
|
||||
# Insert our (guessed) name.
|
||||
_dir = os.path.split(sys.executable)[0] # removes "python"
|
||||
_dir = os.path.split(_dir)[0] # Removes "MacOS"
|
||||
_dir = os.path.join(_dir, 'Resources')
|
||||
sys.argv.insert(0, '__rawmain__')
|
||||
# Insert our (guessed) name.
|
||||
_dir = os.path.split(sys.executable)[0] # removes "python"
|
||||
_dir = os.path.split(_dir)[0] # Removes "MacOS"
|
||||
_dir = os.path.join(_dir, 'Resources')
|
||||
sys.argv.insert(0, '__rawmain__')
|
||||
else:
|
||||
_dir = os.path.split(sys.argv[0])[0]
|
||||
_dir = os.path.split(sys.argv[0])[0]
|
||||
#
|
||||
# Add the Resources directory to the path. This is where files installed
|
||||
# by BuildApplet.py with the --extra option show up, and if those files are
|
||||
|
@ -36,28 +36,28 @@ argvemulator.ArgvCollector().mainloop()
|
|||
#
|
||||
__file__ = os.path.join(_dir, '__main__.py')
|
||||
if os.path.exists(__file__):
|
||||
#
|
||||
# Setup something resembling a normal environment and go.
|
||||
#
|
||||
sys.argv[0] = __file__
|
||||
del argvemulator, os, sys, _dir
|
||||
execfile(__file__)
|
||||
#
|
||||
# Setup something resembling a normal environment and go.
|
||||
#
|
||||
sys.argv[0] = __file__
|
||||
del argvemulator, os, sys, _dir
|
||||
execfile(__file__)
|
||||
else:
|
||||
__file__ = os.path.join(_dir, '__main__.pyc')
|
||||
if os.path.exists(__file__):
|
||||
#
|
||||
# If we have only a .pyc file we read the code object from that
|
||||
#
|
||||
sys.argv[0] = __file__
|
||||
_fp = open(__file__, 'rb')
|
||||
_fp.read(8)
|
||||
__code__ = marshal.load(_fp)
|
||||
#
|
||||
# Again, we create an almost-normal environment (only __code__ is
|
||||
# funny) and go.
|
||||
#
|
||||
del argvemulator, os, sys, marshal, _dir, _fp
|
||||
exec __code__
|
||||
else:
|
||||
sys.stderr.write("%s: neither __main__.py nor __main__.pyc found\n"%sys.argv[0])
|
||||
sys.exit(1)
|
||||
__file__ = os.path.join(_dir, '__main__.pyc')
|
||||
if os.path.exists(__file__):
|
||||
#
|
||||
# If we have only a .pyc file we read the code object from that
|
||||
#
|
||||
sys.argv[0] = __file__
|
||||
_fp = open(__file__, 'rb')
|
||||
_fp.read(8)
|
||||
__code__ = marshal.load(_fp)
|
||||
#
|
||||
# Again, we create an almost-normal environment (only __code__ is
|
||||
# funny) and go.
|
||||
#
|
||||
del argvemulator, os, sys, marshal, _dir, _fp
|
||||
exec __code__
|
||||
else:
|
||||
sys.stderr.write("%s: neither __main__.py nor __main__.pyc found\n"%sys.argv[0])
|
||||
sys.exit(1)
|
||||
|
|
|
@ -6,12 +6,12 @@
|
|||
import os
|
||||
import sys
|
||||
for name in ["__rawmain__.py", "__rawmain__.pyc", "__main__.py", "__main__.pyc"]:
|
||||
realmain = os.path.join(os.path.dirname(os.path.dirname(sys.argv[0])),
|
||||
"Resources", name)
|
||||
if os.path.exists(realmain):
|
||||
break
|
||||
realmain = os.path.join(os.path.dirname(os.path.dirname(sys.argv[0])),
|
||||
"Resources", name)
|
||||
if os.path.exists(realmain):
|
||||
break
|
||||
else:
|
||||
sys.stderr.write("%s: cannot find applet main program\n" % sys.argv[0])
|
||||
sys.exit(1)
|
||||
sys.stderr.write("%s: cannot find applet main program\n" % sys.argv[0])
|
||||
sys.exit(1)
|
||||
sys.argv.insert(1, realmain)
|
||||
os.execve(sys.executable, sys.argv, os.environ)
|
||||
|
|
|
@ -12,12 +12,12 @@ Error = "bgenlocations.Error"
|
|||
# Where bgen is. For unix-Python bgen isn't installed, so you have to refer to
|
||||
# the source tree here.
|
||||
if sys.platform == 'mac':
|
||||
# For MacPython we know where it is
|
||||
def _pardir(p): return os.path.split(p)[0]
|
||||
BGENDIR=os.path.join(sys.prefix, "Tools", "bgen", "bgen")
|
||||
# For MacPython we know where it is
|
||||
def _pardir(p): return os.path.split(p)[0]
|
||||
BGENDIR=os.path.join(sys.prefix, "Tools", "bgen", "bgen")
|
||||
else:
|
||||
# for unix-Python we don't know, please set it yourself.
|
||||
BGENDIR="/Users/jack/src/python/Tools/bgen/bgen"
|
||||
# for unix-Python we don't know, please set it yourself.
|
||||
BGENDIR="/Users/jack/src/python/Tools/bgen/bgen"
|
||||
|
||||
#
|
||||
# Where to find the Universal Header include files. If you have CodeWarrior
|
||||
|
@ -26,9 +26,9 @@ else:
|
|||
# end of lines, so don't worry about that.
|
||||
#
|
||||
if sys.platform == 'mac':
|
||||
_MWERKSDIR="Sap:Applications (Mac OS 9):Metrowerks CodeWarrior 7.0:Metrowerks CodeWarrior"
|
||||
_MWERKSDIR="Sap:Applications (Mac OS 9):Metrowerks CodeWarrior 7.0:Metrowerks CodeWarrior"
|
||||
else:
|
||||
_MWERKSDIR="/Volumes/Sap/Applications (Mac OS 9)/Metrowerks CodeWarrior 7.0/Metrowerks CodeWarrior/"
|
||||
_MWERKSDIR="/Volumes/Sap/Applications (Mac OS 9)/Metrowerks CodeWarrior 7.0/Metrowerks CodeWarrior/"
|
||||
INCLUDEDIR=os.path.join(_MWERKSDIR, "MacOS Support", "Universal", "Interfaces", "CIncludes")
|
||||
|
||||
#
|
||||
|
@ -37,25 +37,25 @@ INCLUDEDIR=os.path.join(_MWERKSDIR, "MacOS Support", "Universal", "Interfaces",
|
|||
# your source directory, not your installed directory.
|
||||
#
|
||||
if sys.platform == 'mac':
|
||||
TOOLBOXDIR=os.path.join(sys.prefix, "Lib", "plat-mac", "Carbon")
|
||||
TOOLBOXDIR=os.path.join(sys.prefix, "Lib", "plat-mac", "Carbon")
|
||||
else:
|
||||
TOOLBOXDIR="/Users/jack/src/python/Lib/plat-mac/Carbon"
|
||||
TOOLBOXDIR="/Users/jack/src/python/Lib/plat-mac/Carbon"
|
||||
|
||||
# Creator for C files:
|
||||
CREATOR="CWIE"
|
||||
|
||||
if not os.path.exists(BGENDIR):
|
||||
raise Error, "Please fix bgenlocations.py, BGENDIR does not exist: %s" % BGENDIR
|
||||
raise Error, "Please fix bgenlocations.py, BGENDIR does not exist: %s" % BGENDIR
|
||||
if not os.path.exists(INCLUDEDIR):
|
||||
raise Error, "Please fix bgenlocations.py, INCLUDEDIR does not exist: %s" % INCLUDEDIR
|
||||
raise Error, "Please fix bgenlocations.py, INCLUDEDIR does not exist: %s" % INCLUDEDIR
|
||||
if not os.path.exists(TOOLBOXDIR):
|
||||
raise Error, "Please fix bgenlocations.py, TOOLBOXDIR does not exist: %s" % TOOLBOXDIR
|
||||
|
||||
raise Error, "Please fix bgenlocations.py, TOOLBOXDIR does not exist: %s" % TOOLBOXDIR
|
||||
|
||||
# Sigh, due to the way these are used make sure they end with : or /.
|
||||
if BGENDIR[-1] != os.sep:
|
||||
BGENDIR = BGENDIR + os.sep
|
||||
BGENDIR = BGENDIR + os.sep
|
||||
if INCLUDEDIR[-1] != os.sep:
|
||||
INCLUDEDIR = INCLUDEDIR + os.sep
|
||||
INCLUDEDIR = INCLUDEDIR + os.sep
|
||||
if TOOLBOXDIR[-1] != os.sep:
|
||||
TOOLBOXDIR = TOOLBOXDIR + os.sep
|
||||
|
||||
TOOLBOXDIR = TOOLBOXDIR + os.sep
|
||||
|
||||
|
|
|
@ -42,375 +42,375 @@ WRITE = 2
|
|||
RESOURCE_FORK_NAME=Carbon.File.FSGetResourceForkName()
|
||||
|
||||
def findtemplate(template=None):
|
||||
"""Locate the applet template along sys.path"""
|
||||
if MacOS.runtimemodel == 'macho':
|
||||
return None
|
||||
if not template:
|
||||
template=TEMPLATE
|
||||
for p in sys.path:
|
||||
file = os.path.join(p, template)
|
||||
try:
|
||||
file, d1, d2 = Carbon.File.FSResolveAliasFile(file, 1)
|
||||
break
|
||||
except (Carbon.File.Error, ValueError):
|
||||
continue
|
||||
else:
|
||||
raise BuildError, "Template %s not found on sys.path" % `template`
|
||||
file = file.as_pathname()
|
||||
return file
|
||||
|
||||
"""Locate the applet template along sys.path"""
|
||||
if MacOS.runtimemodel == 'macho':
|
||||
return None
|
||||
if not template:
|
||||
template=TEMPLATE
|
||||
for p in sys.path:
|
||||
file = os.path.join(p, template)
|
||||
try:
|
||||
file, d1, d2 = Carbon.File.FSResolveAliasFile(file, 1)
|
||||
break
|
||||
except (Carbon.File.Error, ValueError):
|
||||
continue
|
||||
else:
|
||||
raise BuildError, "Template %s not found on sys.path" % `template`
|
||||
file = file.as_pathname()
|
||||
return file
|
||||
|
||||
def process(template, filename, destname, copy_codefragment=0,
|
||||
rsrcname=None, others=[], raw=0, progress="default"):
|
||||
|
||||
if progress == "default":
|
||||
progress = EasyDialogs.ProgressBar("Processing %s..."%os.path.split(filename)[1], 120)
|
||||
progress.label("Compiling...")
|
||||
progress.inc(0)
|
||||
# check for the script name being longer than 32 chars. This may trigger a bug
|
||||
# on OSX that can destroy your sourcefile.
|
||||
if '#' in os.path.split(filename)[1]:
|
||||
raise BuildError, "BuildApplet could destroy your sourcefile on OSX, please rename: %s" % filename
|
||||
# Read the source and compile it
|
||||
# (there's no point overwriting the destination if it has a syntax error)
|
||||
|
||||
fp = open(filename, 'rU')
|
||||
text = fp.read()
|
||||
fp.close()
|
||||
try:
|
||||
code = compile(text + '\n', filename, "exec")
|
||||
except SyntaxError, arg:
|
||||
raise BuildError, "Syntax error in script %s: %s" % (filename, arg)
|
||||
except EOFError:
|
||||
raise BuildError, "End-of-file in script %s" % (filename,)
|
||||
|
||||
# Set the destination file name. Note that basename
|
||||
# does contain the whole filepath, only a .py is stripped.
|
||||
|
||||
if string.lower(filename[-3:]) == ".py":
|
||||
basename = filename[:-3]
|
||||
if MacOS.runtimemodel != 'macho' and not destname:
|
||||
destname = basename
|
||||
else:
|
||||
basename = filename
|
||||
|
||||
if not destname:
|
||||
if MacOS.runtimemodel == 'macho':
|
||||
destname = basename + '.app'
|
||||
else:
|
||||
destname = basename + '.applet'
|
||||
if not rsrcname:
|
||||
rsrcname = basename + '.rsrc'
|
||||
|
||||
# Try removing the output file. This fails in MachO, but it should
|
||||
# do any harm.
|
||||
try:
|
||||
os.remove(destname)
|
||||
except os.error:
|
||||
pass
|
||||
process_common(template, progress, code, rsrcname, destname, 0,
|
||||
copy_codefragment, raw, others, filename)
|
||||
|
||||
rsrcname=None, others=[], raw=0, progress="default"):
|
||||
|
||||
if progress == "default":
|
||||
progress = EasyDialogs.ProgressBar("Processing %s..."%os.path.split(filename)[1], 120)
|
||||
progress.label("Compiling...")
|
||||
progress.inc(0)
|
||||
# check for the script name being longer than 32 chars. This may trigger a bug
|
||||
# on OSX that can destroy your sourcefile.
|
||||
if '#' in os.path.split(filename)[1]:
|
||||
raise BuildError, "BuildApplet could destroy your sourcefile on OSX, please rename: %s" % filename
|
||||
# Read the source and compile it
|
||||
# (there's no point overwriting the destination if it has a syntax error)
|
||||
|
||||
fp = open(filename, 'rU')
|
||||
text = fp.read()
|
||||
fp.close()
|
||||
try:
|
||||
code = compile(text + '\n', filename, "exec")
|
||||
except SyntaxError, arg:
|
||||
raise BuildError, "Syntax error in script %s: %s" % (filename, arg)
|
||||
except EOFError:
|
||||
raise BuildError, "End-of-file in script %s" % (filename,)
|
||||
|
||||
# Set the destination file name. Note that basename
|
||||
# does contain the whole filepath, only a .py is stripped.
|
||||
|
||||
if string.lower(filename[-3:]) == ".py":
|
||||
basename = filename[:-3]
|
||||
if MacOS.runtimemodel != 'macho' and not destname:
|
||||
destname = basename
|
||||
else:
|
||||
basename = filename
|
||||
|
||||
if not destname:
|
||||
if MacOS.runtimemodel == 'macho':
|
||||
destname = basename + '.app'
|
||||
else:
|
||||
destname = basename + '.applet'
|
||||
if not rsrcname:
|
||||
rsrcname = basename + '.rsrc'
|
||||
|
||||
# Try removing the output file. This fails in MachO, but it should
|
||||
# do any harm.
|
||||
try:
|
||||
os.remove(destname)
|
||||
except os.error:
|
||||
pass
|
||||
process_common(template, progress, code, rsrcname, destname, 0,
|
||||
copy_codefragment, raw, others, filename)
|
||||
|
||||
|
||||
def update(template, filename, output):
|
||||
if MacOS.runtimemodel == 'macho':
|
||||
raise BuildError, "No updating yet for MachO applets"
|
||||
if progress:
|
||||
progress = EasyDialogs.ProgressBar("Updating %s..."%os.path.split(filename)[1], 120)
|
||||
else:
|
||||
progress = None
|
||||
if not output:
|
||||
output = filename + ' (updated)'
|
||||
|
||||
# Try removing the output file
|
||||
try:
|
||||
os.remove(output)
|
||||
except os.error:
|
||||
pass
|
||||
process_common(template, progress, None, filename, output, 1, 1)
|
||||
if MacOS.runtimemodel == 'macho':
|
||||
raise BuildError, "No updating yet for MachO applets"
|
||||
if progress:
|
||||
progress = EasyDialogs.ProgressBar("Updating %s..."%os.path.split(filename)[1], 120)
|
||||
else:
|
||||
progress = None
|
||||
if not output:
|
||||
output = filename + ' (updated)'
|
||||
|
||||
# Try removing the output file
|
||||
try:
|
||||
os.remove(output)
|
||||
except os.error:
|
||||
pass
|
||||
process_common(template, progress, None, filename, output, 1, 1)
|
||||
|
||||
|
||||
def process_common(template, progress, code, rsrcname, destname, is_update,
|
||||
copy_codefragment, raw=0, others=[], filename=None):
|
||||
if MacOS.runtimemodel == 'macho':
|
||||
return process_common_macho(template, progress, code, rsrcname, destname,
|
||||
is_update, raw, others, filename)
|
||||
if others:
|
||||
raise BuildError, "Extra files only allowed for MachoPython applets"
|
||||
# Create FSSpecs for the various files
|
||||
template_fsr, d1, d2 = Carbon.File.FSResolveAliasFile(template, 1)
|
||||
template = template_fsr.as_pathname()
|
||||
|
||||
# Copy data (not resources, yet) from the template
|
||||
if progress:
|
||||
progress.label("Copy data fork...")
|
||||
progress.set(10)
|
||||
|
||||
if copy_codefragment:
|
||||
tmpl = open(template, "rb")
|
||||
dest = open(destname, "wb")
|
||||
data = tmpl.read()
|
||||
if data:
|
||||
dest.write(data)
|
||||
dest.close()
|
||||
tmpl.close()
|
||||
del dest
|
||||
del tmpl
|
||||
|
||||
# Open the output resource fork
|
||||
|
||||
if progress:
|
||||
progress.label("Copy resources...")
|
||||
progress.set(20)
|
||||
try:
|
||||
output = Res.FSOpenResourceFile(destname, RESOURCE_FORK_NAME, WRITE)
|
||||
except MacOS.Error:
|
||||
destdir, destfile = os.path.split(destname)
|
||||
Res.FSCreateResourceFile(destdir, unicode(destfile), RESOURCE_FORK_NAME)
|
||||
output = Res.FSOpenResourceFile(destname, RESOURCE_FORK_NAME, WRITE)
|
||||
|
||||
# Copy the resources from the target specific resource template, if any
|
||||
typesfound, ownertype = [], None
|
||||
try:
|
||||
input = Res.FSOpenResourceFile(rsrcname, RESOURCE_FORK_NAME, READ)
|
||||
except (MacOS.Error, ValueError):
|
||||
pass
|
||||
if progress:
|
||||
progress.inc(50)
|
||||
else:
|
||||
if is_update:
|
||||
skip_oldfile = ['cfrg']
|
||||
else:
|
||||
skip_oldfile = []
|
||||
typesfound, ownertype = copyres(input, output, skip_oldfile, 0, progress)
|
||||
Res.CloseResFile(input)
|
||||
|
||||
# Check which resource-types we should not copy from the template
|
||||
skiptypes = []
|
||||
if 'vers' in typesfound: skiptypes.append('vers')
|
||||
if 'SIZE' in typesfound: skiptypes.append('SIZE')
|
||||
if 'BNDL' in typesfound: skiptypes = skiptypes + ['BNDL', 'FREF', 'icl4',
|
||||
'icl8', 'ics4', 'ics8', 'ICN#', 'ics#']
|
||||
if not copy_codefragment:
|
||||
skiptypes.append('cfrg')
|
||||
## skipowner = (ownertype <> None)
|
||||
|
||||
# Copy the resources from the template
|
||||
|
||||
input = Res.FSOpenResourceFile(template, RESOURCE_FORK_NAME, READ)
|
||||
dummy, tmplowner = copyres(input, output, skiptypes, 1, progress)
|
||||
|
||||
Res.CloseResFile(input)
|
||||
## if ownertype == None:
|
||||
## raise BuildError, "No owner resource found in either resource file or template"
|
||||
# Make sure we're manipulating the output resource file now
|
||||
|
||||
Res.UseResFile(output)
|
||||
copy_codefragment, raw=0, others=[], filename=None):
|
||||
if MacOS.runtimemodel == 'macho':
|
||||
return process_common_macho(template, progress, code, rsrcname, destname,
|
||||
is_update, raw, others, filename)
|
||||
if others:
|
||||
raise BuildError, "Extra files only allowed for MachoPython applets"
|
||||
# Create FSSpecs for the various files
|
||||
template_fsr, d1, d2 = Carbon.File.FSResolveAliasFile(template, 1)
|
||||
template = template_fsr.as_pathname()
|
||||
|
||||
# Copy data (not resources, yet) from the template
|
||||
if progress:
|
||||
progress.label("Copy data fork...")
|
||||
progress.set(10)
|
||||
|
||||
if copy_codefragment:
|
||||
tmpl = open(template, "rb")
|
||||
dest = open(destname, "wb")
|
||||
data = tmpl.read()
|
||||
if data:
|
||||
dest.write(data)
|
||||
dest.close()
|
||||
tmpl.close()
|
||||
del dest
|
||||
del tmpl
|
||||
|
||||
# Open the output resource fork
|
||||
|
||||
if progress:
|
||||
progress.label("Copy resources...")
|
||||
progress.set(20)
|
||||
try:
|
||||
output = Res.FSOpenResourceFile(destname, RESOURCE_FORK_NAME, WRITE)
|
||||
except MacOS.Error:
|
||||
destdir, destfile = os.path.split(destname)
|
||||
Res.FSCreateResourceFile(destdir, unicode(destfile), RESOURCE_FORK_NAME)
|
||||
output = Res.FSOpenResourceFile(destname, RESOURCE_FORK_NAME, WRITE)
|
||||
|
||||
# Copy the resources from the target specific resource template, if any
|
||||
typesfound, ownertype = [], None
|
||||
try:
|
||||
input = Res.FSOpenResourceFile(rsrcname, RESOURCE_FORK_NAME, READ)
|
||||
except (MacOS.Error, ValueError):
|
||||
pass
|
||||
if progress:
|
||||
progress.inc(50)
|
||||
else:
|
||||
if is_update:
|
||||
skip_oldfile = ['cfrg']
|
||||
else:
|
||||
skip_oldfile = []
|
||||
typesfound, ownertype = copyres(input, output, skip_oldfile, 0, progress)
|
||||
Res.CloseResFile(input)
|
||||
|
||||
# Check which resource-types we should not copy from the template
|
||||
skiptypes = []
|
||||
if 'vers' in typesfound: skiptypes.append('vers')
|
||||
if 'SIZE' in typesfound: skiptypes.append('SIZE')
|
||||
if 'BNDL' in typesfound: skiptypes = skiptypes + ['BNDL', 'FREF', 'icl4',
|
||||
'icl8', 'ics4', 'ics8', 'ICN#', 'ics#']
|
||||
if not copy_codefragment:
|
||||
skiptypes.append('cfrg')
|
||||
## skipowner = (ownertype <> None)
|
||||
|
||||
# Copy the resources from the template
|
||||
|
||||
input = Res.FSOpenResourceFile(template, RESOURCE_FORK_NAME, READ)
|
||||
dummy, tmplowner = copyres(input, output, skiptypes, 1, progress)
|
||||
|
||||
Res.CloseResFile(input)
|
||||
## if ownertype == None:
|
||||
## raise BuildError, "No owner resource found in either resource file or template"
|
||||
# Make sure we're manipulating the output resource file now
|
||||
|
||||
Res.UseResFile(output)
|
||||
|
||||
if ownertype == None:
|
||||
# No owner resource in the template. We have skipped the
|
||||
# Python owner resource, so we have to add our own. The relevant
|
||||
# bundle stuff is already included in the interpret/applet template.
|
||||
newres = Res.Resource('\0')
|
||||
newres.AddResource(DEFAULT_APPLET_CREATOR, 0, "Owner resource")
|
||||
ownertype = DEFAULT_APPLET_CREATOR
|
||||
|
||||
if code:
|
||||
# Delete any existing 'PYC ' resource named __main__
|
||||
|
||||
try:
|
||||
res = Res.Get1NamedResource(RESTYPE, RESNAME)
|
||||
res.RemoveResource()
|
||||
except Res.Error:
|
||||
pass
|
||||
|
||||
# Create the raw data for the resource from the code object
|
||||
if progress:
|
||||
progress.label("Write PYC resource...")
|
||||
progress.set(120)
|
||||
|
||||
data = marshal.dumps(code)
|
||||
del code
|
||||
data = (MAGIC + '\0\0\0\0') + data
|
||||
|
||||
# Create the resource and write it
|
||||
|
||||
id = 0
|
||||
while id < 128:
|
||||
id = Res.Unique1ID(RESTYPE)
|
||||
res = Res.Resource(data)
|
||||
res.AddResource(RESTYPE, id, RESNAME)
|
||||
attrs = res.GetResAttrs()
|
||||
attrs = attrs | 0x04 # set preload
|
||||
res.SetResAttrs(attrs)
|
||||
res.WriteResource()
|
||||
res.ReleaseResource()
|
||||
|
||||
# Close the output file
|
||||
|
||||
Res.CloseResFile(output)
|
||||
|
||||
# Now set the creator, type and bundle bit of the destination.
|
||||
# Done with FSSpec's, FSRef FInfo isn't good enough yet (2.3a1+)
|
||||
dest_fss = Carbon.File.FSSpec(destname)
|
||||
dest_finfo = dest_fss.FSpGetFInfo()
|
||||
dest_finfo.Creator = ownertype
|
||||
dest_finfo.Type = 'APPL'
|
||||
dest_finfo.Flags = dest_finfo.Flags | Carbon.Files.kHasBundle | Carbon.Files.kIsShared
|
||||
dest_finfo.Flags = dest_finfo.Flags & ~Carbon.Files.kHasBeenInited
|
||||
dest_fss.FSpSetFInfo(dest_finfo)
|
||||
|
||||
macostools.touched(destname)
|
||||
if progress:
|
||||
progress.label("Done.")
|
||||
progress.inc(0)
|
||||
if ownertype == None:
|
||||
# No owner resource in the template. We have skipped the
|
||||
# Python owner resource, so we have to add our own. The relevant
|
||||
# bundle stuff is already included in the interpret/applet template.
|
||||
newres = Res.Resource('\0')
|
||||
newres.AddResource(DEFAULT_APPLET_CREATOR, 0, "Owner resource")
|
||||
ownertype = DEFAULT_APPLET_CREATOR
|
||||
|
||||
if code:
|
||||
# Delete any existing 'PYC ' resource named __main__
|
||||
|
||||
try:
|
||||
res = Res.Get1NamedResource(RESTYPE, RESNAME)
|
||||
res.RemoveResource()
|
||||
except Res.Error:
|
||||
pass
|
||||
|
||||
# Create the raw data for the resource from the code object
|
||||
if progress:
|
||||
progress.label("Write PYC resource...")
|
||||
progress.set(120)
|
||||
|
||||
data = marshal.dumps(code)
|
||||
del code
|
||||
data = (MAGIC + '\0\0\0\0') + data
|
||||
|
||||
# Create the resource and write it
|
||||
|
||||
id = 0
|
||||
while id < 128:
|
||||
id = Res.Unique1ID(RESTYPE)
|
||||
res = Res.Resource(data)
|
||||
res.AddResource(RESTYPE, id, RESNAME)
|
||||
attrs = res.GetResAttrs()
|
||||
attrs = attrs | 0x04 # set preload
|
||||
res.SetResAttrs(attrs)
|
||||
res.WriteResource()
|
||||
res.ReleaseResource()
|
||||
|
||||
# Close the output file
|
||||
|
||||
Res.CloseResFile(output)
|
||||
|
||||
# Now set the creator, type and bundle bit of the destination.
|
||||
# Done with FSSpec's, FSRef FInfo isn't good enough yet (2.3a1+)
|
||||
dest_fss = Carbon.File.FSSpec(destname)
|
||||
dest_finfo = dest_fss.FSpGetFInfo()
|
||||
dest_finfo.Creator = ownertype
|
||||
dest_finfo.Type = 'APPL'
|
||||
dest_finfo.Flags = dest_finfo.Flags | Carbon.Files.kHasBundle | Carbon.Files.kIsShared
|
||||
dest_finfo.Flags = dest_finfo.Flags & ~Carbon.Files.kHasBeenInited
|
||||
dest_fss.FSpSetFInfo(dest_finfo)
|
||||
|
||||
macostools.touched(destname)
|
||||
if progress:
|
||||
progress.label("Done.")
|
||||
progress.inc(0)
|
||||
|
||||
def process_common_macho(template, progress, code, rsrcname, destname, is_update,
|
||||
raw=0, others=[], filename=None):
|
||||
# Check that we have a filename
|
||||
if filename is None:
|
||||
raise BuildError, "Need source filename on MacOSX"
|
||||
# First make sure the name ends in ".app"
|
||||
if destname[-4:] != '.app':
|
||||
destname = destname + '.app'
|
||||
# Now deduce the short name
|
||||
destdir, shortname = os.path.split(destname)
|
||||
if shortname[-4:] == '.app':
|
||||
# Strip the .app suffix
|
||||
shortname = shortname[:-4]
|
||||
# And deduce the .plist and .icns names
|
||||
plistname = None
|
||||
icnsname = None
|
||||
if rsrcname and rsrcname[-5:] == '.rsrc':
|
||||
tmp = rsrcname[:-5]
|
||||
plistname = tmp + '.plist'
|
||||
if os.path.exists(plistname):
|
||||
icnsname = tmp + '.icns'
|
||||
if not os.path.exists(icnsname):
|
||||
icnsname = None
|
||||
else:
|
||||
plistname = None
|
||||
if not os.path.exists(rsrcname):
|
||||
rsrcname = None
|
||||
if progress:
|
||||
progress.label('Creating bundle...')
|
||||
import bundlebuilder
|
||||
builder = bundlebuilder.AppBuilder(verbosity=0)
|
||||
builder.mainprogram = filename
|
||||
builder.builddir = destdir
|
||||
builder.name = shortname
|
||||
if rsrcname:
|
||||
realrsrcname = macresource.resource_pathname(rsrcname)
|
||||
builder.files.append((realrsrcname,
|
||||
os.path.join('Contents/Resources', os.path.basename(rsrcname))))
|
||||
for o in others:
|
||||
if type(o) == str:
|
||||
builder.resources.append(o)
|
||||
else:
|
||||
builder.files.append(o)
|
||||
if plistname:
|
||||
import plistlib
|
||||
builder.plist = plistlib.Plist.fromFile(plistname)
|
||||
if icnsname:
|
||||
builder.iconfile = icnsname
|
||||
if not raw:
|
||||
builder.argv_emulation = 1
|
||||
builder.setup()
|
||||
builder.build()
|
||||
if progress:
|
||||
progress.label('Done.')
|
||||
progress.inc(0)
|
||||
|
||||
## macostools.touched(dest_fss)
|
||||
raw=0, others=[], filename=None):
|
||||
# Check that we have a filename
|
||||
if filename is None:
|
||||
raise BuildError, "Need source filename on MacOSX"
|
||||
# First make sure the name ends in ".app"
|
||||
if destname[-4:] != '.app':
|
||||
destname = destname + '.app'
|
||||
# Now deduce the short name
|
||||
destdir, shortname = os.path.split(destname)
|
||||
if shortname[-4:] == '.app':
|
||||
# Strip the .app suffix
|
||||
shortname = shortname[:-4]
|
||||
# And deduce the .plist and .icns names
|
||||
plistname = None
|
||||
icnsname = None
|
||||
if rsrcname and rsrcname[-5:] == '.rsrc':
|
||||
tmp = rsrcname[:-5]
|
||||
plistname = tmp + '.plist'
|
||||
if os.path.exists(plistname):
|
||||
icnsname = tmp + '.icns'
|
||||
if not os.path.exists(icnsname):
|
||||
icnsname = None
|
||||
else:
|
||||
plistname = None
|
||||
if not os.path.exists(rsrcname):
|
||||
rsrcname = None
|
||||
if progress:
|
||||
progress.label('Creating bundle...')
|
||||
import bundlebuilder
|
||||
builder = bundlebuilder.AppBuilder(verbosity=0)
|
||||
builder.mainprogram = filename
|
||||
builder.builddir = destdir
|
||||
builder.name = shortname
|
||||
if rsrcname:
|
||||
realrsrcname = macresource.resource_pathname(rsrcname)
|
||||
builder.files.append((realrsrcname,
|
||||
os.path.join('Contents/Resources', os.path.basename(rsrcname))))
|
||||
for o in others:
|
||||
if type(o) == str:
|
||||
builder.resources.append(o)
|
||||
else:
|
||||
builder.files.append(o)
|
||||
if plistname:
|
||||
import plistlib
|
||||
builder.plist = plistlib.Plist.fromFile(plistname)
|
||||
if icnsname:
|
||||
builder.iconfile = icnsname
|
||||
if not raw:
|
||||
builder.argv_emulation = 1
|
||||
builder.setup()
|
||||
builder.build()
|
||||
if progress:
|
||||
progress.label('Done.')
|
||||
progress.inc(0)
|
||||
|
||||
## macostools.touched(dest_fss)
|
||||
|
||||
# Copy resources between two resource file descriptors.
|
||||
# skip a resource named '__main__' or (if skipowner is set) with ID zero.
|
||||
# Also skip resources with a type listed in skiptypes.
|
||||
#
|
||||
def copyres(input, output, skiptypes, skipowner, progress=None):
|
||||
ctor = None
|
||||
alltypes = []
|
||||
Res.UseResFile(input)
|
||||
ntypes = Res.Count1Types()
|
||||
progress_type_inc = 50/ntypes
|
||||
for itype in range(1, 1+ntypes):
|
||||
type = Res.Get1IndType(itype)
|
||||
if type in skiptypes:
|
||||
continue
|
||||
alltypes.append(type)
|
||||
nresources = Res.Count1Resources(type)
|
||||
progress_cur_inc = progress_type_inc/nresources
|
||||
for ires in range(1, 1+nresources):
|
||||
res = Res.Get1IndResource(type, ires)
|
||||
id, type, name = res.GetResInfo()
|
||||
lcname = string.lower(name)
|
||||
ctor = None
|
||||
alltypes = []
|
||||
Res.UseResFile(input)
|
||||
ntypes = Res.Count1Types()
|
||||
progress_type_inc = 50/ntypes
|
||||
for itype in range(1, 1+ntypes):
|
||||
type = Res.Get1IndType(itype)
|
||||
if type in skiptypes:
|
||||
continue
|
||||
alltypes.append(type)
|
||||
nresources = Res.Count1Resources(type)
|
||||
progress_cur_inc = progress_type_inc/nresources
|
||||
for ires in range(1, 1+nresources):
|
||||
res = Res.Get1IndResource(type, ires)
|
||||
id, type, name = res.GetResInfo()
|
||||
lcname = string.lower(name)
|
||||
|
||||
if lcname == OWNERNAME and id == 0:
|
||||
if skipowner:
|
||||
continue # Skip this one
|
||||
else:
|
||||
ctor = type
|
||||
size = res.size
|
||||
attrs = res.GetResAttrs()
|
||||
if progress:
|
||||
progress.label("Copy %s %d %s"%(type, id, name))
|
||||
progress.inc(progress_cur_inc)
|
||||
res.LoadResource()
|
||||
res.DetachResource()
|
||||
Res.UseResFile(output)
|
||||
try:
|
||||
res2 = Res.Get1Resource(type, id)
|
||||
except MacOS.Error:
|
||||
res2 = None
|
||||
if res2:
|
||||
if progress:
|
||||
progress.label("Overwrite %s %d %s"%(type, id, name))
|
||||
progress.inc(0)
|
||||
res2.RemoveResource()
|
||||
res.AddResource(type, id, name)
|
||||
res.WriteResource()
|
||||
attrs = attrs | res.GetResAttrs()
|
||||
res.SetResAttrs(attrs)
|
||||
Res.UseResFile(input)
|
||||
return alltypes, ctor
|
||||
if lcname == OWNERNAME and id == 0:
|
||||
if skipowner:
|
||||
continue # Skip this one
|
||||
else:
|
||||
ctor = type
|
||||
size = res.size
|
||||
attrs = res.GetResAttrs()
|
||||
if progress:
|
||||
progress.label("Copy %s %d %s"%(type, id, name))
|
||||
progress.inc(progress_cur_inc)
|
||||
res.LoadResource()
|
||||
res.DetachResource()
|
||||
Res.UseResFile(output)
|
||||
try:
|
||||
res2 = Res.Get1Resource(type, id)
|
||||
except MacOS.Error:
|
||||
res2 = None
|
||||
if res2:
|
||||
if progress:
|
||||
progress.label("Overwrite %s %d %s"%(type, id, name))
|
||||
progress.inc(0)
|
||||
res2.RemoveResource()
|
||||
res.AddResource(type, id, name)
|
||||
res.WriteResource()
|
||||
attrs = attrs | res.GetResAttrs()
|
||||
res.SetResAttrs(attrs)
|
||||
Res.UseResFile(input)
|
||||
return alltypes, ctor
|
||||
|
||||
def copyapptree(srctree, dsttree, exceptlist=[], progress=None):
|
||||
names = []
|
||||
if os.path.exists(dsttree):
|
||||
shutil.rmtree(dsttree)
|
||||
os.mkdir(dsttree)
|
||||
todo = os.listdir(srctree)
|
||||
while todo:
|
||||
this, todo = todo[0], todo[1:]
|
||||
if this in exceptlist:
|
||||
continue
|
||||
thispath = os.path.join(srctree, this)
|
||||
if os.path.isdir(thispath):
|
||||
thiscontent = os.listdir(thispath)
|
||||
for t in thiscontent:
|
||||
todo.append(os.path.join(this, t))
|
||||
names.append(this)
|
||||
for this in names:
|
||||
srcpath = os.path.join(srctree, this)
|
||||
dstpath = os.path.join(dsttree, this)
|
||||
if os.path.isdir(srcpath):
|
||||
os.mkdir(dstpath)
|
||||
elif os.path.islink(srcpath):
|
||||
endpoint = os.readlink(srcpath)
|
||||
os.symlink(endpoint, dstpath)
|
||||
else:
|
||||
if progress:
|
||||
progress.label('Copy '+this)
|
||||
progress.inc(0)
|
||||
shutil.copy2(srcpath, dstpath)
|
||||
|
||||
names = []
|
||||
if os.path.exists(dsttree):
|
||||
shutil.rmtree(dsttree)
|
||||
os.mkdir(dsttree)
|
||||
todo = os.listdir(srctree)
|
||||
while todo:
|
||||
this, todo = todo[0], todo[1:]
|
||||
if this in exceptlist:
|
||||
continue
|
||||
thispath = os.path.join(srctree, this)
|
||||
if os.path.isdir(thispath):
|
||||
thiscontent = os.listdir(thispath)
|
||||
for t in thiscontent:
|
||||
todo.append(os.path.join(this, t))
|
||||
names.append(this)
|
||||
for this in names:
|
||||
srcpath = os.path.join(srctree, this)
|
||||
dstpath = os.path.join(dsttree, this)
|
||||
if os.path.isdir(srcpath):
|
||||
os.mkdir(dstpath)
|
||||
elif os.path.islink(srcpath):
|
||||
endpoint = os.readlink(srcpath)
|
||||
os.symlink(endpoint, dstpath)
|
||||
else:
|
||||
if progress:
|
||||
progress.label('Copy '+this)
|
||||
progress.inc(0)
|
||||
shutil.copy2(srcpath, dstpath)
|
||||
|
||||
def writepycfile(codeobject, cfile):
|
||||
import marshal
|
||||
fc = open(cfile, 'wb')
|
||||
fc.write('\0\0\0\0') # MAGIC placeholder, written later
|
||||
fc.write('\0\0\0\0') # Timestap placeholder, not needed
|
||||
marshal.dump(codeobject, fc)
|
||||
fc.flush()
|
||||
fc.seek(0, 0)
|
||||
fc.write(MAGIC)
|
||||
fc.close()
|
||||
import marshal
|
||||
fc = open(cfile, 'wb')
|
||||
fc.write('\0\0\0\0') # MAGIC placeholder, written later
|
||||
fc.write('\0\0\0\0') # Timestap placeholder, not needed
|
||||
marshal.dump(codeobject, fc)
|
||||
fc.flush()
|
||||
fc.seek(0, 0)
|
||||
fc.write(MAGIC)
|
||||
fc.close()
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -18,167 +18,167 @@ error = "cfm.error"
|
|||
BUFSIZE = 0x80000
|
||||
|
||||
def mergecfmfiles(srclist, dst, architecture = 'fat'):
|
||||
"""Merge all files in srclist into a new file dst.
|
||||
|
||||
If architecture is given, only code fragments of that type will be used:
|
||||
"pwpc" for PPC, "m68k" for cfm68k. This does not work for "classic"
|
||||
68k code, since it does not use code fragments to begin with.
|
||||
If architecture is None, all fragments will be used, enabling FAT binaries.
|
||||
"""
|
||||
|
||||
srclist = list(srclist)
|
||||
for i in range(len(srclist)):
|
||||
srclist[i] = Carbon.File.pathname(srclist[i])
|
||||
dst = Carbon.File.pathname(dst)
|
||||
|
||||
dstfile = open(dst, "wb")
|
||||
rf = Res.FSpOpenResFile(dst, 3)
|
||||
try:
|
||||
dstcfrg = CfrgResource()
|
||||
for src in srclist:
|
||||
srccfrg = CfrgResource(src)
|
||||
for frag in srccfrg.fragments:
|
||||
if frag.architecture == 'pwpc' and architecture == 'm68k':
|
||||
continue
|
||||
if frag.architecture == 'm68k' and architecture == 'pwpc':
|
||||
continue
|
||||
dstcfrg.append(frag)
|
||||
|
||||
frag.copydata(dstfile)
|
||||
|
||||
cfrgres = Res.Resource(dstcfrg.build())
|
||||
Res.UseResFile(rf)
|
||||
cfrgres.AddResource('cfrg', 0, "")
|
||||
finally:
|
||||
dstfile.close()
|
||||
rf = Res.CloseResFile(rf)
|
||||
"""Merge all files in srclist into a new file dst.
|
||||
|
||||
If architecture is given, only code fragments of that type will be used:
|
||||
"pwpc" for PPC, "m68k" for cfm68k. This does not work for "classic"
|
||||
68k code, since it does not use code fragments to begin with.
|
||||
If architecture is None, all fragments will be used, enabling FAT binaries.
|
||||
"""
|
||||
|
||||
srclist = list(srclist)
|
||||
for i in range(len(srclist)):
|
||||
srclist[i] = Carbon.File.pathname(srclist[i])
|
||||
dst = Carbon.File.pathname(dst)
|
||||
|
||||
dstfile = open(dst, "wb")
|
||||
rf = Res.FSpOpenResFile(dst, 3)
|
||||
try:
|
||||
dstcfrg = CfrgResource()
|
||||
for src in srclist:
|
||||
srccfrg = CfrgResource(src)
|
||||
for frag in srccfrg.fragments:
|
||||
if frag.architecture == 'pwpc' and architecture == 'm68k':
|
||||
continue
|
||||
if frag.architecture == 'm68k' and architecture == 'pwpc':
|
||||
continue
|
||||
dstcfrg.append(frag)
|
||||
|
||||
frag.copydata(dstfile)
|
||||
|
||||
cfrgres = Res.Resource(dstcfrg.build())
|
||||
Res.UseResFile(rf)
|
||||
cfrgres.AddResource('cfrg', 0, "")
|
||||
finally:
|
||||
dstfile.close()
|
||||
rf = Res.CloseResFile(rf)
|
||||
|
||||
|
||||
class CfrgResource:
|
||||
|
||||
def __init__(self, path = None):
|
||||
self.version = 1
|
||||
self.fragments = []
|
||||
self.path = path
|
||||
if path is not None and os.path.exists(path):
|
||||
currentresref = Res.CurResFile()
|
||||
resref = Res.FSpOpenResFile(path, 1)
|
||||
Res.UseResFile(resref)
|
||||
try:
|
||||
try:
|
||||
data = Res.Get1Resource('cfrg', 0).data
|
||||
except Res.Error:
|
||||
raise Res.Error, "no 'cfrg' resource found", sys.exc_traceback
|
||||
finally:
|
||||
Res.CloseResFile(resref)
|
||||
Res.UseResFile(currentresref)
|
||||
self.parse(data)
|
||||
if self.version <> 1:
|
||||
raise error, "unknown 'cfrg' resource format"
|
||||
|
||||
def parse(self, data):
|
||||
(res1, res2, self.version,
|
||||
res3, res4, res5, res6,
|
||||
self.memberCount) = struct.unpack("8l", data[:32])
|
||||
data = data[32:]
|
||||
while data:
|
||||
frag = FragmentDescriptor(self.path, data)
|
||||
data = data[frag.memberSize:]
|
||||
self.fragments.append(frag)
|
||||
|
||||
def build(self):
|
||||
self.memberCount = len(self.fragments)
|
||||
data = struct.pack("8l", 0, 0, self.version, 0, 0, 0, 0, self.memberCount)
|
||||
for frag in self.fragments:
|
||||
data = data + frag.build()
|
||||
return data
|
||||
|
||||
def append(self, frag):
|
||||
self.fragments.append(frag)
|
||||
|
||||
def __init__(self, path = None):
|
||||
self.version = 1
|
||||
self.fragments = []
|
||||
self.path = path
|
||||
if path is not None and os.path.exists(path):
|
||||
currentresref = Res.CurResFile()
|
||||
resref = Res.FSpOpenResFile(path, 1)
|
||||
Res.UseResFile(resref)
|
||||
try:
|
||||
try:
|
||||
data = Res.Get1Resource('cfrg', 0).data
|
||||
except Res.Error:
|
||||
raise Res.Error, "no 'cfrg' resource found", sys.exc_traceback
|
||||
finally:
|
||||
Res.CloseResFile(resref)
|
||||
Res.UseResFile(currentresref)
|
||||
self.parse(data)
|
||||
if self.version <> 1:
|
||||
raise error, "unknown 'cfrg' resource format"
|
||||
|
||||
def parse(self, data):
|
||||
(res1, res2, self.version,
|
||||
res3, res4, res5, res6,
|
||||
self.memberCount) = struct.unpack("8l", data[:32])
|
||||
data = data[32:]
|
||||
while data:
|
||||
frag = FragmentDescriptor(self.path, data)
|
||||
data = data[frag.memberSize:]
|
||||
self.fragments.append(frag)
|
||||
|
||||
def build(self):
|
||||
self.memberCount = len(self.fragments)
|
||||
data = struct.pack("8l", 0, 0, self.version, 0, 0, 0, 0, self.memberCount)
|
||||
for frag in self.fragments:
|
||||
data = data + frag.build()
|
||||
return data
|
||||
|
||||
def append(self, frag):
|
||||
self.fragments.append(frag)
|
||||
|
||||
|
||||
class FragmentDescriptor:
|
||||
|
||||
def __init__(self, path, data = None):
|
||||
self.path = path
|
||||
if data is not None:
|
||||
self.parse(data)
|
||||
|
||||
def parse(self, data):
|
||||
self.architecture = data[:4]
|
||||
( self.updatelevel,
|
||||
self.currentVersion,
|
||||
self.oldDefVersion,
|
||||
self.stacksize,
|
||||
self.applibdir,
|
||||
self.fragtype,
|
||||
self.where,
|
||||
self.offset,
|
||||
self.length,
|
||||
self.res1, self.res2,
|
||||
self.memberSize,) = struct.unpack("4lhBB4lh", data[4:42])
|
||||
pname = data[42:self.memberSize]
|
||||
self.name = pname[1:1+ord(pname[0])]
|
||||
|
||||
def build(self):
|
||||
data = self.architecture
|
||||
data = data + struct.pack("4lhBB4l",
|
||||
self.updatelevel,
|
||||
self.currentVersion,
|
||||
self.oldDefVersion,
|
||||
self.stacksize,
|
||||
self.applibdir,
|
||||
self.fragtype,
|
||||
self.where,
|
||||
self.offset,
|
||||
self.length,
|
||||
self.res1, self.res2)
|
||||
self.memberSize = len(data) + 2 + 1 + len(self.name)
|
||||
# pad to 4 byte boundaries
|
||||
if self.memberSize % 4:
|
||||
self.memberSize = self.memberSize + 4 - (self.memberSize % 4)
|
||||
data = data + struct.pack("hb", self.memberSize, len(self.name))
|
||||
data = data + self.name
|
||||
data = data + '\000' * (self.memberSize - len(data))
|
||||
return data
|
||||
|
||||
def getfragment(self):
|
||||
if self.where <> 1:
|
||||
raise error, "can't read fragment, unsupported location"
|
||||
f = open(self.path, "rb")
|
||||
f.seek(self.offset)
|
||||
if self.length:
|
||||
frag = f.read(self.length)
|
||||
else:
|
||||
frag = f.read()
|
||||
f.close()
|
||||
return frag
|
||||
|
||||
def copydata(self, outfile):
|
||||
if self.where <> 1:
|
||||
raise error, "can't read fragment, unsupported location"
|
||||
infile = open(self.path, "rb")
|
||||
if self.length == 0:
|
||||
infile.seek(0, 2)
|
||||
self.length = infile.tell()
|
||||
|
||||
# Position input file and record new offset from output file
|
||||
infile.seek(self.offset)
|
||||
|
||||
# pad to 16 byte boundaries
|
||||
offset = outfile.tell()
|
||||
if offset % 16:
|
||||
offset = offset + 16 - (offset % 16)
|
||||
outfile.seek(offset)
|
||||
self.offset = offset
|
||||
|
||||
l = self.length
|
||||
while l:
|
||||
if l > BUFSIZE:
|
||||
outfile.write(infile.read(BUFSIZE))
|
||||
l = l - BUFSIZE
|
||||
else:
|
||||
outfile.write(infile.read(l))
|
||||
l = 0
|
||||
infile.close()
|
||||
|
||||
def __init__(self, path, data = None):
|
||||
self.path = path
|
||||
if data is not None:
|
||||
self.parse(data)
|
||||
|
||||
def parse(self, data):
|
||||
self.architecture = data[:4]
|
||||
( self.updatelevel,
|
||||
self.currentVersion,
|
||||
self.oldDefVersion,
|
||||
self.stacksize,
|
||||
self.applibdir,
|
||||
self.fragtype,
|
||||
self.where,
|
||||
self.offset,
|
||||
self.length,
|
||||
self.res1, self.res2,
|
||||
self.memberSize,) = struct.unpack("4lhBB4lh", data[4:42])
|
||||
pname = data[42:self.memberSize]
|
||||
self.name = pname[1:1+ord(pname[0])]
|
||||
|
||||
def build(self):
|
||||
data = self.architecture
|
||||
data = data + struct.pack("4lhBB4l",
|
||||
self.updatelevel,
|
||||
self.currentVersion,
|
||||
self.oldDefVersion,
|
||||
self.stacksize,
|
||||
self.applibdir,
|
||||
self.fragtype,
|
||||
self.where,
|
||||
self.offset,
|
||||
self.length,
|
||||
self.res1, self.res2)
|
||||
self.memberSize = len(data) + 2 + 1 + len(self.name)
|
||||
# pad to 4 byte boundaries
|
||||
if self.memberSize % 4:
|
||||
self.memberSize = self.memberSize + 4 - (self.memberSize % 4)
|
||||
data = data + struct.pack("hb", self.memberSize, len(self.name))
|
||||
data = data + self.name
|
||||
data = data + '\000' * (self.memberSize - len(data))
|
||||
return data
|
||||
|
||||
def getfragment(self):
|
||||
if self.where <> 1:
|
||||
raise error, "can't read fragment, unsupported location"
|
||||
f = open(self.path, "rb")
|
||||
f.seek(self.offset)
|
||||
if self.length:
|
||||
frag = f.read(self.length)
|
||||
else:
|
||||
frag = f.read()
|
||||
f.close()
|
||||
return frag
|
||||
|
||||
def copydata(self, outfile):
|
||||
if self.where <> 1:
|
||||
raise error, "can't read fragment, unsupported location"
|
||||
infile = open(self.path, "rb")
|
||||
if self.length == 0:
|
||||
infile.seek(0, 2)
|
||||
self.length = infile.tell()
|
||||
|
||||
# Position input file and record new offset from output file
|
||||
infile.seek(self.offset)
|
||||
|
||||
# pad to 16 byte boundaries
|
||||
offset = outfile.tell()
|
||||
if offset % 16:
|
||||
offset = offset + 16 - (offset % 16)
|
||||
outfile.seek(offset)
|
||||
self.offset = offset
|
||||
|
||||
l = self.length
|
||||
while l:
|
||||
if l > BUFSIZE:
|
||||
outfile.write(infile.read(BUFSIZE))
|
||||
l = l - BUFSIZE
|
||||
else:
|
||||
outfile.write(infile.read(l))
|
||||
l = 0
|
||||
infile.close()
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -11,16 +11,16 @@ import macostools
|
|||
error=icglue.error
|
||||
|
||||
# From ictypes.h:
|
||||
icPrefNotFoundErr = -666 # preference not found (duh!)
|
||||
icPermErr = -667 # cannot set preference
|
||||
icPrefDataErr = -668 # problem with preference data
|
||||
icInternalErr = -669 # hmm, this is not good
|
||||
icTruncatedErr = -670 # more data was present than was returned
|
||||
icNoMoreWritersErr = -671 # you cannot begin a write session because someone else is already doing it */
|
||||
icNothingToOverrideErr = -672 # no component for the override component to capture
|
||||
icNoURLErr = -673 # no URL found
|
||||
icConfigNotFoundErr = -674 # no configuration was found
|
||||
icConfigInappropriateErr = -675 # incorrect manufacturer code
|
||||
icPrefNotFoundErr = -666 # preference not found (duh!)
|
||||
icPermErr = -667 # cannot set preference
|
||||
icPrefDataErr = -668 # problem with preference data
|
||||
icInternalErr = -669 # hmm, this is not good
|
||||
icTruncatedErr = -670 # more data was present than was returned
|
||||
icNoMoreWritersErr = -671 # you cannot begin a write session because someone else is already doing it */
|
||||
icNothingToOverrideErr = -672 # no component for the override component to capture
|
||||
icNoURLErr = -673 # no URL found
|
||||
icConfigNotFoundErr = -674 # no configuration was found
|
||||
icConfigInappropriateErr = -675 # incorrect manufacturer code
|
||||
|
||||
ICattr_no_change = -1
|
||||
|
||||
|
@ -30,240 +30,240 @@ icReadWritePerm = 2
|
|||
# End of ictypes.h
|
||||
|
||||
class ICOpaqueData:
|
||||
"""An unparseable IC entry"""
|
||||
def __init__(self, data):
|
||||
self.data = data
|
||||
"""An unparseable IC entry"""
|
||||
def __init__(self, data):
|
||||
self.data = data
|
||||
|
||||
def __repr__(self):
|
||||
return "ICOpaqueData(%s)"%`self.data`
|
||||
def __repr__(self):
|
||||
return "ICOpaqueData(%s)"%`self.data`
|
||||
|
||||
_ICOpaqueDataType=type(ICOpaqueData(''))
|
||||
|
||||
|
||||
def _decode_default(data, key):
|
||||
if len(data) == 0:
|
||||
return data
|
||||
if ord(data[0]) == len(data)-1:
|
||||
# Assume Pstring
|
||||
return data[1:]
|
||||
return ICOpaqueData(data)
|
||||
|
||||
|
||||
if len(data) == 0:
|
||||
return data
|
||||
if ord(data[0]) == len(data)-1:
|
||||
# Assume Pstring
|
||||
return data[1:]
|
||||
return ICOpaqueData(data)
|
||||
|
||||
|
||||
def _decode_multistr(data, key):
|
||||
numstr = ord(data[0]) << 8 | ord(data[1])
|
||||
rv = []
|
||||
ptr = 2
|
||||
for i in range(numstr):
|
||||
strlen = ord(data[ptr])
|
||||
str = data[ptr+1:ptr+strlen+1]
|
||||
rv.append(str)
|
||||
ptr = ptr + strlen + 1
|
||||
return rv
|
||||
|
||||
numstr = ord(data[0]) << 8 | ord(data[1])
|
||||
rv = []
|
||||
ptr = 2
|
||||
for i in range(numstr):
|
||||
strlen = ord(data[ptr])
|
||||
str = data[ptr+1:ptr+strlen+1]
|
||||
rv.append(str)
|
||||
ptr = ptr + strlen + 1
|
||||
return rv
|
||||
|
||||
def _decode_fontrecord(data, key):
|
||||
size = ord(data[0]) << 8 | ord(data[1])
|
||||
face = ord(data[2])
|
||||
namelen = ord(data[4])
|
||||
return size, face, data[5:5+namelen]
|
||||
|
||||
size = ord(data[0]) << 8 | ord(data[1])
|
||||
face = ord(data[2])
|
||||
namelen = ord(data[4])
|
||||
return size, face, data[5:5+namelen]
|
||||
|
||||
def _decode_boolean(data, key):
|
||||
return ord(data[0])
|
||||
|
||||
return ord(data[0])
|
||||
|
||||
def _decode_text(data, key):
|
||||
return data
|
||||
|
||||
return data
|
||||
|
||||
def _decode_charset(data, key):
|
||||
return data[:256], data[256:]
|
||||
|
||||
return data[:256], data[256:]
|
||||
|
||||
def _decode_appspec(data, key):
|
||||
namelen = ord(data[4])
|
||||
return data[0:4], data[5:5+namelen]
|
||||
namelen = ord(data[4])
|
||||
return data[0:4], data[5:5+namelen]
|
||||
|
||||
def _code_default(data, key):
|
||||
return chr(len(data)) + data
|
||||
|
||||
return chr(len(data)) + data
|
||||
|
||||
def _code_multistr(data, key):
|
||||
numstr = len(data)
|
||||
rv = chr((numstr>>8) & 0xff) + chr(numstr & 0xff)
|
||||
for i in data:
|
||||
rv = rv + _code_default(i)
|
||||
return rv
|
||||
|
||||
numstr = len(data)
|
||||
rv = chr((numstr>>8) & 0xff) + chr(numstr & 0xff)
|
||||
for i in data:
|
||||
rv = rv + _code_default(i)
|
||||
return rv
|
||||
|
||||
def _code_fontrecord(data, key):
|
||||
size, face, name = data
|
||||
return chr((size>>8) & 0xff) + chr(size & 0xff) + chr(face & 0xff) + \
|
||||
chr(0) + _code_default(name)
|
||||
|
||||
size, face, name = data
|
||||
return chr((size>>8) & 0xff) + chr(size & 0xff) + chr(face & 0xff) + \
|
||||
chr(0) + _code_default(name)
|
||||
|
||||
def _code_boolean(data, key):
|
||||
print 'XXXX boolean:', `data`
|
||||
return chr(data)
|
||||
|
||||
print 'XXXX boolean:', `data`
|
||||
return chr(data)
|
||||
|
||||
def _code_text(data, key):
|
||||
return data
|
||||
|
||||
return data
|
||||
|
||||
def _code_charset(data, key):
|
||||
return data[0] + data[1]
|
||||
|
||||
return data[0] + data[1]
|
||||
|
||||
def _code_appspec(data, key):
|
||||
return data[0] + _code_default(data[1])
|
||||
|
||||
return data[0] + _code_default(data[1])
|
||||
|
||||
_decoder_table = {
|
||||
"ArchieAll" : (_decode_multistr , _code_multistr),
|
||||
"UMichAll" : (_decode_multistr , _code_multistr),
|
||||
"InfoMacAll" : (_decode_multistr , _code_multistr),
|
||||
"ListFont" : (_decode_fontrecord , _code_fontrecord),
|
||||
"ScreenFont" : (_decode_fontrecord , _code_fontrecord),
|
||||
"PrinterFont" : (_decode_fontrecord , _code_fontrecord),
|
||||
# "DownloadFolder" : (_decode_filespec , _code_filespec),
|
||||
"Signature": (_decode_text , _code_text),
|
||||
"Plan" : (_decode_text , _code_text),
|
||||
"MailHeaders" : (_decode_text , _code_text),
|
||||
"NewsHeaders" : (_decode_text , _code_text),
|
||||
# "Mapping"
|
||||
"CharacterSet" : (_decode_charset , _code_charset),
|
||||
"Helper\245" : (_decode_appspec , _code_appspec),
|
||||
# "Services" : (_decode_services, ????),
|
||||
"NewMailFlashIcon" : (_decode_boolean , _code_boolean),
|
||||
"NewMailDialog" : (_decode_boolean , _code_boolean),
|
||||
"NewMailPlaySound" : (_decode_boolean , _code_boolean),
|
||||
# "WebBackgroundColor" : _decode_color,
|
||||
"NoProxyDomains" : (_decode_multistr , _code_multistr),
|
||||
"UseHTTPProxy" : (_decode_boolean , _code_boolean),
|
||||
"UseGopherProxy": (_decode_boolean , _code_boolean),
|
||||
"UseFTPProxy" : (_decode_boolean , _code_boolean),
|
||||
"UsePassiveFTP" : (_decode_boolean , _code_boolean),
|
||||
"ArchieAll" : (_decode_multistr , _code_multistr),
|
||||
"UMichAll" : (_decode_multistr , _code_multistr),
|
||||
"InfoMacAll" : (_decode_multistr , _code_multistr),
|
||||
"ListFont" : (_decode_fontrecord , _code_fontrecord),
|
||||
"ScreenFont" : (_decode_fontrecord , _code_fontrecord),
|
||||
"PrinterFont" : (_decode_fontrecord , _code_fontrecord),
|
||||
# "DownloadFolder" : (_decode_filespec , _code_filespec),
|
||||
"Signature": (_decode_text , _code_text),
|
||||
"Plan" : (_decode_text , _code_text),
|
||||
"MailHeaders" : (_decode_text , _code_text),
|
||||
"NewsHeaders" : (_decode_text , _code_text),
|
||||
# "Mapping"
|
||||
"CharacterSet" : (_decode_charset , _code_charset),
|
||||
"Helper\245" : (_decode_appspec , _code_appspec),
|
||||
# "Services" : (_decode_services, ????),
|
||||
"NewMailFlashIcon" : (_decode_boolean , _code_boolean),
|
||||
"NewMailDialog" : (_decode_boolean , _code_boolean),
|
||||
"NewMailPlaySound" : (_decode_boolean , _code_boolean),
|
||||
# "WebBackgroundColor" : _decode_color,
|
||||
"NoProxyDomains" : (_decode_multistr , _code_multistr),
|
||||
"UseHTTPProxy" : (_decode_boolean , _code_boolean),
|
||||
"UseGopherProxy": (_decode_boolean , _code_boolean),
|
||||
"UseFTPProxy" : (_decode_boolean , _code_boolean),
|
||||
"UsePassiveFTP" : (_decode_boolean , _code_boolean),
|
||||
}
|
||||
|
||||
def _decode(data, key):
|
||||
if '\245' in key:
|
||||
key2 = key[:string.index(key, '\245')+1]
|
||||
else:
|
||||
key2 = key
|
||||
if _decoder_table.has_key(key2):
|
||||
decoder = _decoder_table[key2][0]
|
||||
else:
|
||||
decoder = _decode_default
|
||||
return decoder(data, key)
|
||||
if '\245' in key:
|
||||
key2 = key[:string.index(key, '\245')+1]
|
||||
else:
|
||||
key2 = key
|
||||
if _decoder_table.has_key(key2):
|
||||
decoder = _decoder_table[key2][0]
|
||||
else:
|
||||
decoder = _decode_default
|
||||
return decoder(data, key)
|
||||
|
||||
def _code(data, key):
|
||||
if type(data) == _ICOpaqueDataType:
|
||||
return data.data
|
||||
if '\245' in key:
|
||||
key2 = key[:string.index(key, '\245')+1]
|
||||
else:
|
||||
key2 = key
|
||||
if _decoder_table.has_key(key2):
|
||||
coder = _decoder_table[key2][1]
|
||||
else:
|
||||
coder = _code_default
|
||||
return coder(data, key)
|
||||
|
||||
if type(data) == _ICOpaqueDataType:
|
||||
return data.data
|
||||
if '\245' in key:
|
||||
key2 = key[:string.index(key, '\245')+1]
|
||||
else:
|
||||
key2 = key
|
||||
if _decoder_table.has_key(key2):
|
||||
coder = _decoder_table[key2][1]
|
||||
else:
|
||||
coder = _code_default
|
||||
return coder(data, key)
|
||||
|
||||
class IC:
|
||||
def __init__(self, signature='Pyth', ic=None):
|
||||
if ic:
|
||||
self.ic = ic
|
||||
else:
|
||||
self.ic = icglue.ICStart(signature)
|
||||
if hasattr(self.ic, 'ICFindConfigFile'):
|
||||
self.ic.ICFindConfigFile()
|
||||
self.h = Res.Resource('')
|
||||
|
||||
def keys(self):
|
||||
rv = []
|
||||
self.ic.ICBegin(icReadOnlyPerm)
|
||||
num = self.ic.ICCountPref()
|
||||
for i in range(num):
|
||||
rv.append(self.ic.ICGetIndPref(i+1))
|
||||
self.ic.ICEnd()
|
||||
return rv
|
||||
|
||||
def has_key(self, key):
|
||||
return self.__contains__(key)
|
||||
|
||||
def __contains__(self, key):
|
||||
try:
|
||||
dummy = self.ic.ICFindPrefHandle(key, self.h)
|
||||
except icglue.error:
|
||||
return 0
|
||||
return 1
|
||||
|
||||
def __getitem__(self, key):
|
||||
attr = self.ic.ICFindPrefHandle(key, self.h)
|
||||
return _decode(self.h.data, key)
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
value = _code(value, key)
|
||||
self.ic.ICSetPref(key, ICattr_no_change, value)
|
||||
|
||||
def launchurl(self, url, hint=""):
|
||||
# Work around a bug in ICLaunchURL: file:/foo does
|
||||
# not work but file:///foo does.
|
||||
if url[:6] == 'file:/' and url[6] != '/':
|
||||
url = 'file:///' + url[6:]
|
||||
self.ic.ICLaunchURL(hint, url, 0, len(url))
|
||||
|
||||
def parseurl(self, data, start=None, end=None, hint=""):
|
||||
if start == None:
|
||||
selStart = 0
|
||||
selEnd = len(data)
|
||||
else:
|
||||
selStart = selEnd = start
|
||||
if end != None:
|
||||
selEnd = end
|
||||
selStart, selEnd = self.ic.ICParseURL(hint, data, selStart, selEnd, self.h)
|
||||
return self.h.data, selStart, selEnd
|
||||
|
||||
def mapfile(self, file):
|
||||
if type(file) != type(''):
|
||||
file = file.as_tuple()[2]
|
||||
return self.ic.ICMapFilename(file)
|
||||
|
||||
def maptypecreator(self, type, creator, filename=""):
|
||||
return self.ic.ICMapTypeCreator(type, creator, filename)
|
||||
|
||||
def settypecreator(self, file):
|
||||
file = Carbon.File.pathname(file)
|
||||
record = self.mapfile(os.path.split(file)[1])
|
||||
MacOS.SetCreatorAndType(file, record[2], record[1])
|
||||
macostools.touched(fss)
|
||||
|
||||
def __init__(self, signature='Pyth', ic=None):
|
||||
if ic:
|
||||
self.ic = ic
|
||||
else:
|
||||
self.ic = icglue.ICStart(signature)
|
||||
if hasattr(self.ic, 'ICFindConfigFile'):
|
||||
self.ic.ICFindConfigFile()
|
||||
self.h = Res.Resource('')
|
||||
|
||||
def keys(self):
|
||||
rv = []
|
||||
self.ic.ICBegin(icReadOnlyPerm)
|
||||
num = self.ic.ICCountPref()
|
||||
for i in range(num):
|
||||
rv.append(self.ic.ICGetIndPref(i+1))
|
||||
self.ic.ICEnd()
|
||||
return rv
|
||||
|
||||
def has_key(self, key):
|
||||
return self.__contains__(key)
|
||||
|
||||
def __contains__(self, key):
|
||||
try:
|
||||
dummy = self.ic.ICFindPrefHandle(key, self.h)
|
||||
except icglue.error:
|
||||
return 0
|
||||
return 1
|
||||
|
||||
def __getitem__(self, key):
|
||||
attr = self.ic.ICFindPrefHandle(key, self.h)
|
||||
return _decode(self.h.data, key)
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
value = _code(value, key)
|
||||
self.ic.ICSetPref(key, ICattr_no_change, value)
|
||||
|
||||
def launchurl(self, url, hint=""):
|
||||
# Work around a bug in ICLaunchURL: file:/foo does
|
||||
# not work but file:///foo does.
|
||||
if url[:6] == 'file:/' and url[6] != '/':
|
||||
url = 'file:///' + url[6:]
|
||||
self.ic.ICLaunchURL(hint, url, 0, len(url))
|
||||
|
||||
def parseurl(self, data, start=None, end=None, hint=""):
|
||||
if start == None:
|
||||
selStart = 0
|
||||
selEnd = len(data)
|
||||
else:
|
||||
selStart = selEnd = start
|
||||
if end != None:
|
||||
selEnd = end
|
||||
selStart, selEnd = self.ic.ICParseURL(hint, data, selStart, selEnd, self.h)
|
||||
return self.h.data, selStart, selEnd
|
||||
|
||||
def mapfile(self, file):
|
||||
if type(file) != type(''):
|
||||
file = file.as_tuple()[2]
|
||||
return self.ic.ICMapFilename(file)
|
||||
|
||||
def maptypecreator(self, type, creator, filename=""):
|
||||
return self.ic.ICMapTypeCreator(type, creator, filename)
|
||||
|
||||
def settypecreator(self, file):
|
||||
file = Carbon.File.pathname(file)
|
||||
record = self.mapfile(os.path.split(file)[1])
|
||||
MacOS.SetCreatorAndType(file, record[2], record[1])
|
||||
macostools.touched(fss)
|
||||
|
||||
# Convenience routines
|
||||
_dft_ic = None
|
||||
|
||||
def launchurl(url, hint=""):
|
||||
global _dft_ic
|
||||
if _dft_ic == None: _dft_ic = IC()
|
||||
return _dft_ic.launchurl(url, hint)
|
||||
|
||||
global _dft_ic
|
||||
if _dft_ic == None: _dft_ic = IC()
|
||||
return _dft_ic.launchurl(url, hint)
|
||||
|
||||
def parseurl(data, start=None, end=None, hint=""):
|
||||
global _dft_ic
|
||||
if _dft_ic == None: _dft_ic = IC()
|
||||
return _dft_ic.parseurl(data, start, end, hint)
|
||||
|
||||
global _dft_ic
|
||||
if _dft_ic == None: _dft_ic = IC()
|
||||
return _dft_ic.parseurl(data, start, end, hint)
|
||||
|
||||
def mapfile(filename):
|
||||
global _dft_ic
|
||||
if _dft_ic == None: _dft_ic = IC()
|
||||
return _dft_ic.mapfile(filename)
|
||||
|
||||
global _dft_ic
|
||||
if _dft_ic == None: _dft_ic = IC()
|
||||
return _dft_ic.mapfile(filename)
|
||||
|
||||
def maptypecreator(type, creator, filename=""):
|
||||
global _dft_ic
|
||||
if _dft_ic == None: _dft_ic = IC()
|
||||
return _dft_ic.maptypecreator(type, creator, filename)
|
||||
|
||||
global _dft_ic
|
||||
if _dft_ic == None: _dft_ic = IC()
|
||||
return _dft_ic.maptypecreator(type, creator, filename)
|
||||
|
||||
def settypecreator(file):
|
||||
global _dft_ic
|
||||
if _dft_ic == None: _dft_ic = IC()
|
||||
return _dft_ic.settypecreator(file)
|
||||
|
||||
global _dft_ic
|
||||
if _dft_ic == None: _dft_ic = IC()
|
||||
return _dft_ic.settypecreator(file)
|
||||
|
||||
def _test():
|
||||
ic = IC()
|
||||
for k in ic.keys():
|
||||
try:
|
||||
v = ic[k]
|
||||
except error:
|
||||
v = '????'
|
||||
print k, '\t', v
|
||||
sys.exit(1)
|
||||
|
||||
ic = IC()
|
||||
for k in ic.keys():
|
||||
try:
|
||||
v = ic[k]
|
||||
except error:
|
||||
v = '????'
|
||||
print k, '\t', v
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
_test()
|
||||
|
||||
_test()
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -28,25 +28,25 @@ smAllScripts = -3
|
|||
# Find the epoch conversion for file dates in a way that works on OS9 and OSX
|
||||
import time
|
||||
if time.gmtime(0)[0] == 1970:
|
||||
_EPOCHCONVERT = -((1970-1904)*365 + 17) * (24*60*60) + 0x100000000L
|
||||
def _utc2time(utc):
|
||||
t = utc[1] + _EPOCHCONVERT
|
||||
return int(t)
|
||||
def _time2utc(t):
|
||||
t = int(t) - _EPOCHCONVERT
|
||||
if t < -0x7fffffff:
|
||||
t = t + 0x10000000L
|
||||
return (0, int(t), 0)
|
||||
_EPOCHCONVERT = -((1970-1904)*365 + 17) * (24*60*60) + 0x100000000L
|
||||
def _utc2time(utc):
|
||||
t = utc[1] + _EPOCHCONVERT
|
||||
return int(t)
|
||||
def _time2utc(t):
|
||||
t = int(t) - _EPOCHCONVERT
|
||||
if t < -0x7fffffff:
|
||||
t = t + 0x10000000L
|
||||
return (0, int(t), 0)
|
||||
else:
|
||||
def _utc2time(utc):
|
||||
t = utc[1]
|
||||
if t < 0:
|
||||
t = t + 0x100000000L
|
||||
return t
|
||||
def _time2utc(t):
|
||||
if t > 0x7fffffff:
|
||||
t = t - 0x100000000L
|
||||
return (0, int(t), 0)
|
||||
def _utc2time(utc):
|
||||
t = utc[1]
|
||||
if t < 0:
|
||||
t = t + 0x100000000L
|
||||
return t
|
||||
def _time2utc(t):
|
||||
if t > 0x7fffffff:
|
||||
t = t - 0x100000000L
|
||||
return (0, int(t), 0)
|
||||
|
||||
# The old name of the error object:
|
||||
error = Carbon.File.Error
|
||||
|
@ -56,60 +56,60 @@ error = Carbon.File.Error
|
|||
# of the method names are subtly different.
|
||||
#
|
||||
class FSSpec(Carbon.File.FSSpec):
|
||||
def as_fsref(self):
|
||||
return FSRef(self)
|
||||
|
||||
def NewAlias(self, src=None):
|
||||
return Alias(Carbon.File.NewAlias(src, self))
|
||||
|
||||
def GetCreatorType(self):
|
||||
finfo = self.FSpGetFInfo()
|
||||
return finfo.Creator, finfo.Type
|
||||
|
||||
def SetCreatorType(self, ctor, tp):
|
||||
finfo = self.FSpGetFInfo()
|
||||
finfo.Creator = ctor
|
||||
finfo.Type = tp
|
||||
self.FSpSetFInfo(finfo)
|
||||
|
||||
def GetFInfo(self):
|
||||
return self.FSpGetFInfo()
|
||||
|
||||
def SetFInfo(self, info):
|
||||
return self.FSpSetFInfo(info)
|
||||
|
||||
def GetDates(self):
|
||||
catInfoFlags = kFSCatInfoCreateDate|kFSCatInfoContentMod|kFSCatInfoBackupDate
|
||||
catinfo, d1, d2, d3 = FSRef(self).FSGetCatalogInfo(catInfoFlags)
|
||||
cdate = catinfo.createDate
|
||||
mdate = catinfo.contentModDate
|
||||
bdate = catinfo.backupDate
|
||||
return _utc2time(cdate), _utc2time(mdate), _utc2time(bdate)
|
||||
|
||||
def SetDates(self, cdate, mdate, bdate):
|
||||
catInfoFlags = kFSCatInfoCreateDate|kFSCatInfoContentMod|kFSCatInfoBackupDate
|
||||
catinfo = Carbon.File.FSCatalogInfo(
|
||||
createDate = _time2utc(cdate),
|
||||
contentModDate = _time2utc(mdate),
|
||||
backupDate = _time2utc(bdate))
|
||||
FSRef(self).FSSetCatalogInfo(catInfoFlags, catinfo)
|
||||
|
||||
def as_fsref(self):
|
||||
return FSRef(self)
|
||||
|
||||
def NewAlias(self, src=None):
|
||||
return Alias(Carbon.File.NewAlias(src, self))
|
||||
|
||||
def GetCreatorType(self):
|
||||
finfo = self.FSpGetFInfo()
|
||||
return finfo.Creator, finfo.Type
|
||||
|
||||
def SetCreatorType(self, ctor, tp):
|
||||
finfo = self.FSpGetFInfo()
|
||||
finfo.Creator = ctor
|
||||
finfo.Type = tp
|
||||
self.FSpSetFInfo(finfo)
|
||||
|
||||
def GetFInfo(self):
|
||||
return self.FSpGetFInfo()
|
||||
|
||||
def SetFInfo(self, info):
|
||||
return self.FSpSetFInfo(info)
|
||||
|
||||
def GetDates(self):
|
||||
catInfoFlags = kFSCatInfoCreateDate|kFSCatInfoContentMod|kFSCatInfoBackupDate
|
||||
catinfo, d1, d2, d3 = FSRef(self).FSGetCatalogInfo(catInfoFlags)
|
||||
cdate = catinfo.createDate
|
||||
mdate = catinfo.contentModDate
|
||||
bdate = catinfo.backupDate
|
||||
return _utc2time(cdate), _utc2time(mdate), _utc2time(bdate)
|
||||
|
||||
def SetDates(self, cdate, mdate, bdate):
|
||||
catInfoFlags = kFSCatInfoCreateDate|kFSCatInfoContentMod|kFSCatInfoBackupDate
|
||||
catinfo = Carbon.File.FSCatalogInfo(
|
||||
createDate = _time2utc(cdate),
|
||||
contentModDate = _time2utc(mdate),
|
||||
backupDate = _time2utc(bdate))
|
||||
FSRef(self).FSSetCatalogInfo(catInfoFlags, catinfo)
|
||||
|
||||
class FSRef(Carbon.File.FSRef):
|
||||
def as_fsspec(self):
|
||||
return FSSpec(self)
|
||||
|
||||
def as_fsspec(self):
|
||||
return FSSpec(self)
|
||||
|
||||
class Alias(Carbon.File.Alias):
|
||||
|
||||
def GetInfo(self, index):
|
||||
return self.GetAliasInfo(index)
|
||||
|
||||
def Update(self, *args):
|
||||
pass # print "Alias.Update not yet implemented"
|
||||
|
||||
def Resolve(self, src=None):
|
||||
fss, changed = self.ResolveAlias(src)
|
||||
return FSSpec(fss), changed
|
||||
|
||||
def GetInfo(self, index):
|
||||
return self.GetAliasInfo(index)
|
||||
|
||||
def Update(self, *args):
|
||||
pass # print "Alias.Update not yet implemented"
|
||||
|
||||
def Resolve(self, src=None):
|
||||
fss, changed = self.ResolveAlias(src)
|
||||
return FSSpec(fss), changed
|
||||
|
||||
from Carbon.File import FInfo
|
||||
|
||||
# Backward-compatible type names:
|
||||
|
@ -120,21 +120,21 @@ FInfoType = FInfo
|
|||
|
||||
# Global functions:
|
||||
def ResolveAliasFile(fss, chain=1):
|
||||
fss, isdir, isalias = Carbon.File.ResolveAliasFile(fss, chain)
|
||||
return FSSpec(fss), isdir, isalias
|
||||
|
||||
fss, isdir, isalias = Carbon.File.ResolveAliasFile(fss, chain)
|
||||
return FSSpec(fss), isdir, isalias
|
||||
|
||||
def RawFSSpec(data):
|
||||
return FSSpec(rawdata=data)
|
||||
|
||||
return FSSpec(rawdata=data)
|
||||
|
||||
def RawAlias(data):
|
||||
return Alias(rawdata=data)
|
||||
|
||||
return Alias(rawdata=data)
|
||||
|
||||
def FindApplication(*args):
|
||||
raise NotImplementedError, "FindApplication no longer implemented"
|
||||
|
||||
raise NotImplementedError, "FindApplication no longer implemented"
|
||||
|
||||
def NewAliasMinimalFromFullPath(path):
|
||||
return Alias(Carbon.File.NewAliasMinimalFromFullPath(path, '', ''))
|
||||
|
||||
return Alias(Carbon.File.NewAliasMinimalFromFullPath(path, '', ''))
|
||||
|
||||
# Another global function:
|
||||
from Carbon.Folder import FindFolder
|
||||
|
||||
|
@ -145,54 +145,54 @@ from Carbon.Folder import FindFolder
|
|||
_curfolder = None
|
||||
|
||||
def StandardGetFile(*typelist):
|
||||
"""Ask for an input file, optionally specifying 4-char file types that are
|
||||
allowable"""
|
||||
return PromptGetFile('', *typelist)
|
||||
|
||||
"""Ask for an input file, optionally specifying 4-char file types that are
|
||||
allowable"""
|
||||
return PromptGetFile('', *typelist)
|
||||
|
||||
def PromptGetFile(prompt, *typelist):
|
||||
"""Ask for an input file giving the user a prompt message. Optionally you can
|
||||
specifying 4-char file types that are allowable"""
|
||||
import EasyDialogs
|
||||
warnings.warn("macfs.StandardGetFile and friends are deprecated, use EasyDialogs.AskFileForOpen",
|
||||
"""Ask for an input file giving the user a prompt message. Optionally you can
|
||||
specifying 4-char file types that are allowable"""
|
||||
import EasyDialogs
|
||||
warnings.warn("macfs.StandardGetFile and friends are deprecated, use EasyDialogs.AskFileForOpen",
|
||||
DeprecationWarning, stacklevel=2)
|
||||
if not typelist:
|
||||
typelist = None
|
||||
fss = EasyDialogs.AskFileForOpen(message=prompt, wanted=FSSpec,
|
||||
typeList=typelist, defaultLocation=_handleSetFolder())
|
||||
return fss, not fss is None
|
||||
if not typelist:
|
||||
typelist = None
|
||||
fss = EasyDialogs.AskFileForOpen(message=prompt, wanted=FSSpec,
|
||||
typeList=typelist, defaultLocation=_handleSetFolder())
|
||||
return fss, not fss is None
|
||||
|
||||
def StandardPutFile(prompt, default=None):
|
||||
"""Ask the user for an output file, with a prompt. Optionally you cn supply a
|
||||
default output filename"""
|
||||
import EasyDialogs
|
||||
warnings.warn("macfs.StandardGetFile and friends are deprecated, use EasyDialogs.AskFileForOpen",
|
||||
"""Ask the user for an output file, with a prompt. Optionally you cn supply a
|
||||
default output filename"""
|
||||
import EasyDialogs
|
||||
warnings.warn("macfs.StandardGetFile and friends are deprecated, use EasyDialogs.AskFileForOpen",
|
||||
DeprecationWarning, stacklevel=2)
|
||||
fss = EasyDialogs.AskFileForSave(wanted=FSSpec, message=prompt,
|
||||
savedFileName=default, defaultLocation=_handleSetFolder())
|
||||
return fss, not fss is None
|
||||
|
||||
fss = EasyDialogs.AskFileForSave(wanted=FSSpec, message=prompt,
|
||||
savedFileName=default, defaultLocation=_handleSetFolder())
|
||||
return fss, not fss is None
|
||||
|
||||
def SetFolder(folder):
|
||||
global _curfolder
|
||||
warnings.warn("macfs.StandardGetFile and friends are deprecated, use EasyDialogs.AskFileForOpen",
|
||||
global _curfolder
|
||||
warnings.warn("macfs.StandardGetFile and friends are deprecated, use EasyDialogs.AskFileForOpen",
|
||||
DeprecationWarning, stacklevel=2)
|
||||
if _curfolder:
|
||||
rv = FSSpec(_curfolder)
|
||||
else:
|
||||
rv = None
|
||||
_curfolder = folder
|
||||
return rv
|
||||
|
||||
if _curfolder:
|
||||
rv = FSSpec(_curfolder)
|
||||
else:
|
||||
rv = None
|
||||
_curfolder = folder
|
||||
return rv
|
||||
|
||||
def _handleSetFolder():
|
||||
global _curfolder
|
||||
rv = _curfolder
|
||||
_curfolder = None
|
||||
return rv
|
||||
|
||||
global _curfolder
|
||||
rv = _curfolder
|
||||
_curfolder = None
|
||||
return rv
|
||||
|
||||
def GetDirectory(prompt=None):
|
||||
"""Ask the user to select a folder. Optionally you can give a prompt."""
|
||||
import EasyDialogs
|
||||
warnings.warn("macfs.StandardGetFile and friends are deprecated, use EasyDialogs.AskFileForOpen",
|
||||
"""Ask the user to select a folder. Optionally you can give a prompt."""
|
||||
import EasyDialogs
|
||||
warnings.warn("macfs.StandardGetFile and friends are deprecated, use EasyDialogs.AskFileForOpen",
|
||||
DeprecationWarning, stacklevel=2)
|
||||
fss = EasyDialogs.AskFolder(message=prompt, wanted=FSSpec,
|
||||
defaultLocation=_handleSetFolder())
|
||||
return fss, not fss is None
|
||||
fss = EasyDialogs.AskFolder(message=prompt, wanted=FSSpec,
|
||||
defaultLocation=_handleSetFolder())
|
||||
return fss, not fss is None
|
||||
|
|
|
@ -10,137 +10,137 @@ class ArgumentError(TypeError): pass
|
|||
class ResourceFileNotFoundError(ImportError): pass
|
||||
|
||||
def need(restype, resid, filename=None, modname=None):
|
||||
"""Open a resource file, if needed. restype and resid
|
||||
are required parameters, and identify the resource for which to test. If it
|
||||
is available we are done. If it is not available we look for a file filename
|
||||
(default: modname with .rsrc appended) either in the same folder as
|
||||
where modname was loaded from, or otherwise across sys.path.
|
||||
|
||||
Returns the refno of the resource file opened (or None)"""
|
||||
"""Open a resource file, if needed. restype and resid
|
||||
are required parameters, and identify the resource for which to test. If it
|
||||
is available we are done. If it is not available we look for a file filename
|
||||
(default: modname with .rsrc appended) either in the same folder as
|
||||
where modname was loaded from, or otherwise across sys.path.
|
||||
|
||||
Returns the refno of the resource file opened (or None)"""
|
||||
|
||||
if modname is None and filename is None:
|
||||
raise ArgumentError, "Either filename or modname argument (or both) must be given"
|
||||
|
||||
if type(resid) is type(1):
|
||||
try:
|
||||
h = Res.GetResource(restype, resid)
|
||||
except Res.Error:
|
||||
pass
|
||||
else:
|
||||
return None
|
||||
else:
|
||||
try:
|
||||
h = Res.GetNamedResource(restype, resid)
|
||||
except Res.Error:
|
||||
pass
|
||||
else:
|
||||
return None
|
||||
|
||||
# Construct a filename if we don't have one
|
||||
if not filename:
|
||||
if '.' in modname:
|
||||
filename = modname.split('.')[-1] + '.rsrc'
|
||||
else:
|
||||
filename = modname + '.rsrc'
|
||||
|
||||
# Now create a list of folders to search
|
||||
searchdirs = []
|
||||
if modname == '__main__':
|
||||
# If we're main we look in the current directory
|
||||
searchdirs = [os.curdir]
|
||||
if sys.modules.has_key(modname):
|
||||
mod = sys.modules[modname]
|
||||
if hasattr(mod, '__file__'):
|
||||
searchdirs = [os.path.dirname(mod.__file__)]
|
||||
searchdirs.extend(sys.path)
|
||||
|
||||
# And look for the file
|
||||
for dir in searchdirs:
|
||||
pathname = os.path.join(dir, filename)
|
||||
if os.path.exists(pathname):
|
||||
break
|
||||
else:
|
||||
raise ResourceFileNotFoundError, filename
|
||||
|
||||
refno = open_pathname(pathname)
|
||||
|
||||
# And check that the resource exists now
|
||||
if type(resid) is type(1):
|
||||
h = Res.GetResource(restype, resid)
|
||||
else:
|
||||
h = Res.GetNamedResource(restype, resid)
|
||||
return refno
|
||||
|
||||
if modname is None and filename is None:
|
||||
raise ArgumentError, "Either filename or modname argument (or both) must be given"
|
||||
|
||||
if type(resid) is type(1):
|
||||
try:
|
||||
h = Res.GetResource(restype, resid)
|
||||
except Res.Error:
|
||||
pass
|
||||
else:
|
||||
return None
|
||||
else:
|
||||
try:
|
||||
h = Res.GetNamedResource(restype, resid)
|
||||
except Res.Error:
|
||||
pass
|
||||
else:
|
||||
return None
|
||||
|
||||
# Construct a filename if we don't have one
|
||||
if not filename:
|
||||
if '.' in modname:
|
||||
filename = modname.split('.')[-1] + '.rsrc'
|
||||
else:
|
||||
filename = modname + '.rsrc'
|
||||
|
||||
# Now create a list of folders to search
|
||||
searchdirs = []
|
||||
if modname == '__main__':
|
||||
# If we're main we look in the current directory
|
||||
searchdirs = [os.curdir]
|
||||
if sys.modules.has_key(modname):
|
||||
mod = sys.modules[modname]
|
||||
if hasattr(mod, '__file__'):
|
||||
searchdirs = [os.path.dirname(mod.__file__)]
|
||||
searchdirs.extend(sys.path)
|
||||
|
||||
# And look for the file
|
||||
for dir in searchdirs:
|
||||
pathname = os.path.join(dir, filename)
|
||||
if os.path.exists(pathname):
|
||||
break
|
||||
else:
|
||||
raise ResourceFileNotFoundError, filename
|
||||
|
||||
refno = open_pathname(pathname)
|
||||
|
||||
# And check that the resource exists now
|
||||
if type(resid) is type(1):
|
||||
h = Res.GetResource(restype, resid)
|
||||
else:
|
||||
h = Res.GetNamedResource(restype, resid)
|
||||
return refno
|
||||
|
||||
def open_pathname(pathname, verbose=0):
|
||||
"""Open a resource file given by pathname, possibly decoding an
|
||||
AppleSingle file"""
|
||||
try:
|
||||
refno = Res.FSpOpenResFile(pathname, 1)
|
||||
except Res.Error, arg:
|
||||
if arg[0] in (-37, -39):
|
||||
# No resource fork. We may be on OSX, and this may be either
|
||||
# a data-fork based resource file or a AppleSingle file
|
||||
# from the CVS repository.
|
||||
try:
|
||||
refno = Res.FSOpenResourceFile(pathname, u'', 1)
|
||||
except Res.Error, arg:
|
||||
if arg[0] != -199:
|
||||
# -199 is "bad resource map"
|
||||
raise
|
||||
else:
|
||||
return refno
|
||||
# Finally try decoding an AppleSingle file
|
||||
pathname = _decode(pathname, verbose=verbose)
|
||||
refno = Res.FSOpenResourceFile(pathname, u'', 1)
|
||||
else:
|
||||
raise
|
||||
return refno
|
||||
|
||||
"""Open a resource file given by pathname, possibly decoding an
|
||||
AppleSingle file"""
|
||||
try:
|
||||
refno = Res.FSpOpenResFile(pathname, 1)
|
||||
except Res.Error, arg:
|
||||
if arg[0] in (-37, -39):
|
||||
# No resource fork. We may be on OSX, and this may be either
|
||||
# a data-fork based resource file or a AppleSingle file
|
||||
# from the CVS repository.
|
||||
try:
|
||||
refno = Res.FSOpenResourceFile(pathname, u'', 1)
|
||||
except Res.Error, arg:
|
||||
if arg[0] != -199:
|
||||
# -199 is "bad resource map"
|
||||
raise
|
||||
else:
|
||||
return refno
|
||||
# Finally try decoding an AppleSingle file
|
||||
pathname = _decode(pathname, verbose=verbose)
|
||||
refno = Res.FSOpenResourceFile(pathname, u'', 1)
|
||||
else:
|
||||
raise
|
||||
return refno
|
||||
|
||||
def resource_pathname(pathname, verbose=0):
|
||||
"""Return the pathname for a resource file (either DF or RF based).
|
||||
If the pathname given already refers to such a file simply return it,
|
||||
otherwise first decode it."""
|
||||
try:
|
||||
refno = Res.FSpOpenResFile(pathname, 1)
|
||||
Res.CloseResFile(refno)
|
||||
except Res.Error, arg:
|
||||
if arg[0] in (-37, -39):
|
||||
# No resource fork. We may be on OSX, and this may be either
|
||||
# a data-fork based resource file or a AppleSingle file
|
||||
# from the CVS repository.
|
||||
try:
|
||||
refno = Res.FSOpenResourceFile(pathname, u'', 1)
|
||||
except Res.Error, arg:
|
||||
if arg[0] != -199:
|
||||
# -199 is "bad resource map"
|
||||
raise
|
||||
else:
|
||||
return refno
|
||||
# Finally try decoding an AppleSingle file
|
||||
pathname = _decode(pathname, verbose=verbose)
|
||||
else:
|
||||
raise
|
||||
return pathname
|
||||
|
||||
"""Return the pathname for a resource file (either DF or RF based).
|
||||
If the pathname given already refers to such a file simply return it,
|
||||
otherwise first decode it."""
|
||||
try:
|
||||
refno = Res.FSpOpenResFile(pathname, 1)
|
||||
Res.CloseResFile(refno)
|
||||
except Res.Error, arg:
|
||||
if arg[0] in (-37, -39):
|
||||
# No resource fork. We may be on OSX, and this may be either
|
||||
# a data-fork based resource file or a AppleSingle file
|
||||
# from the CVS repository.
|
||||
try:
|
||||
refno = Res.FSOpenResourceFile(pathname, u'', 1)
|
||||
except Res.Error, arg:
|
||||
if arg[0] != -199:
|
||||
# -199 is "bad resource map"
|
||||
raise
|
||||
else:
|
||||
return refno
|
||||
# Finally try decoding an AppleSingle file
|
||||
pathname = _decode(pathname, verbose=verbose)
|
||||
else:
|
||||
raise
|
||||
return pathname
|
||||
|
||||
def open_error_resource():
|
||||
"""Open the resource file containing the error code to error message
|
||||
mapping."""
|
||||
need('Estr', 1, filename="errors.rsrc", modname=__name__)
|
||||
|
||||
"""Open the resource file containing the error code to error message
|
||||
mapping."""
|
||||
need('Estr', 1, filename="errors.rsrc", modname=__name__)
|
||||
|
||||
def _decode(pathname, verbose=0):
|
||||
# Decode an AppleSingle resource file, return the new pathname.
|
||||
newpathname = pathname + '.df.rsrc'
|
||||
if os.path.exists(newpathname) and \
|
||||
os.stat(newpathname).st_mtime >= os.stat(pathname).st_mtime:
|
||||
return newpathname
|
||||
if hasattr(os, 'access') and not \
|
||||
os.access(os.path.dirname(pathname), os.W_OK|os.X_OK):
|
||||
# The destination directory isn't writeable. Create the file in
|
||||
# a temporary directory
|
||||
import tempfile
|
||||
fd, newpathname = tempfile.mkstemp(".rsrc")
|
||||
if verbose:
|
||||
print 'Decoding', pathname, 'to', newpathname
|
||||
import applesingle
|
||||
applesingle.decode(pathname, newpathname, resonly=1)
|
||||
return newpathname
|
||||
# Decode an AppleSingle resource file, return the new pathname.
|
||||
newpathname = pathname + '.df.rsrc'
|
||||
if os.path.exists(newpathname) and \
|
||||
os.stat(newpathname).st_mtime >= os.stat(pathname).st_mtime:
|
||||
return newpathname
|
||||
if hasattr(os, 'access') and not \
|
||||
os.access(os.path.dirname(pathname), os.W_OK|os.X_OK):
|
||||
# The destination directory isn't writeable. Create the file in
|
||||
# a temporary directory
|
||||
import tempfile
|
||||
fd, newpathname = tempfile.mkstemp(".rsrc")
|
||||
if verbose:
|
||||
print 'Decoding', pathname, 'to', newpathname
|
||||
import applesingle
|
||||
applesingle.decode(pathname, newpathname, resonly=1)
|
||||
return newpathname
|
||||
|
|
1466
Lib/plat-mac/pimp.py
1466
Lib/plat-mac/pimp.py
File diff suppressed because it is too large
Load Diff
|
@ -33,29 +33,29 @@ The <date> plist data has (limited) support through the Date class.
|
|||
|
||||
Generate Plist example:
|
||||
|
||||
pl = Plist(
|
||||
aString="Doodah",
|
||||
aList=["A", "B", 12, 32.1, [1, 2, 3]],
|
||||
aFloat = 0.1,
|
||||
anInt = 728,
|
||||
aDict=Dict(
|
||||
anotherString="<hello & hi there!>",
|
||||
aUnicodeValue=u'M\xe4ssig, Ma\xdf',
|
||||
aTrueValue=True,
|
||||
aFalseValue=False,
|
||||
),
|
||||
someData = Data("<binary gunk>"),
|
||||
someMoreData = Data("<lots of binary gunk>" * 10),
|
||||
aDate = Date(time.mktime(time.gmtime())),
|
||||
)
|
||||
# unicode keys are possible, but a little awkward to use:
|
||||
pl[u'\xc5benraa'] = "That was a unicode key."
|
||||
pl.write(fileName)
|
||||
pl = Plist(
|
||||
aString="Doodah",
|
||||
aList=["A", "B", 12, 32.1, [1, 2, 3]],
|
||||
aFloat = 0.1,
|
||||
anInt = 728,
|
||||
aDict=Dict(
|
||||
anotherString="<hello & hi there!>",
|
||||
aUnicodeValue=u'M\xe4ssig, Ma\xdf',
|
||||
aTrueValue=True,
|
||||
aFalseValue=False,
|
||||
),
|
||||
someData = Data("<binary gunk>"),
|
||||
someMoreData = Data("<lots of binary gunk>" * 10),
|
||||
aDate = Date(time.mktime(time.gmtime())),
|
||||
)
|
||||
# unicode keys are possible, but a little awkward to use:
|
||||
pl[u'\xc5benraa'] = "That was a unicode key."
|
||||
pl.write(fileName)
|
||||
|
||||
Parse Plist example:
|
||||
|
||||
pl = Plist.fromFile(pathOrFile)
|
||||
print pl.aKey
|
||||
pl = Plist.fromFile(pathOrFile)
|
||||
print pl.aKey
|
||||
|
||||
|
||||
"""
|
||||
|
@ -71,40 +71,40 @@ INDENT = "\t"
|
|||
|
||||
class DumbXMLWriter:
|
||||
|
||||
def __init__(self, file):
|
||||
self.file = file
|
||||
self.stack = []
|
||||
self.indentLevel = 0
|
||||
def __init__(self, file):
|
||||
self.file = file
|
||||
self.stack = []
|
||||
self.indentLevel = 0
|
||||
|
||||
def beginElement(self, element):
|
||||
self.stack.append(element)
|
||||
self.writeln("<%s>" % element)
|
||||
self.indentLevel += 1
|
||||
def beginElement(self, element):
|
||||
self.stack.append(element)
|
||||
self.writeln("<%s>" % element)
|
||||
self.indentLevel += 1
|
||||
|
||||
def endElement(self, element):
|
||||
assert self.indentLevel > 0
|
||||
assert self.stack.pop() == element
|
||||
self.indentLevel -= 1
|
||||
self.writeln("</%s>" % element)
|
||||
def endElement(self, element):
|
||||
assert self.indentLevel > 0
|
||||
assert self.stack.pop() == element
|
||||
self.indentLevel -= 1
|
||||
self.writeln("</%s>" % element)
|
||||
|
||||
def simpleElement(self, element, value=None):
|
||||
if value:
|
||||
value = _encode(value)
|
||||
self.writeln("<%s>%s</%s>" % (element, value, element))
|
||||
else:
|
||||
self.writeln("<%s/>" % element)
|
||||
def simpleElement(self, element, value=None):
|
||||
if value:
|
||||
value = _encode(value)
|
||||
self.writeln("<%s>%s</%s>" % (element, value, element))
|
||||
else:
|
||||
self.writeln("<%s/>" % element)
|
||||
|
||||
def writeln(self, line):
|
||||
if line:
|
||||
self.file.write(self.indentLevel * INDENT + line + "\n")
|
||||
else:
|
||||
self.file.write("\n")
|
||||
def writeln(self, line):
|
||||
if line:
|
||||
self.file.write(self.indentLevel * INDENT + line + "\n")
|
||||
else:
|
||||
self.file.write("\n")
|
||||
|
||||
|
||||
def _encode(text):
|
||||
text = text.replace("&", "&")
|
||||
text = text.replace("<", "<")
|
||||
return text.encode("utf-8")
|
||||
text = text.replace("&", "&")
|
||||
text = text.replace("<", "<")
|
||||
return text.encode("utf-8")
|
||||
|
||||
|
||||
PLISTHEADER = """\
|
||||
|
@ -114,323 +114,323 @@ PLISTHEADER = """\
|
|||
|
||||
class PlistWriter(DumbXMLWriter):
|
||||
|
||||
def __init__(self, file):
|
||||
file.write(PLISTHEADER)
|
||||
DumbXMLWriter.__init__(self, file)
|
||||
def __init__(self, file):
|
||||
file.write(PLISTHEADER)
|
||||
DumbXMLWriter.__init__(self, file)
|
||||
|
||||
def writeValue(self, value):
|
||||
if isinstance(value, (str, unicode)):
|
||||
self.simpleElement("string", value)
|
||||
elif isinstance(value, bool):
|
||||
# must switch for bool before int, as bool is a
|
||||
# subclass of int...
|
||||
if value:
|
||||
self.simpleElement("true")
|
||||
else:
|
||||
self.simpleElement("false")
|
||||
elif isinstance(value, int):
|
||||
self.simpleElement("integer", str(value))
|
||||
elif isinstance(value, float):
|
||||
# should perhaps use repr() for better precision?
|
||||
self.simpleElement("real", str(value))
|
||||
elif isinstance(value, (dict, Dict)):
|
||||
self.writeDict(value)
|
||||
elif isinstance(value, Data):
|
||||
self.writeData(value)
|
||||
elif isinstance(value, Date):
|
||||
self.simpleElement("date", value.toString())
|
||||
elif isinstance(value, (tuple, list)):
|
||||
self.writeArray(value)
|
||||
else:
|
||||
assert 0, "unsuported type: %s" % type(value)
|
||||
def writeValue(self, value):
|
||||
if isinstance(value, (str, unicode)):
|
||||
self.simpleElement("string", value)
|
||||
elif isinstance(value, bool):
|
||||
# must switch for bool before int, as bool is a
|
||||
# subclass of int...
|
||||
if value:
|
||||
self.simpleElement("true")
|
||||
else:
|
||||
self.simpleElement("false")
|
||||
elif isinstance(value, int):
|
||||
self.simpleElement("integer", str(value))
|
||||
elif isinstance(value, float):
|
||||
# should perhaps use repr() for better precision?
|
||||
self.simpleElement("real", str(value))
|
||||
elif isinstance(value, (dict, Dict)):
|
||||
self.writeDict(value)
|
||||
elif isinstance(value, Data):
|
||||
self.writeData(value)
|
||||
elif isinstance(value, Date):
|
||||
self.simpleElement("date", value.toString())
|
||||
elif isinstance(value, (tuple, list)):
|
||||
self.writeArray(value)
|
||||
else:
|
||||
assert 0, "unsuported type: %s" % type(value)
|
||||
|
||||
def writeData(self, data):
|
||||
self.beginElement("data")
|
||||
for line in data.asBase64().split("\n"):
|
||||
if line:
|
||||
self.writeln(line)
|
||||
self.endElement("data")
|
||||
def writeData(self, data):
|
||||
self.beginElement("data")
|
||||
for line in data.asBase64().split("\n"):
|
||||
if line:
|
||||
self.writeln(line)
|
||||
self.endElement("data")
|
||||
|
||||
def writeDict(self, d):
|
||||
self.beginElement("dict")
|
||||
items = d.items()
|
||||
items.sort()
|
||||
for key, value in items:
|
||||
assert isinstance(key, (str, unicode)), "keys must be strings"
|
||||
self.simpleElement("key", key)
|
||||
self.writeValue(value)
|
||||
self.endElement("dict")
|
||||
def writeDict(self, d):
|
||||
self.beginElement("dict")
|
||||
items = d.items()
|
||||
items.sort()
|
||||
for key, value in items:
|
||||
assert isinstance(key, (str, unicode)), "keys must be strings"
|
||||
self.simpleElement("key", key)
|
||||
self.writeValue(value)
|
||||
self.endElement("dict")
|
||||
|
||||
def writeArray(self, array):
|
||||
self.beginElement("array")
|
||||
for value in array:
|
||||
self.writeValue(value)
|
||||
self.endElement("array")
|
||||
def writeArray(self, array):
|
||||
self.beginElement("array")
|
||||
for value in array:
|
||||
self.writeValue(value)
|
||||
self.endElement("array")
|
||||
|
||||
|
||||
class Dict:
|
||||
|
||||
"""Dict wrapper for convenient access of values through attributes."""
|
||||
"""Dict wrapper for convenient access of values through attributes."""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.__dict__.update(kwargs)
|
||||
def __init__(self, **kwargs):
|
||||
self.__dict__.update(kwargs)
|
||||
|
||||
def __cmp__(self, other):
|
||||
if isinstance(other, self.__class__):
|
||||
return cmp(self.__dict__, other.__dict__)
|
||||
elif isinstance(other, dict):
|
||||
return cmp(self.__dict__, other)
|
||||
else:
|
||||
return cmp(id(self), id(other))
|
||||
def __cmp__(self, other):
|
||||
if isinstance(other, self.__class__):
|
||||
return cmp(self.__dict__, other.__dict__)
|
||||
elif isinstance(other, dict):
|
||||
return cmp(self.__dict__, other)
|
||||
else:
|
||||
return cmp(id(self), id(other))
|
||||
|
||||
def __str__(self):
|
||||
return "%s(**%s)" % (self.__class__.__name__, self.__dict__)
|
||||
__repr__ = __str__
|
||||
def __str__(self):
|
||||
return "%s(**%s)" % (self.__class__.__name__, self.__dict__)
|
||||
__repr__ = __str__
|
||||
|
||||
def copy(self):
|
||||
return self.__class__(**self.__dict__)
|
||||
def copy(self):
|
||||
return self.__class__(**self.__dict__)
|
||||
|
||||
def __getattr__(self, attr):
|
||||
"""Delegate everything else to the dict object."""
|
||||
return getattr(self.__dict__, attr)
|
||||
def __getattr__(self, attr):
|
||||
"""Delegate everything else to the dict object."""
|
||||
return getattr(self.__dict__, attr)
|
||||
|
||||
|
||||
class Plist(Dict):
|
||||
|
||||
"""The main Plist object. Basically a dict (the toplevel object
|
||||
of a plist is a dict) with two additional methods to read from
|
||||
and write to files.
|
||||
"""
|
||||
"""The main Plist object. Basically a dict (the toplevel object
|
||||
of a plist is a dict) with two additional methods to read from
|
||||
and write to files.
|
||||
"""
|
||||
|
||||
def fromFile(cls, pathOrFile):
|
||||
didOpen = 0
|
||||
if not hasattr(pathOrFile, "write"):
|
||||
pathOrFile = open(pathOrFile)
|
||||
didOpen = 1
|
||||
p = PlistParser()
|
||||
plist = p.parse(pathOrFile)
|
||||
if didOpen:
|
||||
pathOrFile.close()
|
||||
return plist
|
||||
fromFile = classmethod(fromFile)
|
||||
def fromFile(cls, pathOrFile):
|
||||
didOpen = 0
|
||||
if not hasattr(pathOrFile, "write"):
|
||||
pathOrFile = open(pathOrFile)
|
||||
didOpen = 1
|
||||
p = PlistParser()
|
||||
plist = p.parse(pathOrFile)
|
||||
if didOpen:
|
||||
pathOrFile.close()
|
||||
return plist
|
||||
fromFile = classmethod(fromFile)
|
||||
|
||||
def write(self, pathOrFile):
|
||||
if not hasattr(pathOrFile, "write"):
|
||||
pathOrFile = open(pathOrFile, "w")
|
||||
didOpen = 1
|
||||
else:
|
||||
didOpen = 0
|
||||
def write(self, pathOrFile):
|
||||
if not hasattr(pathOrFile, "write"):
|
||||
pathOrFile = open(pathOrFile, "w")
|
||||
didOpen = 1
|
||||
else:
|
||||
didOpen = 0
|
||||
|
||||
writer = PlistWriter(pathOrFile)
|
||||
writer.writeln("<plist version=\"1.0\">")
|
||||
writer.writeDict(self.__dict__)
|
||||
writer.writeln("</plist>")
|
||||
writer = PlistWriter(pathOrFile)
|
||||
writer.writeln("<plist version=\"1.0\">")
|
||||
writer.writeDict(self.__dict__)
|
||||
writer.writeln("</plist>")
|
||||
|
||||
if didOpen:
|
||||
pathOrFile.close()
|
||||
if didOpen:
|
||||
pathOrFile.close()
|
||||
|
||||
|
||||
class Data:
|
||||
|
||||
"""Wrapper for binary data."""
|
||||
"""Wrapper for binary data."""
|
||||
|
||||
def __init__(self, data):
|
||||
self.data = data
|
||||
def __init__(self, data):
|
||||
self.data = data
|
||||
|
||||
def fromBase64(cls, data):
|
||||
import base64
|
||||
return cls(base64.decodestring(data))
|
||||
fromBase64 = classmethod(fromBase64)
|
||||
def fromBase64(cls, data):
|
||||
import base64
|
||||
return cls(base64.decodestring(data))
|
||||
fromBase64 = classmethod(fromBase64)
|
||||
|
||||
def asBase64(self):
|
||||
import base64
|
||||
return base64.encodestring(self.data)
|
||||
def asBase64(self):
|
||||
import base64
|
||||
return base64.encodestring(self.data)
|
||||
|
||||
def __cmp__(self, other):
|
||||
if isinstance(other, self.__class__):
|
||||
return cmp(self.data, other.data)
|
||||
elif isinstance(other, str):
|
||||
return cmp(self.data, other)
|
||||
else:
|
||||
return cmp(id(self), id(other))
|
||||
def __cmp__(self, other):
|
||||
if isinstance(other, self.__class__):
|
||||
return cmp(self.data, other.data)
|
||||
elif isinstance(other, str):
|
||||
return cmp(self.data, other)
|
||||
else:
|
||||
return cmp(id(self), id(other))
|
||||
|
||||
def __repr__(self):
|
||||
return "%s(%s)" % (self.__class__.__name__, repr(self.data))
|
||||
def __repr__(self):
|
||||
return "%s(%s)" % (self.__class__.__name__, repr(self.data))
|
||||
|
||||
|
||||
class Date:
|
||||
|
||||
"""Primitive date wrapper, uses time floats internally, is agnostic
|
||||
about time zones.
|
||||
"""
|
||||
"""Primitive date wrapper, uses time floats internally, is agnostic
|
||||
about time zones.
|
||||
"""
|
||||
|
||||
def __init__(self, date):
|
||||
if isinstance(date, str):
|
||||
from xml.utils.iso8601 import parse
|
||||
date = parse(date)
|
||||
self.date = date
|
||||
def __init__(self, date):
|
||||
if isinstance(date, str):
|
||||
from xml.utils.iso8601 import parse
|
||||
date = parse(date)
|
||||
self.date = date
|
||||
|
||||
def toString(self):
|
||||
from xml.utils.iso8601 import tostring
|
||||
return tostring(self.date)
|
||||
def toString(self):
|
||||
from xml.utils.iso8601 import tostring
|
||||
return tostring(self.date)
|
||||
|
||||
def __cmp__(self, other):
|
||||
if isinstance(other, self.__class__):
|
||||
return cmp(self.date, other.date)
|
||||
elif isinstance(other, (int, float)):
|
||||
return cmp(self.date, other)
|
||||
else:
|
||||
return cmp(id(self), id(other))
|
||||
def __cmp__(self, other):
|
||||
if isinstance(other, self.__class__):
|
||||
return cmp(self.date, other.date)
|
||||
elif isinstance(other, (int, float)):
|
||||
return cmp(self.date, other)
|
||||
else:
|
||||
return cmp(id(self), id(other))
|
||||
|
||||
def __repr__(self):
|
||||
return "%s(%s)" % (self.__class__.__name__, repr(self.toString()))
|
||||
def __repr__(self):
|
||||
return "%s(%s)" % (self.__class__.__name__, repr(self.toString()))
|
||||
|
||||
|
||||
class PlistParser:
|
||||
|
||||
def __init__(self):
|
||||
self.stack = []
|
||||
self.currentKey = None
|
||||
self.root = None
|
||||
def __init__(self):
|
||||
self.stack = []
|
||||
self.currentKey = None
|
||||
self.root = None
|
||||
|
||||
def parse(self, file):
|
||||
from xml.parsers.expat import ParserCreate
|
||||
parser = ParserCreate()
|
||||
parser.StartElementHandler = self.handleBeginElement
|
||||
parser.EndElementHandler = self.handleEndElement
|
||||
parser.CharacterDataHandler = self.handleData
|
||||
parser.ParseFile(file)
|
||||
return self.root
|
||||
def parse(self, file):
|
||||
from xml.parsers.expat import ParserCreate
|
||||
parser = ParserCreate()
|
||||
parser.StartElementHandler = self.handleBeginElement
|
||||
parser.EndElementHandler = self.handleEndElement
|
||||
parser.CharacterDataHandler = self.handleData
|
||||
parser.ParseFile(file)
|
||||
return self.root
|
||||
|
||||
def handleBeginElement(self, element, attrs):
|
||||
self.data = []
|
||||
handler = getattr(self, "begin_" + element, None)
|
||||
if handler is not None:
|
||||
handler(attrs)
|
||||
def handleBeginElement(self, element, attrs):
|
||||
self.data = []
|
||||
handler = getattr(self, "begin_" + element, None)
|
||||
if handler is not None:
|
||||
handler(attrs)
|
||||
|
||||
def handleEndElement(self, element):
|
||||
handler = getattr(self, "end_" + element, None)
|
||||
if handler is not None:
|
||||
handler()
|
||||
def handleEndElement(self, element):
|
||||
handler = getattr(self, "end_" + element, None)
|
||||
if handler is not None:
|
||||
handler()
|
||||
|
||||
def handleData(self, data):
|
||||
self.data.append(data)
|
||||
def handleData(self, data):
|
||||
self.data.append(data)
|
||||
|
||||
def addObject(self, value):
|
||||
if self.currentKey is not None:
|
||||
self.stack[-1][self.currentKey] = value
|
||||
self.currentKey = None
|
||||
elif not self.stack:
|
||||
# this is the root object
|
||||
assert self.root is value
|
||||
else:
|
||||
self.stack[-1].append(value)
|
||||
def addObject(self, value):
|
||||
if self.currentKey is not None:
|
||||
self.stack[-1][self.currentKey] = value
|
||||
self.currentKey = None
|
||||
elif not self.stack:
|
||||
# this is the root object
|
||||
assert self.root is value
|
||||
else:
|
||||
self.stack[-1].append(value)
|
||||
|
||||
def getData(self):
|
||||
data = "".join(self.data)
|
||||
try:
|
||||
data = data.encode("ascii")
|
||||
except UnicodeError:
|
||||
pass
|
||||
self.data = []
|
||||
return data
|
||||
def getData(self):
|
||||
data = "".join(self.data)
|
||||
try:
|
||||
data = data.encode("ascii")
|
||||
except UnicodeError:
|
||||
pass
|
||||
self.data = []
|
||||
return data
|
||||
|
||||
# element handlers
|
||||
# element handlers
|
||||
|
||||
def begin_dict(self, attrs):
|
||||
if self.root is None:
|
||||
self.root = d = Plist()
|
||||
else:
|
||||
d = Dict()
|
||||
self.addObject(d)
|
||||
self.stack.append(d)
|
||||
def end_dict(self):
|
||||
self.stack.pop()
|
||||
def begin_dict(self, attrs):
|
||||
if self.root is None:
|
||||
self.root = d = Plist()
|
||||
else:
|
||||
d = Dict()
|
||||
self.addObject(d)
|
||||
self.stack.append(d)
|
||||
def end_dict(self):
|
||||
self.stack.pop()
|
||||
|
||||
def end_key(self):
|
||||
self.currentKey = self.getData()
|
||||
def end_key(self):
|
||||
self.currentKey = self.getData()
|
||||
|
||||
def begin_array(self, attrs):
|
||||
a = []
|
||||
self.addObject(a)
|
||||
self.stack.append(a)
|
||||
def end_array(self):
|
||||
self.stack.pop()
|
||||
def begin_array(self, attrs):
|
||||
a = []
|
||||
self.addObject(a)
|
||||
self.stack.append(a)
|
||||
def end_array(self):
|
||||
self.stack.pop()
|
||||
|
||||
def end_true(self):
|
||||
self.addObject(True)
|
||||
def end_false(self):
|
||||
self.addObject(False)
|
||||
def end_integer(self):
|
||||
self.addObject(int(self.getData()))
|
||||
def end_real(self):
|
||||
self.addObject(float(self.getData()))
|
||||
def end_string(self):
|
||||
self.addObject(self.getData())
|
||||
def end_data(self):
|
||||
self.addObject(Data.fromBase64(self.getData()))
|
||||
def end_date(self):
|
||||
self.addObject(Date(self.getData()))
|
||||
def end_true(self):
|
||||
self.addObject(True)
|
||||
def end_false(self):
|
||||
self.addObject(False)
|
||||
def end_integer(self):
|
||||
self.addObject(int(self.getData()))
|
||||
def end_real(self):
|
||||
self.addObject(float(self.getData()))
|
||||
def end_string(self):
|
||||
self.addObject(self.getData())
|
||||
def end_data(self):
|
||||
self.addObject(Data.fromBase64(self.getData()))
|
||||
def end_date(self):
|
||||
self.addObject(Date(self.getData()))
|
||||
|
||||
|
||||
# cruft to support booleans in Python <= 2.3
|
||||
import sys
|
||||
if sys.version_info[:2] < (2, 3):
|
||||
# Python 2.2 and earlier: no booleans
|
||||
# Python 2.2.x: booleans are ints
|
||||
class bool(int):
|
||||
"""Imitation of the Python 2.3 bool object."""
|
||||
def __new__(cls, value):
|
||||
return int.__new__(cls, not not value)
|
||||
def __repr__(self):
|
||||
if self:
|
||||
return "True"
|
||||
else:
|
||||
return "False"
|
||||
True = bool(1)
|
||||
False = bool(0)
|
||||
# Python 2.2 and earlier: no booleans
|
||||
# Python 2.2.x: booleans are ints
|
||||
class bool(int):
|
||||
"""Imitation of the Python 2.3 bool object."""
|
||||
def __new__(cls, value):
|
||||
return int.__new__(cls, not not value)
|
||||
def __repr__(self):
|
||||
if self:
|
||||
return "True"
|
||||
else:
|
||||
return "False"
|
||||
True = bool(1)
|
||||
False = bool(0)
|
||||
else:
|
||||
# Bind the boolean builtins to local names
|
||||
True = True
|
||||
False = False
|
||||
bool = bool
|
||||
# Bind the boolean builtins to local names
|
||||
True = True
|
||||
False = False
|
||||
bool = bool
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from StringIO import StringIO
|
||||
import time
|
||||
if len(sys.argv) == 1:
|
||||
pl = Plist(
|
||||
aString="Doodah",
|
||||
aList=["A", "B", 12, 32.1, [1, 2, 3]],
|
||||
aFloat = 0.1,
|
||||
anInt = 728,
|
||||
aDict=Dict(
|
||||
anotherString="<hello & hi there!>",
|
||||
aUnicodeValue=u'M\xe4ssig, Ma\xdf',
|
||||
aTrueValue=True,
|
||||
aFalseValue=False,
|
||||
),
|
||||
someData = Data("<binary gunk>"),
|
||||
someMoreData = Data("<lots of binary gunk>" * 10),
|
||||
aDate = Date(time.mktime(time.gmtime())),
|
||||
)
|
||||
elif len(sys.argv) == 2:
|
||||
pl = Plist.fromFile(sys.argv[1])
|
||||
else:
|
||||
print "Too many arguments: at most 1 plist file can be given."
|
||||
sys.exit(1)
|
||||
from StringIO import StringIO
|
||||
import time
|
||||
if len(sys.argv) == 1:
|
||||
pl = Plist(
|
||||
aString="Doodah",
|
||||
aList=["A", "B", 12, 32.1, [1, 2, 3]],
|
||||
aFloat = 0.1,
|
||||
anInt = 728,
|
||||
aDict=Dict(
|
||||
anotherString="<hello & hi there!>",
|
||||
aUnicodeValue=u'M\xe4ssig, Ma\xdf',
|
||||
aTrueValue=True,
|
||||
aFalseValue=False,
|
||||
),
|
||||
someData = Data("<binary gunk>"),
|
||||
someMoreData = Data("<lots of binary gunk>" * 10),
|
||||
aDate = Date(time.mktime(time.gmtime())),
|
||||
)
|
||||
elif len(sys.argv) == 2:
|
||||
pl = Plist.fromFile(sys.argv[1])
|
||||
else:
|
||||
print "Too many arguments: at most 1 plist file can be given."
|
||||
sys.exit(1)
|
||||
|
||||
# unicode keys are possible, but a little awkward to use:
|
||||
pl[u'\xc5benraa'] = "That was a unicode key."
|
||||
f = StringIO()
|
||||
pl.write(f)
|
||||
xml = f.getvalue()
|
||||
print xml
|
||||
f.seek(0)
|
||||
pl2 = Plist.fromFile(f)
|
||||
assert pl == pl2
|
||||
f = StringIO()
|
||||
pl2.write(f)
|
||||
assert xml == f.getvalue()
|
||||
#print repr(pl2)
|
||||
# unicode keys are possible, but a little awkward to use:
|
||||
pl[u'\xc5benraa'] = "That was a unicode key."
|
||||
f = StringIO()
|
||||
pl.write(f)
|
||||
xml = f.getvalue()
|
||||
print xml
|
||||
f.seek(0)
|
||||
pl2 = Plist.fromFile(f)
|
||||
assert pl == pl2
|
||||
f = StringIO()
|
||||
pl2.write(f)
|
||||
assert xml == f.getvalue()
|
||||
#print repr(pl2)
|
||||
|
|
|
@ -13,280 +13,280 @@ from Carbon import Qdoffs
|
|||
from Carbon import QDOffscreen
|
||||
from Carbon import Res
|
||||
try:
|
||||
import MediaDescr
|
||||
import MediaDescr
|
||||
except ImportError:
|
||||
def _audiodescr(data):
|
||||
return None
|
||||
def _audiodescr(data):
|
||||
return None
|
||||
else:
|
||||
def _audiodescr(data):
|
||||
return MediaDescr.SoundDescription.decode(data)
|
||||
def _audiodescr(data):
|
||||
return MediaDescr.SoundDescription.decode(data)
|
||||
try:
|
||||
from imgformat import macrgb
|
||||
from imgformat import macrgb
|
||||
except ImportError:
|
||||
macrgb = "Macintosh RGB format"
|
||||
macrgb = "Macintosh RGB format"
|
||||
import os
|
||||
# import audio.format
|
||||
|
||||
class VideoFormat:
|
||||
def __init__(self, name, descr, width, height, format):
|
||||
self.__name = name
|
||||
self.__descr = descr
|
||||
self.__width = width
|
||||
self.__height = height
|
||||
self.__format = format
|
||||
|
||||
def getname(self):
|
||||
return self.__name
|
||||
|
||||
def getdescr(self):
|
||||
return self.__descr
|
||||
|
||||
def getsize(self):
|
||||
return self.__width, self.__height
|
||||
|
||||
def getformat(self):
|
||||
return self.__format
|
||||
|
||||
def __init__(self, name, descr, width, height, format):
|
||||
self.__name = name
|
||||
self.__descr = descr
|
||||
self.__width = width
|
||||
self.__height = height
|
||||
self.__format = format
|
||||
|
||||
def getname(self):
|
||||
return self.__name
|
||||
|
||||
def getdescr(self):
|
||||
return self.__descr
|
||||
|
||||
def getsize(self):
|
||||
return self.__width, self.__height
|
||||
|
||||
def getformat(self):
|
||||
return self.__format
|
||||
|
||||
class _Reader:
|
||||
def __init__(self, path):
|
||||
fd = Qt.OpenMovieFile(path, 0)
|
||||
self.movie, d1, d2 = Qt.NewMovieFromFile(fd, 0, 0)
|
||||
self.movietimescale = self.movie.GetMovieTimeScale()
|
||||
try:
|
||||
self.audiotrack = self.movie.GetMovieIndTrackType(1,
|
||||
QuickTime.AudioMediaCharacteristic, QuickTime.movieTrackCharacteristic)
|
||||
self.audiomedia = self.audiotrack.GetTrackMedia()
|
||||
except Qt.Error:
|
||||
self.audiotrack = self.audiomedia = None
|
||||
self.audiodescr = {}
|
||||
else:
|
||||
handle = Res.Handle('')
|
||||
n = self.audiomedia.GetMediaSampleDescriptionCount()
|
||||
self.audiomedia.GetMediaSampleDescription(1, handle)
|
||||
self.audiodescr = _audiodescr(handle.data)
|
||||
self.audiotimescale = self.audiomedia.GetMediaTimeScale()
|
||||
del handle
|
||||
|
||||
try:
|
||||
self.videotrack = self.movie.GetMovieIndTrackType(1,
|
||||
QuickTime.VisualMediaCharacteristic, QuickTime.movieTrackCharacteristic)
|
||||
self.videomedia = self.videotrack.GetTrackMedia()
|
||||
except Qt.Error:
|
||||
self.videotrack = self.videomedia = self.videotimescale = None
|
||||
if self.videotrack:
|
||||
self.videotimescale = self.videomedia.GetMediaTimeScale()
|
||||
x0, y0, x1, y1 = self.movie.GetMovieBox()
|
||||
self.videodescr = {'width':(x1-x0), 'height':(y1-y0)}
|
||||
self._initgworld()
|
||||
self.videocurtime = None
|
||||
self.audiocurtime = None
|
||||
def __init__(self, path):
|
||||
fd = Qt.OpenMovieFile(path, 0)
|
||||
self.movie, d1, d2 = Qt.NewMovieFromFile(fd, 0, 0)
|
||||
self.movietimescale = self.movie.GetMovieTimeScale()
|
||||
try:
|
||||
self.audiotrack = self.movie.GetMovieIndTrackType(1,
|
||||
QuickTime.AudioMediaCharacteristic, QuickTime.movieTrackCharacteristic)
|
||||
self.audiomedia = self.audiotrack.GetTrackMedia()
|
||||
except Qt.Error:
|
||||
self.audiotrack = self.audiomedia = None
|
||||
self.audiodescr = {}
|
||||
else:
|
||||
handle = Res.Handle('')
|
||||
n = self.audiomedia.GetMediaSampleDescriptionCount()
|
||||
self.audiomedia.GetMediaSampleDescription(1, handle)
|
||||
self.audiodescr = _audiodescr(handle.data)
|
||||
self.audiotimescale = self.audiomedia.GetMediaTimeScale()
|
||||
del handle
|
||||
|
||||
try:
|
||||
self.videotrack = self.movie.GetMovieIndTrackType(1,
|
||||
QuickTime.VisualMediaCharacteristic, QuickTime.movieTrackCharacteristic)
|
||||
self.videomedia = self.videotrack.GetTrackMedia()
|
||||
except Qt.Error:
|
||||
self.videotrack = self.videomedia = self.videotimescale = None
|
||||
if self.videotrack:
|
||||
self.videotimescale = self.videomedia.GetMediaTimeScale()
|
||||
x0, y0, x1, y1 = self.movie.GetMovieBox()
|
||||
self.videodescr = {'width':(x1-x0), 'height':(y1-y0)}
|
||||
self._initgworld()
|
||||
self.videocurtime = None
|
||||
self.audiocurtime = None
|
||||
|
||||
|
||||
def __del__(self):
|
||||
self.audiomedia = None
|
||||
self.audiotrack = None
|
||||
self.videomedia = None
|
||||
self.videotrack = None
|
||||
self.movie = None
|
||||
|
||||
def _initgworld(self):
|
||||
old_port, old_dev = Qdoffs.GetGWorld()
|
||||
try:
|
||||
movie_w = self.videodescr['width']
|
||||
movie_h = self.videodescr['height']
|
||||
movie_rect = (0, 0, movie_w, movie_h)
|
||||
self.gworld = Qdoffs.NewGWorld(32, movie_rect, None, None, QDOffscreen.keepLocal)
|
||||
self.pixmap = self.gworld.GetGWorldPixMap()
|
||||
Qdoffs.LockPixels(self.pixmap)
|
||||
Qdoffs.SetGWorld(self.gworld.as_GrafPtr(), None)
|
||||
Qd.EraseRect(movie_rect)
|
||||
self.movie.SetMovieGWorld(self.gworld.as_GrafPtr(), None)
|
||||
self.movie.SetMovieBox(movie_rect)
|
||||
self.movie.SetMovieActive(1)
|
||||
self.movie.MoviesTask(0)
|
||||
self.movie.SetMoviePlayHints(QuickTime.hintsHighQuality, QuickTime.hintsHighQuality)
|
||||
# XXXX framerate
|
||||
finally:
|
||||
Qdoffs.SetGWorld(old_port, old_dev)
|
||||
|
||||
def _gettrackduration_ms(self, track):
|
||||
tracktime = track.GetTrackDuration()
|
||||
return self._movietime_to_ms(tracktime)
|
||||
|
||||
def _movietime_to_ms(self, time):
|
||||
value, d1, d2 = Qt.ConvertTimeScale((time, self.movietimescale, None), 1000)
|
||||
return value
|
||||
|
||||
def _videotime_to_ms(self, time):
|
||||
value, d1, d2 = Qt.ConvertTimeScale((time, self.videotimescale, None), 1000)
|
||||
return value
|
||||
|
||||
def _audiotime_to_ms(self, time):
|
||||
value, d1, d2 = Qt.ConvertTimeScale((time, self.audiotimescale, None), 1000)
|
||||
return value
|
||||
|
||||
def _videotime_to_movietime(self, time):
|
||||
value, d1, d2 = Qt.ConvertTimeScale((time, self.videotimescale, None),
|
||||
self.movietimescale)
|
||||
return value
|
||||
|
||||
def HasAudio(self):
|
||||
return not self.audiotrack is None
|
||||
|
||||
def HasVideo(self):
|
||||
return not self.videotrack is None
|
||||
|
||||
def GetAudioDuration(self):
|
||||
if not self.audiotrack:
|
||||
return 0
|
||||
return self._gettrackduration_ms(self.audiotrack)
|
||||
|
||||
def __del__(self):
|
||||
self.audiomedia = None
|
||||
self.audiotrack = None
|
||||
self.videomedia = None
|
||||
self.videotrack = None
|
||||
self.movie = None
|
||||
|
||||
def _initgworld(self):
|
||||
old_port, old_dev = Qdoffs.GetGWorld()
|
||||
try:
|
||||
movie_w = self.videodescr['width']
|
||||
movie_h = self.videodescr['height']
|
||||
movie_rect = (0, 0, movie_w, movie_h)
|
||||
self.gworld = Qdoffs.NewGWorld(32, movie_rect, None, None, QDOffscreen.keepLocal)
|
||||
self.pixmap = self.gworld.GetGWorldPixMap()
|
||||
Qdoffs.LockPixels(self.pixmap)
|
||||
Qdoffs.SetGWorld(self.gworld.as_GrafPtr(), None)
|
||||
Qd.EraseRect(movie_rect)
|
||||
self.movie.SetMovieGWorld(self.gworld.as_GrafPtr(), None)
|
||||
self.movie.SetMovieBox(movie_rect)
|
||||
self.movie.SetMovieActive(1)
|
||||
self.movie.MoviesTask(0)
|
||||
self.movie.SetMoviePlayHints(QuickTime.hintsHighQuality, QuickTime.hintsHighQuality)
|
||||
# XXXX framerate
|
||||
finally:
|
||||
Qdoffs.SetGWorld(old_port, old_dev)
|
||||
|
||||
def _gettrackduration_ms(self, track):
|
||||
tracktime = track.GetTrackDuration()
|
||||
return self._movietime_to_ms(tracktime)
|
||||
|
||||
def _movietime_to_ms(self, time):
|
||||
value, d1, d2 = Qt.ConvertTimeScale((time, self.movietimescale, None), 1000)
|
||||
return value
|
||||
|
||||
def _videotime_to_ms(self, time):
|
||||
value, d1, d2 = Qt.ConvertTimeScale((time, self.videotimescale, None), 1000)
|
||||
return value
|
||||
|
||||
def _audiotime_to_ms(self, time):
|
||||
value, d1, d2 = Qt.ConvertTimeScale((time, self.audiotimescale, None), 1000)
|
||||
return value
|
||||
|
||||
def _videotime_to_movietime(self, time):
|
||||
value, d1, d2 = Qt.ConvertTimeScale((time, self.videotimescale, None),
|
||||
self.movietimescale)
|
||||
return value
|
||||
|
||||
def HasAudio(self):
|
||||
return not self.audiotrack is None
|
||||
|
||||
def HasVideo(self):
|
||||
return not self.videotrack is None
|
||||
|
||||
def GetAudioDuration(self):
|
||||
if not self.audiotrack:
|
||||
return 0
|
||||
return self._gettrackduration_ms(self.audiotrack)
|
||||
|
||||
def GetVideoDuration(self):
|
||||
if not self.videotrack:
|
||||
return 0
|
||||
return self._gettrackduration_ms(self.videotrack)
|
||||
|
||||
def GetAudioFormat(self):
|
||||
if not self.audiodescr:
|
||||
return None, None, None, None, None
|
||||
bps = self.audiodescr['sampleSize']
|
||||
nch = self.audiodescr['numChannels']
|
||||
if nch == 1:
|
||||
channels = ['mono']
|
||||
elif nch == 2:
|
||||
channels = ['left', 'right']
|
||||
else:
|
||||
channels = map(lambda x: str(x+1), range(nch))
|
||||
if bps % 8:
|
||||
# Funny bits-per sample. We pretend not to understand
|
||||
blocksize = 0
|
||||
fpb = 0
|
||||
else:
|
||||
# QuickTime is easy (for as far as we support it): samples are always a whole
|
||||
# number of bytes, so frames are nchannels*samplesize, and there's one frame per block.
|
||||
blocksize = (bps/8)*nch
|
||||
fpb = 1
|
||||
if self.audiodescr['dataFormat'] == 'raw ':
|
||||
encoding = 'linear-excess'
|
||||
elif self.audiodescr['dataFormat'] == 'twos':
|
||||
encoding = 'linear-signed'
|
||||
else:
|
||||
encoding = 'quicktime-coding-%s'%self.audiodescr['dataFormat']
|
||||
## return audio.format.AudioFormatLinear('quicktime_audio', 'QuickTime Audio Format',
|
||||
## channels, encoding, blocksize=blocksize, fpb=fpb, bps=bps)
|
||||
return channels, encoding, blocksize, fpb, bps
|
||||
|
||||
def GetAudioFrameRate(self):
|
||||
if not self.audiodescr:
|
||||
return None
|
||||
return int(self.audiodescr['sampleRate'])
|
||||
|
||||
def GetVideoFormat(self):
|
||||
width = self.videodescr['width']
|
||||
height = self.videodescr['height']
|
||||
return VideoFormat('dummy_format', 'Dummy Video Format', width, height, macrgb)
|
||||
|
||||
def GetVideoFrameRate(self):
|
||||
tv = self.videocurtime
|
||||
if tv == None:
|
||||
tv = 0
|
||||
flags = QuickTime.nextTimeStep|QuickTime.nextTimeEdgeOK
|
||||
tv, dur = self.videomedia.GetMediaNextInterestingTime(flags, tv, 1.0)
|
||||
dur = self._videotime_to_ms(dur)
|
||||
return int((1000.0/dur)+0.5)
|
||||
|
||||
def ReadAudio(self, nframes, time=None):
|
||||
if not time is None:
|
||||
self.audiocurtime = time
|
||||
flags = QuickTime.nextTimeStep|QuickTime.nextTimeEdgeOK
|
||||
if self.audiocurtime == None:
|
||||
self.audiocurtime = 0
|
||||
tv = self.audiomedia.GetMediaNextInterestingTimeOnly(flags, self.audiocurtime, 1.0)
|
||||
if tv < 0 or (self.audiocurtime and tv < self.audiocurtime):
|
||||
return self._audiotime_to_ms(self.audiocurtime), None
|
||||
h = Res.Handle('')
|
||||
desc_h = Res.Handle('')
|
||||
size, actualtime, sampleduration, desc_index, actualcount, flags = \
|
||||
self.audiomedia.GetMediaSample(h, 0, tv, desc_h, nframes)
|
||||
self.audiocurtime = actualtime + actualcount*sampleduration
|
||||
return self._audiotime_to_ms(actualtime), h.data
|
||||
|
||||
def ReadVideo(self, time=None):
|
||||
if not time is None:
|
||||
self.videocurtime = time
|
||||
flags = QuickTime.nextTimeStep
|
||||
if self.videocurtime == None:
|
||||
flags = flags | QuickTime.nextTimeEdgeOK
|
||||
self.videocurtime = 0
|
||||
tv = self.videomedia.GetMediaNextInterestingTimeOnly(flags, self.videocurtime, 1.0)
|
||||
if tv < 0 or (self.videocurtime and tv <= self.videocurtime):
|
||||
return self._videotime_to_ms(self.videocurtime), None
|
||||
self.videocurtime = tv
|
||||
moviecurtime = self._videotime_to_movietime(self.videocurtime)
|
||||
self.movie.SetMovieTimeValue(moviecurtime)
|
||||
self.movie.MoviesTask(0)
|
||||
return self._videotime_to_ms(self.videocurtime), self._getpixmapcontent()
|
||||
|
||||
def _getpixmapcontent(self):
|
||||
"""Shuffle the offscreen PixMap data, because it may have funny stride values"""
|
||||
rowbytes = Qdoffs.GetPixRowBytes(self.pixmap)
|
||||
width = self.videodescr['width']
|
||||
height = self.videodescr['height']
|
||||
start = 0
|
||||
rv = ''
|
||||
for i in range(height):
|
||||
nextline = Qdoffs.GetPixMapBytes(self.pixmap, start, width*4)
|
||||
start = start + rowbytes
|
||||
rv = rv + nextline
|
||||
return rv
|
||||
def GetVideoDuration(self):
|
||||
if not self.videotrack:
|
||||
return 0
|
||||
return self._gettrackduration_ms(self.videotrack)
|
||||
|
||||
def GetAudioFormat(self):
|
||||
if not self.audiodescr:
|
||||
return None, None, None, None, None
|
||||
bps = self.audiodescr['sampleSize']
|
||||
nch = self.audiodescr['numChannels']
|
||||
if nch == 1:
|
||||
channels = ['mono']
|
||||
elif nch == 2:
|
||||
channels = ['left', 'right']
|
||||
else:
|
||||
channels = map(lambda x: str(x+1), range(nch))
|
||||
if bps % 8:
|
||||
# Funny bits-per sample. We pretend not to understand
|
||||
blocksize = 0
|
||||
fpb = 0
|
||||
else:
|
||||
# QuickTime is easy (for as far as we support it): samples are always a whole
|
||||
# number of bytes, so frames are nchannels*samplesize, and there's one frame per block.
|
||||
blocksize = (bps/8)*nch
|
||||
fpb = 1
|
||||
if self.audiodescr['dataFormat'] == 'raw ':
|
||||
encoding = 'linear-excess'
|
||||
elif self.audiodescr['dataFormat'] == 'twos':
|
||||
encoding = 'linear-signed'
|
||||
else:
|
||||
encoding = 'quicktime-coding-%s'%self.audiodescr['dataFormat']
|
||||
## return audio.format.AudioFormatLinear('quicktime_audio', 'QuickTime Audio Format',
|
||||
## channels, encoding, blocksize=blocksize, fpb=fpb, bps=bps)
|
||||
return channels, encoding, blocksize, fpb, bps
|
||||
|
||||
def GetAudioFrameRate(self):
|
||||
if not self.audiodescr:
|
||||
return None
|
||||
return int(self.audiodescr['sampleRate'])
|
||||
|
||||
def GetVideoFormat(self):
|
||||
width = self.videodescr['width']
|
||||
height = self.videodescr['height']
|
||||
return VideoFormat('dummy_format', 'Dummy Video Format', width, height, macrgb)
|
||||
|
||||
def GetVideoFrameRate(self):
|
||||
tv = self.videocurtime
|
||||
if tv == None:
|
||||
tv = 0
|
||||
flags = QuickTime.nextTimeStep|QuickTime.nextTimeEdgeOK
|
||||
tv, dur = self.videomedia.GetMediaNextInterestingTime(flags, tv, 1.0)
|
||||
dur = self._videotime_to_ms(dur)
|
||||
return int((1000.0/dur)+0.5)
|
||||
|
||||
def ReadAudio(self, nframes, time=None):
|
||||
if not time is None:
|
||||
self.audiocurtime = time
|
||||
flags = QuickTime.nextTimeStep|QuickTime.nextTimeEdgeOK
|
||||
if self.audiocurtime == None:
|
||||
self.audiocurtime = 0
|
||||
tv = self.audiomedia.GetMediaNextInterestingTimeOnly(flags, self.audiocurtime, 1.0)
|
||||
if tv < 0 or (self.audiocurtime and tv < self.audiocurtime):
|
||||
return self._audiotime_to_ms(self.audiocurtime), None
|
||||
h = Res.Handle('')
|
||||
desc_h = Res.Handle('')
|
||||
size, actualtime, sampleduration, desc_index, actualcount, flags = \
|
||||
self.audiomedia.GetMediaSample(h, 0, tv, desc_h, nframes)
|
||||
self.audiocurtime = actualtime + actualcount*sampleduration
|
||||
return self._audiotime_to_ms(actualtime), h.data
|
||||
|
||||
def ReadVideo(self, time=None):
|
||||
if not time is None:
|
||||
self.videocurtime = time
|
||||
flags = QuickTime.nextTimeStep
|
||||
if self.videocurtime == None:
|
||||
flags = flags | QuickTime.nextTimeEdgeOK
|
||||
self.videocurtime = 0
|
||||
tv = self.videomedia.GetMediaNextInterestingTimeOnly(flags, self.videocurtime, 1.0)
|
||||
if tv < 0 or (self.videocurtime and tv <= self.videocurtime):
|
||||
return self._videotime_to_ms(self.videocurtime), None
|
||||
self.videocurtime = tv
|
||||
moviecurtime = self._videotime_to_movietime(self.videocurtime)
|
||||
self.movie.SetMovieTimeValue(moviecurtime)
|
||||
self.movie.MoviesTask(0)
|
||||
return self._videotime_to_ms(self.videocurtime), self._getpixmapcontent()
|
||||
|
||||
def _getpixmapcontent(self):
|
||||
"""Shuffle the offscreen PixMap data, because it may have funny stride values"""
|
||||
rowbytes = Qdoffs.GetPixRowBytes(self.pixmap)
|
||||
width = self.videodescr['width']
|
||||
height = self.videodescr['height']
|
||||
start = 0
|
||||
rv = ''
|
||||
for i in range(height):
|
||||
nextline = Qdoffs.GetPixMapBytes(self.pixmap, start, width*4)
|
||||
start = start + rowbytes
|
||||
rv = rv + nextline
|
||||
return rv
|
||||
|
||||
def reader(url):
|
||||
try:
|
||||
rdr = _Reader(url)
|
||||
except IOError:
|
||||
return None
|
||||
return rdr
|
||||
try:
|
||||
rdr = _Reader(url)
|
||||
except IOError:
|
||||
return None
|
||||
return rdr
|
||||
|
||||
def _test():
|
||||
import EasyDialogs
|
||||
try:
|
||||
import img
|
||||
except ImportError:
|
||||
img = None
|
||||
import MacOS
|
||||
Qt.EnterMovies()
|
||||
path = EasyDialogs.AskFileForOpen(message='Video to convert')
|
||||
if not path: sys.exit(0)
|
||||
rdr = reader(path)
|
||||
if not rdr:
|
||||
sys.exit(1)
|
||||
dstdir = EasyDialogs.AskFileForSave(message='Name for output folder')
|
||||
if not dstdir: sys.exit(0)
|
||||
num = 0
|
||||
os.mkdir(dstdir)
|
||||
videofmt = rdr.GetVideoFormat()
|
||||
imgfmt = videofmt.getformat()
|
||||
imgw, imgh = videofmt.getsize()
|
||||
timestamp, data = rdr.ReadVideo()
|
||||
while data:
|
||||
fname = 'frame%04.4d.jpg'%num
|
||||
num = num+1
|
||||
pname = os.path.join(dstdir, fname)
|
||||
if not img: print 'Not',
|
||||
print 'Writing %s, size %dx%d, %d bytes'%(fname, imgw, imgh, len(data))
|
||||
if img:
|
||||
wrt = img.writer(imgfmt, pname)
|
||||
wrt.width = imgw
|
||||
wrt.height = imgh
|
||||
wrt.write(data)
|
||||
timestamp, data = rdr.ReadVideo()
|
||||
MacOS.SetCreatorAndType(pname, 'ogle', 'JPEG')
|
||||
if num > 20:
|
||||
print 'stopping at 20 frames so your disk does not fill up:-)'
|
||||
break
|
||||
print 'Total frames:', num
|
||||
|
||||
import EasyDialogs
|
||||
try:
|
||||
import img
|
||||
except ImportError:
|
||||
img = None
|
||||
import MacOS
|
||||
Qt.EnterMovies()
|
||||
path = EasyDialogs.AskFileForOpen(message='Video to convert')
|
||||
if not path: sys.exit(0)
|
||||
rdr = reader(path)
|
||||
if not rdr:
|
||||
sys.exit(1)
|
||||
dstdir = EasyDialogs.AskFileForSave(message='Name for output folder')
|
||||
if not dstdir: sys.exit(0)
|
||||
num = 0
|
||||
os.mkdir(dstdir)
|
||||
videofmt = rdr.GetVideoFormat()
|
||||
imgfmt = videofmt.getformat()
|
||||
imgw, imgh = videofmt.getsize()
|
||||
timestamp, data = rdr.ReadVideo()
|
||||
while data:
|
||||
fname = 'frame%04.4d.jpg'%num
|
||||
num = num+1
|
||||
pname = os.path.join(dstdir, fname)
|
||||
if not img: print 'Not',
|
||||
print 'Writing %s, size %dx%d, %d bytes'%(fname, imgw, imgh, len(data))
|
||||
if img:
|
||||
wrt = img.writer(imgfmt, pname)
|
||||
wrt.width = imgw
|
||||
wrt.height = imgh
|
||||
wrt.write(data)
|
||||
timestamp, data = rdr.ReadVideo()
|
||||
MacOS.SetCreatorAndType(pname, 'ogle', 'JPEG')
|
||||
if num > 20:
|
||||
print 'stopping at 20 frames so your disk does not fill up:-)'
|
||||
break
|
||||
print 'Total frames:', num
|
||||
|
||||
if __name__ == '__main__':
|
||||
_test()
|
||||
sys.exit(1)
|
||||
|
||||
_test()
|
||||
sys.exit(1)
|
||||
|
||||
|
|
Loading…
Reference in New Issue