15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)"""
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) File:
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) JetPreview.py
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Contents and purpose:
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Plays the preview of a segment or event via the dialog box
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Copyright (c) 2008 Android Open Source Project
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Licensed under the Apache License, Version 2.0 (the "License");
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) you may not use this file except in compliance with the License.
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) You may obtain a copy of the License at
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      http://www.apache.org/licenses/LICENSE-2.0
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Unless required by applicable law or agreed to in writing, software
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) distributed under the License is distributed on an "AS IS" BASIS,
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) See the License for the specific language governing permissions and
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) limitations under the License.
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)"""
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)from __future__ import with_statement
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import wx
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import threading
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)from JetDefs import *
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)from JetCtrls import *
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)from JetFile import *
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)from JetUtils import *
325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)from eas import *
335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)from JetStatusEvent import *
34591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
35591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochclass PreviewPlayer(wx.Frame):
365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    """ Segment player """
375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    def __init__ (self, play_button, segment):
3809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        self.segment = segment
3909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        self.play_button = play_button
405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        self.mute_button = None
41c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        self.trigger_button = None
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        self.playerLock = threading.RLock()
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        self.SetKeepPlayingFlag(False)
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        self.graph = None
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    def SetGraphCtrl(self, graph, parentWin):
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        """ Sets the graph control for the player """
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        self.graph = graph
49c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        self.parentWin = parentWin
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    def SetGraphCallbackFct(self, ClickCallbackFct):
52        """ Sets the callback function for the graph control to update """
53        self.ClickCallbackFct = ClickCallbackFct
54
55    def GraphTriggerClip(self, sClipName, iEventId):
56        """ Triggers a clip by clicking on it """
57        with self.playerLock:
58            try:
59                self.jet.TriggerClip(iEventId)
60                return True
61            except:
62                return False
63
64    def SetMuteFlag(self, trackNum, mute):
65        """ Sets a mute flag """
66        sync = JetDefs.DEFAULT_MUTE_SYNC
67        with self.playerLock:
68            try:
69                self.jet.SetMuteFlag(trackNum, mute, sync)
70                logging.info("SetMuteFlag() Track:%d Mute:%d Sync:%d" % (trackNum, mute, sync))
71                return True
72            except:
73                return False
74
75    def TriggerClip(self, eventID):
76        """ Triggers a clip via function """
77        with self.playerLock:
78            try:
79                self.jet.TriggerClip(eventID)
80                logging.info("TriggerClip() eventID: %d" % eventID)
81                return True
82            except:
83                return False
84
85    def MuteTrackViaButton(self, button, trackNum):
86        """ Mutes a track via a button """
87        with self.playerLock:
88            self.mute_button = button
89            if button.GetLabel() == JetDefs.BUT_MUTE:
90                if self.SetMuteFlag(trackNum, True):
91                    button.SetLabel(JetDefs.BUT_UNMUTE)
92            else:
93                if self.SetMuteFlag(trackNum, False):
94                    button.SetLabel(JetDefs.BUT_MUTE)
95
96    def Start(self):
97        """ Starts the playback.  Called as a thread from dialog boxes """
98        self.paused = False
99
100        wx.PostEvent(self.parentWin, JetStatusEvent(JetDefs.PST_PLAY, None))
101
102        # create a temporary config file, and jet output file
103        FileKillClean(JetDefs.TEMP_JET_CONFIG_FILE)
104
105        self.jet_file = JetFile(JetDefs.TEMP_JET_CONFIG_FILE, "")
106
107        self.jet_file.AddSegment(self.segment.segname,
108                                 self.segment.filename,
109                                 self.segment.start,
110                                 self.segment.end,
111                                 self.segment.length,
112                                 SegmentOutputFile(self.segment.segname, JetDefs.TEMP_JET_CONFIG_FILE),
113                                 self.segment.quantize,
114                                 self.segment.jetevents,
115                                 self.segment.dlsfile,
116                                 None,
117                                 self.segment.transpose,
118                                 self.segment.repeat,
119                                 self.segment.mute_flags)
120        userID = 0
121        dls_num = -1
122        seg_num = 0
123
124        if len(self.segment.dlsfile) > 0:
125            self.jet_file.libraries.append(self.segment.dlsfile)
126            dls_num = 0
127
128        self.jet_file.SaveJetConfig(JetDefs.TEMP_JET_CONFIG_FILE)
129        self.jet_file.WriteJetFileFromConfig(JetDefs.TEMP_JET_CONFIG_FILE)
130
131        if not ValidateConfig(self.jet_file):
132            return
133
134        self.queueSegs = []
135        self.queueSegs.append(QueueSeg(self.segment.segname, userID, seg_num, dls_num, self.segment.repeat, self.segment.transpose, self.segment.mute_flags))
136
137        self.jet = JET()
138        self.jet.eas.StartWave()
139        self.jet.OpenFile(self.jet_file.config.filename)
140
141        # queue first segment and start playback
142        index = 0
143        Queue(self.jet, self.queueSegs[index])
144
145        index += 1
146        self.jet.Play()
147
148        self.SetKeepPlayingFlag(True)
149        while self.GetKeepPlayingFlag():
150            self.jet.Render()
151            status = self.jet.Status()
152
153            # if no more segments - we're done
154            if status.numQueuedSegments == 0:
155                break
156
157            self.jet.GetAppEvent()
158
159            # if less than 2 segs queued - queue another one
160            if (index < len(self.queueSegs)) and (status.numQueuedSegments < 2):
161                Queue(self.jet, self.queueSegs[index])
162                index += 1
163
164            wx.PostEvent(self.parentWin, JetStatusEvent(JetDefs.PST_UPD_LOCATION, status.location))
165
166        SafeJetShutdown(self.playerLock, self.jet)
167
168        FileKillClean(SegmentOutputFile(self.segment.segname, JetDefs.TEMP_JET_CONFIG_FILE))
169        FileKillClean(JetDefs.TEMP_JET_CONFIG_FILE)
170        FileKillClean(self.jet_file.config.filename)
171
172        self.SetKeepPlayingFlag(False)
173
174        wx.PostEvent(self.parentWin, JetStatusEvent(JetDefs.PST_DONE, None))
175
176        wx.PostEvent(self.parentWin, JetStatusEvent(JetDefs.PST_UPD_LOCATION, 0))
177
178    def SetKeepPlayingFlag(self, val):
179        """ Sets the flag to tell us wheter to keep playing """
180        with self.playerLock:
181            self.keepPlaying = val
182
183    def GetKeepPlayingFlag(self):
184        """ Gets the keep playing flag """
185        with self.playerLock:
186            return self.keepPlaying
187
188    def Pause(self):
189        """ Pauses playback """
190        if self.jet is None:
191            return
192        if not self.paused:
193            self.jet.Pause()
194            self.paused = True
195            wx.PostEvent(self.parentWin, JetStatusEvent(JetDefs.PST_PAUSE, None))
196        else:
197            self.jet.Play()
198            self.paused = False
199            wx.PostEvent(self.parentWin, JetStatusEvent(JetDefs.PST_RESUME, None))
200
201