1 """ 2 File: 3 JetUtils.py 4 5 Contents and purpose: 6 Utilities used throughout JetCreator 7 8 Copyright (c) 2008 Android Open Source Project 9 10 Licensed under the Apache License, Version 2.0 (the "License"); 11 you may not use this file except in compliance with the License. 12 You may obtain a copy of the License at 13 14 http://www.apache.org/licenses/LICENSE-2.0 15 16 Unless required by applicable law or agreed to in writing, software 17 distributed under the License is distributed on an "AS IS" BASIS, 18 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 See the License for the specific language governing permissions and 20 limitations under the License. 21 """ 22 23 from __future__ import with_statement 24 25 import wx 26 import os 27 import copy 28 import ConfigParser 29 import logging 30 import time 31 import tempfile 32 33 from JetDefs import * 34 from JetDebug import * 35 from midifile import TimeBase, trackGrid 36 37 class JetCutCopy(object): 38 """ Handles cut/copy/pasting of events and segments """ 39 def __init__ (self, objType, objSave, currentSegmentName): 40 self.objType = objType 41 self.objSave = copy.deepcopy(objSave) 42 self.currentSegmentName = currentSegmentName 43 44 def GetObj(self, objList): 45 """ Gets an object """ 46 objSave = copy.deepcopy(self.objSave) 47 if self.objType == JetDefs.MAIN_SEGLIST: 48 oldName = objSave.segname 49 i = len(oldName) - 1 50 while i > 0: 51 if not oldName[i].isdigit(): 52 break 53 i = i - 1 54 oldName = oldName[0:i+1] 55 i = 1 56 while True: 57 newName = oldName + str(i) 58 if self.UniqueSegName(newName, objList): 59 break 60 i = i + 1 61 objSave.segname = newName 62 elif self.objType == JetDefs.MAIN_EVENTLIST: 63 oldName = objSave.event_name 64 i = len(oldName) - 1 65 while i > 0: 66 if not oldName[i].isdigit(): 67 break 68 i = i - 1 69 oldName = oldName[0:i+1] 70 i = 1 71 while True: 72 newName = oldName + str(i) 73 if self.UniqueEventName(newName, objList): 74 break 75 i = i + 1 76 objSave.event_name = newName 77 return objSave 78 79 def UniqueSegName(self, nameVal, seglist): 80 for nm in seglist: 81 if nm.segname == nameVal: 82 return False 83 return True 84 85 def UniqueEventName(self, nameVal, eventlist): 86 for nm in eventlist: 87 if nm.event_name == nameVal: 88 return False 89 return True 90 91 92 class JetState(object): 93 """ Saves the state for cut/copy/paste """ 94 def __init__ (self, jet_file, currentSegmentIndex, currentEventIndex): 95 self.jet_file = copy.deepcopy(jet_file) 96 self.currentSegmentIndex = currentSegmentIndex 97 self.currentEventIndex = currentEventIndex 98 99 def Queue (jet, queueSeg): 100 """ Queues a segment """ 101 jet.QueueSegment(queueSeg.userID, queueSeg.seg_num, queueSeg.dls_num, queueSeg.repeat, queueSeg.transpose, queueSeg.mute_flags) 102 103 class QueueSeg(object): 104 """ Object representing a segment """ 105 def __init__ (self, name, userID, seg_num, dls_num=-1, repeat=0, transpose=0, mute_flags=0, status=''): 106 self.name = name 107 self.userID = userID 108 self.seg_num = seg_num 109 self.dls_num = dls_num 110 self.repeat = repeat 111 self.transpose = transpose 112 self.mute_flags = mute_flags 113 self.status = status 114 #DumpQueueSeg(self) 115 116 def FindDlsNum(libraries, dlsfile): 117 """ Looks for a dls file in the library list """ 118 for index, library in enumerate(libraries): 119 if library == dlsfile: 120 return index 121 return -1 122 123 def SetRowSelection(list, row, state): 124 """ Sets the selection status of a list row """ 125 if state: 126 list.SetItemState(row, wx.LIST_STATE_SELECTED, wx.LIST_STATE_SELECTED) 127 else: 128 list.SetItemState(row, ~wx.LIST_STATE_SELECTED, wx.LIST_STATE_SELECTED) 129 130 def ClearRowSelections(list): 131 """ Clears the list rows selection status """ 132 index = list.GetFirstSelected() 133 while index != -1: 134 SetRowSelection(list, index, False) 135 index = list.GetNextSelected(index) 136 137 def getColumnText(list, index, col): 138 """ Sets the text of a column """ 139 item = list.GetItem(index, col) 140 return item.GetText() 141 142 def getColumnValue(list, index, col): 143 """ Gets the text of a column """ 144 item = list.GetItem(index, col) 145 v = str(item.GetText()) 146 if len(v) > 0: 147 return int(item.GetText()) 148 else: 149 return 0 150 151 def StrNoneChk(fld): 152 """ Returns a blank string if none """ 153 if fld is None: 154 return "" 155 return str(fld) 156 157 def ConvertStrTimeToTuple(s): 158 """ Converts a string time to a tuple """ 159 try: 160 measures, beats, ticks = s.split(':',3) 161 return (int(measures), int(beats), int(ticks)) 162 except: 163 return JetDefs.MBT_DEFAULT 164 165 def FileRelativePath(target, base=os.curdir): 166 """ Returns relative file path """ 167 if not os.path.exists(target): 168 return target 169 170 if not os.path.isdir(base): 171 return target 172 173 base_list = (os.path.abspath(base)).split(os.sep) 174 target_list = (os.path.abspath(target)).split(os.sep) 175 if os.name in ['nt','dos','os2'] and base_list[0] <> target_list[0]: 176 return target 177 for i in range(min(len(base_list), len(target_list))): 178 if base_list[i] <> target_list[i]: break 179 else: 180 i+=1 181 rel_list = [os.pardir] * (len(base_list)-i) + target_list[i:] 182 return os.path.join(*rel_list) 183 184 def FileFixPath(fileSpec): 185 """ Tweaks slashes """ 186 return fileSpec.replace("\\", "/") 187 188 def FileKillClean(fileName): 189 """ Deletes a file skipping errors """ 190 try: 191 os.remove(fileName) 192 except: 193 pass 194 195 def FileJustRoot(fileName): 196 """ Gets just the root of the file name """ 197 try: 198 return os.path.splitext(fileName)[0] 199 except: 200 return "" 201 202 def FileJustName(fileName): 203 """ Gets just the filename, without the path """ 204 try: 205 return os.path.split(fileName)[1] 206 except: 207 return "" 208 209 def FileJustPath(fileName): 210 """ Gets just the path, without the file name """ 211 try: 212 return os.path.split(fileName)[0] 213 except: 214 return "" 215 216 def FileJustExt(fileName): 217 """ Gets just the extension of the file """ 218 try: 219 ext = os.path.splitext(fileName)[1] 220 return ext.upper() 221 except: 222 return "" 223 224 def FileDateTime(fileName): 225 """ Gets the date/time of a file """ 226 try: 227 filetime = time.ctime(os.path.getmtime(fileName)) 228 return filetime 229 except: 230 return "" 231 232 def FileExists(fileName): 233 """ Checks if a file exists """ 234 try: 235 return os.path.exists(fileName) 236 except: 237 return False 238 239 def IniSetValue(configFile, section, option, value): 240 """ Sets the value of a config file field """ 241 config = ConfigParser.ConfigParser() 242 config.read(configFile) 243 if not config.has_section(section): 244 config.add_section(section) 245 config.set(section, option, value) 246 cfgfile = open(configFile,'w') 247 config.write(cfgfile) 248 cfgfile.close() 249 250 def IniGetValue(configFile, section, option, retType='str', default=''): 251 """ Gets the value of a config file field """ 252 ret = default 253 config = ConfigParser.ConfigParser() 254 config.read(configFile) 255 if config.has_section(section): 256 if config.has_option(section, option): 257 ret = config.get(section, option) 258 if retType =='int': 259 try: 260 ret = int(ret) 261 except: 262 ret = 0 263 elif retType == 'float': 264 try: 265 ret = float(ret) 266 except: 267 ret = 0 268 elif retType == 'bool': 269 try: 270 if ret[0].upper()=='T': 271 ret = True 272 else: 273 ret = False 274 except: 275 ret = False 276 elif retType == 'list': 277 try: 278 ret = eval(ret) 279 except: 280 ret = [] 281 return ret 282 283 def GetRecentJetFiles(): 284 """ Builds a list of recent jet files """ 285 fileList = [] 286 config = ConfigParser.ConfigParser() 287 config.read(JetDefs.JETCREATOR_INI) 288 if config.has_section(JetDefs.RECENT_SECTION): 289 for count in range(0, 10): 290 sFile = "File" + str(count) 291 if config.has_option(JetDefs.RECENT_SECTION, sFile): 292 sFileName = config.get(JetDefs.RECENT_SECTION, sFile) 293 if FileExists(sFileName): 294 if sFileName != JetDefs.UNTITLED_FILE: 295 #fileList.append(FileRelativePath(config.get(JetDefs.RECENT_SECTION, sFile))) 296 fileList.append(config.get(JetDefs.RECENT_SECTION, sFile)) 297 return fileList 298 299 def AppendRecentJetFile(jetFile): 300 """ Appends to a list of recent jet files """ 301 addedFiles = [] 302 fileList = GetRecentJetFiles() 303 config = ConfigParser.ConfigParser() 304 config.read(JetDefs.JETCREATOR_INI) 305 if config.has_section(JetDefs.RECENT_SECTION): 306 config.remove_section(JetDefs.RECENT_SECTION) 307 config.add_section(JetDefs.RECENT_SECTION) 308 config.set(JetDefs.RECENT_SECTION, "File0", jetFile) 309 addedFiles.append(jetFile) 310 count = 1 311 for file in fileList: 312 if file not in addedFiles: 313 sFile = "File" + str(count) 314 config.set(JetDefs.RECENT_SECTION, sFile, file) 315 addedFiles.append(file) 316 count += 1 317 FileKillClean(JetDefs.JETCREATOR_INI) 318 cfgfile = open(JetDefs.JETCREATOR_INI,'w') 319 config.write(cfgfile) 320 cfgfile.close() 321 322 def CompareMbt(mbt1, mbt2): 323 """ Compates to measure/beat/tick values """ 324 try: 325 m1, b1, t1 = mbt1.split(':',3) 326 m2, b2, t2 = mbt2.split(':',3) 327 if int(m1) > int(m2): 328 return False 329 elif int(m1) == int(m2) and int(b1) > int(b2): 330 return False 331 elif int(b1) == int(b2) and int(t1) > int(t2): 332 return False 333 elif int(m1) == int(m2) and int(b1) == int(b2) and int(t1) == int(t2): 334 return False 335 else: 336 return True 337 except: 338 return False 339 340 def MbtVal(mbt): 341 """ Converts mbts to ticks """ 342 if type(mbt).__name__=='str' or type(mbt).__name__=='unicode': 343 mbt1 = mbt 344 else: 345 mbt1 = "%d:%d:%d" % mbt 346 try: 347 return TimeBase().ConvertStrTimeToTicks(mbt1) 348 except: 349 return 0 350 351 def TicksToMbt(ticks): 352 """ Converts ticks to mbts """ 353 return TimeBase().ConvertTicksToMBT(ticks) 354 355 def TicksToStrMbt(ticks): 356 """ Converts ticks to mbts """ 357 return TimeBase().ConvertTicksToStr(ticks, '%02d:%02d:%02d') 358 359 def MbtDifference(mbt1, mbt2): 360 """ Returns difference between mbt values """ 361 return TimeBase().MbtDifference(mbt1, mbt2) 362 363 def PlayMidiFile(midiFile, dlsFile=''): 364 """ Plays a midi file """ 365 try: 366 e = __import__('eas') 367 368 if midiFile == '': 369 return 370 eas = e.EAS() 371 if dlsFile > '': 372 eas.LoadDLSCollection(dlsFile) 373 eas.StartWave() 374 audio_file = eas.OpenFile(midiFile) 375 audio_file.Prepare() 376 audio_file.Play() 377 audio_file.Close() 378 eas.StopWave() 379 eas.Shutdown() 380 except: 381 return 382 383 def SegmentOutputFile(segName, configFile): 384 """ Computes a segment output file """ 385 configPath = FileJustPath(configFile) + "/" 386 segOutput = configPath + "Seg_" + segName + ".mid" 387 return segOutput 388 389 def ComputeMuteFlags(jet_file, segName): 390 """ Computes mute flags """ 391 muteFlag = 0 392 for jet_event in jet_file.GetEvents(segName): 393 muteFlag = SetMute(jet_event.track_num, muteFlag) 394 return muteFlag 395 396 def ComputeMuteFlagsFromList1(list): 397 """ Computes mute flags from a list """ 398 muteFlag = 0 399 num = list.GetItemCount() 400 for iRow in range(num): 401 track_num = list.GetTrackNumber(iRow) 402 if list.IsChecked(iRow): 403 muteFlag = SetMute(track_num, muteFlag) 404 else: 405 muteFlag = ClearMute(track_num, muteFlag) 406 return muteFlag 407 408 def ComputeMuteFlagsFromList(list): 409 """ Computes mute flags from a list """ 410 muteFlags = 0 411 num = list.GetItemCount() 412 for iRow in range(num): 413 track_num = list.GetTrackNumber(iRow) 414 if list.IsChecked(iRow): 415 muteFlags = SetMute(track_num, muteFlags) 416 return muteFlags 417 418 419 def SetMuteFlag(track, muteFlag, mute): 420 """ Sets a mute flag """ 421 if mute: 422 SetMute(track, muteFlag) 423 else: 424 ClearMute(track, muteFlag) 425 426 def SetMute(track, muteFlag): 427 """ Sets a mute flag """ 428 try: 429 muteFlag |= 1 << (track) 430 return muteFlag 431 except: 432 #bad argument 433 return muteFlag 434 435 def ClearMute(track, muteFlag): 436 """ Clears a mute flag """ 437 try: 438 muteFlag &= ~(1 << (track)) 439 return muteFlag; 440 except: 441 #bad argument 442 return muteFlag 443 444 def GetMute(track, muteFlag): 445 """ Get a mute flag """ 446 try: 447 if (muteFlag & ( 1 << (track))) == 0: 448 return False 449 else: 450 return True 451 except: 452 #bad argument 453 return False 454 455 def InfoMsg(msgTitle, msgText): 456 """ Display a simple informational message """ 457 dlg = wx.MessageDialog(None, 458 message=msgText, 459 caption=msgTitle, 460 style=wx.OK|wx.ICON_INFORMATION 461 ) 462 dlg.ShowModal() 463 dlg.Destroy() 464 465 def SendEvent (mycontrol, evt): 466 """ Sends an event """ 467 cmd = wx.CommandEvent(evt) 468 cmd.SetEventObject(mycontrol) 469 cmd.SetId(mycontrol.GetId()) 470 mycontrol.GetEventHandler().ProcessEvent(cmd) 471 472 def GetJetHelpText(dlgName, fld): 473 """ Gets the jet help text file """ 474 return IniGetValue(JetDefs.JETCREATOR_HLP, dlgName, fld) 475 476 def ExportJetArchive(fileName, jetConfigFile, jetFile): 477 """ Exports all files into a zip archive file """ 478 z = __import__('zipfile') 479 zip = z.ZipFile(fileName, 'w') 480 481 #zip the original .JET file 482 if FileExists(jetFile.config.filename): 483 zip.write(jetFile.config.filename, FileJustName(jetFile.config.filename)) 484 485 #make copy of object so we can modify it 486 jet_file = copy.deepcopy(jetFile) 487 488 #zip the files, without paths 489 for segment in jet_file.GetSegments(): 490 if FileExists(segment.filename): 491 if not FileJustName(segment.filename) in zip.namelist(): 492 zip.write(segment.filename, FileJustName(segment.filename)) 493 if FileExists(segment.output): 494 if not FileJustName(segment.output) in zip.namelist(): 495 zip.write(segment.output, FileJustName(segment.output)) 496 497 #zip the library files 498 for library in jet_file.GetLibraries(): 499 if FileExists(library): 500 if not FileJustName(library) in zip.namelist(): 501 zip.write(library, FileJustName(library)) 502 503 #remove the paths on filenames 504 for segment in jet_file.GetSegments(): 505 segment.filename = FileJustName(segment.filename) 506 segment.dlsfile = FileJustName(segment.dlsfile) 507 segment.output = FileJustName(segment.output) 508 509 #remove paths 510 for index, library in enumerate(jet_file.libraries): 511 jet_file.libraries[index] = FileJustName(library) 512 513 #create temporary .JTC file so we can modify paths to files 514 tmpConfigFile = JetDefs.TEMP_JET_CONFIG_FILE 515 FileKillClean(tmpConfigFile) 516 517 #save the file 518 jet_file.SaveJetConfig(tmpConfigFile) 519 520 #zip it and rename it back to original name without path 521 zip.write(tmpConfigFile, FileJustName(jetConfigFile)) 522 523 #create a flag file so we know this is a jet archive 524 zip.write(tmpConfigFile, "JetArchive") 525 526 zip.close() 527 528 FileKillClean(tmpConfigFile) 529 530 def ValidateConfig(test_jet_file): 531 """ Validates the contents of a config file """ 532 dImp = __import__('JetDialogs') 533 errors = [] 534 fatalError = False 535 for segment in test_jet_file.segments: 536 logging.debug(segment.filename) 537 if segment.filename is not None and len(segment.filename) > 0 and not FileExists(segment.filename): 538 errors.append(("Segment MIDI file not found", segment.filename)) 539 fatalError = True 540 if segment.dlsfile is not None and len(segment.dlsfile) > 0 and not FileExists(segment.dlsfile): 541 errors.append(("Segment DLS file not found; removing from config", segment.dlsfile)) 542 segment.dlsfile = "" 543 544 logging.debug(test_jet_file.config.filename) 545 546 if len(errors) == 0: 547 return True 548 else: 549 dlg = dImp.JetErrors("Jet Definition File Errors") 550 dlg.SetErrors(errors) 551 result = dlg.ShowModal() 552 dlg.Destroy() 553 if fatalError: 554 return False 555 else: 556 return True 557 558 def release_getLogger(name): 559 """ passing original handler with debug() method replaced to empty function """ 560 561 def dummy(*k, **kw): 562 pass 563 564 global __orig_getLogger 565 log = __orig_getLogger(name) 566 setattr(log, 'debug', dummy) 567 setattr(log, 'info', dummy) 568 setattr(log, 'error', dummy) 569 setattr(log, 'critical', dummy) 570 return log 571 572 def install_release_loggers(): 573 """ Save original handler, installs newer one """ 574 global __orig_getLogger 575 __orig_getLogger = logging.getLogger 576 setattr(logging, 'getLogger', release_getLogger) 577 578 def restore_getLogger(): 579 """ Restores original handler """ 580 global __orig_getLogger 581 if __orig_getLogger: 582 setattr(logging, 'getLogger', __orig_getLogger) 583 584 def GetMidiFileLength(midiFile): 585 """ Gets the length of a midi file via eas """ 586 e = __import__('eas') 587 588 if not FileExists(midiFile): 589 return 0 590 591 eas = e.EAS() 592 audio_file = eas.OpenFile(midiFile) 593 audio_file.Prepare() 594 midiLength = eas.audio_streams[0].ParseMetaData() 595 audio_file.Close() 596 eas.Shutdown() 597 return midiLength 598 599 def GetMidiInfo(midiFile): 600 """ Gets midi file info """ 601 m = __import__('midifile') 602 md = m.GetMidiInfo(midiFile) 603 return md 604 605 def PrintMidiInfo(midiFile): 606 """ Prints info about a midi file """ 607 mi = GetMidiInfo(midiFile) 608 if mi.err == 0: 609 print("ppqn: " + str(mi.ppqn)) 610 print("beats_per_measure: " + str(mi.beats_per_measure)) 611 print("ending mbt: " + str(mi.endMbt)) 612 print("ending mbt str: " + mi.endMbtStr) 613 print("maxMeasures: " + str(mi.maxMeasures)) 614 print("maxBeats: " + str(mi.maxBeats)) 615 print("maxTicks: " + str(mi.maxTicks)) 616 print("maxTracks: " + str(mi.maxTracks)) 617 print("totalTicks: " + str(mi.totalTicks)) 618 for track in mi.trackList: 619 print(track) 620 else: 621 print("Error opening") 622 623 def MidiSegInfo(segment): 624 """ Midi file info saved in config file for speed """ 625 class segInfo: 626 iMsPerTick = 0 627 bpm = 4 628 ppqn = 480 629 total_ticks = 0 630 iLengthInMs = 0 631 iTracks = 0 632 trackList = [] 633 634 ver = "1.5" 635 ret = segInfo() 636 savedVer = IniGetValue(JetDefs.JETMIDIFILES_INI, segment.filename, "Ver") 637 savedDateTime = IniGetValue(JetDefs.JETMIDIFILES_INI, segment.filename, "DateTime") 638 dateTime = FileDateTime(segment.filename) 639 if ver != savedVer or dateTime != savedDateTime: 640 mi = GetMidiInfo(segment.filename) 641 if mi.err == 0: 642 IniSetValue(JetDefs.JETMIDIFILES_INI, segment.filename, "Ver", ver) 643 IniSetValue(JetDefs.JETMIDIFILES_INI, segment.filename, "DateTime", str(dateTime)) 644 IniSetValue(JetDefs.JETMIDIFILES_INI, segment.filename, "PPQN", str(mi.ppqn)) 645 IniSetValue(JetDefs.JETMIDIFILES_INI, segment.filename, "BPM", str(mi.beats_per_measure)) 646 IniSetValue(JetDefs.JETMIDIFILES_INI, segment.filename, "totalTicks", str(mi.totalTicks)) 647 IniSetValue(JetDefs.JETMIDIFILES_INI, segment.filename, "maxTracks", str(mi.maxTracks)) 648 iLengthInMs = GetMidiFileLength(segment.filename) * 1000 649 IniSetValue(JetDefs.JETMIDIFILES_INI, segment.filename, "LengthInMs", str(iLengthInMs)) 650 if iLengthInMs > 0: 651 IniSetValue(JetDefs.JETMIDIFILES_INI, segment.filename, "MsPerTick", str(iLengthInMs / mi.totalTicks)) 652 #have to write out the tracklist in format that can be saved in INI file 653 tl = [] 654 for track in mi.trackList: 655 tl.append((track.track, track.channel, track.name)) 656 IniSetValue(JetDefs.JETMIDIFILES_INI, segment.filename, "Tracks", tl) 657 658 trackList = [] 659 tl = IniGetValue(JetDefs.JETMIDIFILES_INI, segment.filename, "Tracks", 'list', []) 660 for t in tl: 661 trackList.append(trackGrid(t[0], t[1], t[2],False)) 662 iTracks = IniGetValue(JetDefs.JETMIDIFILES_INI, segment.filename, "maxTracks", 'int', 0) 663 iMsPerTick = IniGetValue(JetDefs.JETMIDIFILES_INI, segment.filename, "MsPerTick", 'float', 0) 664 bpm = IniGetValue(JetDefs.JETMIDIFILES_INI, segment.filename, "BPM", 'int', 0) 665 ppqn = IniGetValue(JetDefs.JETMIDIFILES_INI, segment.filename, "PPQN", 'int', 480) 666 if iMsPerTick == 0 or bpm == 0 or ppqn == 0: 667 return ret 668 tb = TimeBase(ppqn, bpm) 669 total_ticks = tb.ConvertStrTimeToTicks(segment.length) 670 if total_ticks == 0: 671 total_ticks = tb.MbtDifference(tb.ConvertStrTimeToTuple(segment.start), tb.ConvertStrTimeToTuple(segment.end)) 672 if total_ticks == 0: 673 return ret 674 675 ret.iTracks = iTracks 676 ret.iMsPerTick = iMsPerTick 677 ret.bpm = bpm 678 ret.ppqn = ppqn 679 ret.total_ticks = total_ticks 680 ret.iLengthInMs = total_ticks * iMsPerTick 681 ret.trackList = trackList 682 return ret 683 684 def TimeStr(ms): 685 """ Returns a time string """ 686 s=ms/1000 687 m,s=divmod(s,60) 688 h,m=divmod(m,60) 689 d,h=divmod(h,24) 690 if m > 0: 691 return "%d Min %d Sec" % (m,s) 692 else: 693 return "%d Seconds" % (s) 694 695 def mbtFct(mbt, mod): 696 """ Converts times """ 697 if type(mbt).__name__=='str' or type(mbt).__name__=='unicode': 698 mbt = ConvertStrTimeToTuple(mbt) 699 retType = 'str' 700 else: 701 retType = 'int' 702 703 m = mbt[0]+mod 704 b = mbt[1]+mod 705 t = mbt[2] 706 if m < 0: 707 m = 0 708 if b < 0: 709 b = 0 710 if b > 4: 711 b = 4 712 if t < 0: 713 t = 0 714 715 if retType == 'str': 716 return "%d:%d:%d" % (m, b, t) 717 else: 718 return (m, b, t) 719 720 def OsWindows(): 721 """ Tells us whether windows or os x """ 722 if os.name == 'nt': 723 return True ; 724 else: 725 return False ; 726 727 def MacOffset(): 728 """ Mac screen coordinates funky on some controls so we finagle a few pixels """ 729 if not OsWindows(): 730 return 3 731 else: 732 return 0 733 734 def SafeJetShutdown(lock, jet): 735 """ Makes sure we do the jet shutdown properly """ 736 with lock: 737 #MAKE SURE WE CLEANUP 738 #try: jet.Clear_Queue() 739 #except: pass 740 741 try: jet.eas.StopWave() 742 except: pass 743 744 try: jet.Shutdown() 745 except: pass 746 747 jet = None 748 749 750 def CreateTempJetFile(org_jet_file): 751 """ Creates temporary jet file for playback testing """ 752 dirname = JetDefs.TEMP_JET_DIR 753 if not os.path.isdir(dirname): 754 os.mkdir(dirname) 755 756 tmpConfigFile = dirname + FileJustName(org_jet_file.config_file) 757 FileKillClean(tmpConfigFile) 758 759 jet_file = copy.deepcopy(org_jet_file) 760 761 for tmp in jet_file.segments: 762 tmp.output = dirname + FileJustName(tmp.output) 763 764 jet_file.config_file = tmpConfigFile 765 jet_file.config.filename = dirname + FileJustName(jet_file.config.filename) 766 FileKillClean(jet_file.config.filename) 767 768 jet_file.SaveJetConfig(tmpConfigFile) 769 jet_file.WriteJetFileFromConfig(tmpConfigFile) 770 771 return jet_file 772 773 def CleanupTempJetFile(jet_file): 774 """ Cleans up temporary files """ 775 FileKillClean(jet_file.config.filename) 776 FileKillClean(jet_file.config_file) 777 for tmp in jet_file.segments: 778 FileKillClean(tmp.output) 779 780 def GetNow(): 781 return time.asctime() 782 783 784 if __name__ == '__main__': 785 """ Tests functions """ 786 pass 787 788