class SndRoamer(scrolled.ScrolledPanel): """ @author: Brigitte Bigi @organization: Laboratoire Parole et Langage, Aix-en-Provence, France @contact: [email protected] @license: GPL, v3 @copyright: Copyright (C) 2011-2016 Brigitte Bigi @summary: Manage audio files. Panel to manage audio files: - show information, - manage the content of the audio, - play. """ def __init__(self, parent, prefsIO): """ SndRoamer Component ScrolledPanel. """ scrolled.ScrolledPanel.__init__(self, parent, -1) # members self._prefsIO = self._check_prefs(prefsIO) self._filename = None # GUI sizer = self._create_content() # Bind events self.Bind(spEVT_FILE_WANDER, self.OnFileWander) self.Bind(spEVT_SETTINGS, self.OnSettings) self.GetTopLevelParent().Bind(wx.EVT_CHAR_HOOK, self.OnKeyPress) self.SetBackgroundColour(self._prefsIO.GetValue('M_BG_COLOUR')) self.SetSizer(sizer) self.SetAutoLayout(True) self.Layout() self.SetupScrolling() # ---------------------------------------------------------------------- def _create_content(self): """ GUI design. """ sizer = wx.BoxSizer(wx.VERTICAL) # create the panels self._propertyPanel = AudioInfo(self, self._prefsIO) self._managerPanel = AudioRoamer(self, self._prefsIO) self._playerPanel = SndPlayer(self, prefsIO=self._prefsIO) sizer.Add(self._managerPanel, proportion=0, flag=wx.CENTRE | wx.ALL, border=2) sizer.Add(self._propertyPanel, proportion=0, flag=wx.LEFT | wx.EXPAND | wx.ALL, border=2) sizer.Add(self._playerPanel, proportion=1, flag=wx.CENTRE | wx.ALL, border=2) return sizer # ---------------------------------------------------------------------- def _check_prefs(self, prefs): """ Check if preferences are set properly. Set new ones if required. Return the new version. """ if prefs is None: prefs = Preferences(sppasTheme()) else: try: prefs.GetValue('M_BG_COLOUR') prefs.GetValue('M_FG_COLOUR') prefs.GetValue('M_FONT') prefs.GetValue('M_ICON_THEME') except Exception: self._prefsIO.SetTheme(sppasTheme()) prefs = self._prefsIO prefs.SetValue('SND_INFO', 'bool', False) prefs.SetValue('SND_PLAY', 'bool', True) prefs.SetValue('SND_AUTOREPLAY', 'bool', False) prefs.SetValue('SND_PAUSE', 'bool', True) prefs.SetValue('SND_STOP', 'bool', True) prefs.SetValue('SND_NEXT', 'bool', True) prefs.SetValue('SND_REWIND', 'bool', True) prefs.SetValue('SND_EJECT', 'bool', False) # CRASH. MUST CORRECT THE BUG. return prefs # ---------------------------------------------------------------------- # GUI # ---------------------------------------------------------------------- def OnSettings(self, event): """ Set new preferences, then apply them. """ self._prefsIO = self._check_prefs(event.prefsIO) # Apply the changes on self self.SetBackgroundColour(self._prefsIO.GetValue('M_BG_COLOUR')) self.SetForegroundColour(self._prefsIO.GetValue('M_FG_COLOUR')) self.SetFont(self._prefsIO.GetValue('M_FONT')) self._managerPanel.SetPreferences(self._prefsIO) self.Layout() self.Refresh() # ---------------------------------------------------------------------- def SetFont(self, font): """ Change font of all wx texts. """ wx.Window.SetFont(self, font) self._propertyPanel.SetFont(font) self._playerPanel.SetFont(font) # ---------------------------------------------------------------------- def SetBackgroundColour(self, color): """ Change background of all texts. """ wx.Window.SetBackgroundColour(self, color) self._propertyPanel.SetBackgroundColour(color) self._playerPanel.SetBackgroundColour(color) # ---------------------------------------------------------------------- def SetForegroundColour(self, color): """ Change foreground of all texts. """ wx.Window.SetForegroundColour(self, color) self._propertyPanel.SetForegroundColour(color) self._playerPanel.SetForegroundColour(color) # ---------------------------------------------------------------------- # Callbacks # ---------------------------------------------------------------------- def OnFileWander(self, event): """ A file was checked/unchecked/ejected somewhere else. """ o = event.GetEventObject() if o == self._playerPanel: evt = NotebookClosePageEvent() evt.SetEventObject(self) wx.PostEvent(self.GetParent().GetParent().GetParent(), evt) self._propertyPanel.FileDeSelected() return f = event.filename s = event.status if s is True: self._propertyPanel.FileSelected(f) self._playerPanel.FileSelected(f) self._managerPanel.FileSelected(f) self._filename = f else: self._propertyPanel.FileDeSelected() self._playerPanel.FileDeSelected() self._managerPanel.FileDeSelected(f) evt = FileWanderEvent(filename=self._filename, status=False) evt.SetEventObject(self) wx.PostEvent(self.GetParent().GetParent().GetParent(), evt) self._filename = None # ---------------------------------------------------------------------- def OnKeyPress(self, event): """ Respond to a keypress event. """ keycode = event.GetKeyCode() # Media player # TAB -> PLay # F6 -> Rewind # F7 -> Pause/Play # F8 -> Next # F12 -> Eject # ESC -> Stop if keycode == wx.WXK_TAB: self._playerPanel.onPlay(event) elif keycode == wx.WXK_F6: self._playerPanel.onRewind(event) elif keycode == wx.WXK_F7: self._playerPanel.onPause(event) elif keycode == wx.WXK_F8: self._playerPanel.onNext(event) elif keycode == wx.WXK_F12: self._playerPanel.onEject(event) elif keycode == wx.WXK_ESCAPE: self._playerPanel.onStop(event) else: event.Skip()
class IPUscribe(wx.Panel): """ Create the whole IPUscribe panel. """ def __init__(self, parent, prefsIO): """Create a new instance.""" wx.Panel.__init__(self, parent, -1, style=wx.NO_BORDER) sizer = wx.BoxSizer(wx.VERTICAL) # members self._prefsIO = self._check_prefs(prefsIO) self._current_page = 0 self._sndname = None self._buttons = dict() # a set of panels: self._txtinfo = wx.StaticText(self, -1, "", style=wx.ALIGN_LEFT) self._trsPanel = IPUscribeData(self, prefsIO) self._create_media() self._create_nav() sizer.Add(self._txtinfo, proportion=0, flag=wx.ALL | wx.EXPAND, border=8) sizer.Add(self._trsPanel, proportion=1, flag=wx.ALL | wx.EXPAND, border=2) sizer.Add(self._mediaPanel, proportion=0, flag=wx.ALL | wx.EXPAND, border=2) sizer.Add(self._navPanel, proportion=0, flag=wx.ALL | wx.EXPAND, border=2) # Bind events self.Bind(spEVT_FILE_WANDER, self.OnFileWander) self.Bind(spEVT_FILE_DIRTY, self.OnFileDirty) self.Bind(wx.EVT_SET_FOCUS, self.OnFocus) self.GetTopLevelParent().Bind(wx.EVT_CHAR_HOOK, self.OnKeyPress) self.SetSizer(sizer) self.SetAutoLayout(True) self.Layout() self.SetBackgroundColour(self._prefsIO.GetValue('M_BG_COLOUR')) self.SetForegroundColour(self._prefsIO.GetValue('M_FG_COLOUR')) self.SetFont(self._prefsIO.GetValue('M_FONT')) # ---------------------------------------------------------------------- def __create_button(self, bmp): """Create a button and add it to the sizer. :param bmp: a picture file name """ btn = platebtn.PlateButton(self._navPanel, -1, bmp=spBitmap(bmp, 24, theme=self._prefsIO.GetValue('M_ICON_THEME'))) btn.SetInitialSize() btn.SetPressColor(wx.LIGHT_GREY) btn.Enable(True) return btn # ---------------------------------------------------------------------- def _create_media(self): """Create the media panel.""" self._mediaPanel = SndPlayer(self, orient=wx.HORIZONTAL, refreshtimer=10, prefsIO=self._prefsIO) self._mediaPanel.SetPreferences(self._prefsIO) self._mediaPanel.ActivateButtons(False) # ---------------------------------------------------------------------- def _create_nav(self): """Create the page-navigation panel.""" self._navPanel = wx.Panel(self) s = wx.BoxSizer(wx.HORIZONTAL) # Number of IPUs by page self._infoipus = wx.StaticText(self._navPanel, -1, label="IPUs by page: ") self._textpage = wx.TextCtrl(self._navPanel, -1, value=str(IPU_BY_PAGE)) self._spinpage = wx.SpinButton(self._navPanel, style=wx.SP_VERTICAL) self._spinpage.SetRange(20, 300) self._spinpage.SetValue(IPU_BY_PAGE) # Buttons to change the page self._buttons['apply'] = self.__create_button(APPLY_ICON) self._buttons['first'] = self.__create_button(PAGE_FIRST_ICON) self._buttons['prev'] = self.__create_button(PAGE_PREV_ICON) self._buttons['next'] = self.__create_button(PAGE_NEXT_ICON) self._buttons['last'] = self.__create_button(PAGE_LAST_ICON) # Text to indicate the current page self._footer = wx.StaticText(self._navPanel, -1, "") self.__set_footer() s.Add(self._infoipus, 0, wx.ALL | wx.CENTER) s.Add(self._textpage, 0, wx.ALL | wx.CENTER) s.Add(self._spinpage, 0, wx.ALL | wx.CENTER) s.Add(self._buttons['apply'], proportion=0, flag=wx.ALL, border=2) s.AddStretchSpacer() s.Add(self._buttons['first'], proportion=0, flag=wx.ALL, border=2) s.Add(self._buttons['prev'], proportion=0, flag=wx.ALL, border=2) s.Add(self._buttons['next'], proportion=0, flag=wx.ALL, border=2) s.Add(self._buttons['last'], proportion=0, flag=wx.ALL, border=2) s.AddStretchSpacer() s.Add(self._footer, 0, wx.ALL, 6) self.Bind(wx.EVT_SPIN, self.OnSpinPage, self._spinpage) self._buttons['apply'].Bind(wx.EVT_BUTTON, self.OnChangeIPUbyPage) self._buttons['first'].Bind(wx.EVT_BUTTON, self.OnFirstPage) self._buttons['prev'].Bind(wx.EVT_BUTTON, self.OnPrevPage) self._buttons['next'].Bind(wx.EVT_BUTTON, self.OnNextPage) self._buttons['last'].Bind(wx.EVT_BUTTON, self.OnLastPage) self._navPanel.SetSizer(s) # ---------------------------------------------------------------------- def __set_footer(self): """Set the label of the footer.""" page_nb = "---" if self._current_page: page_nb = str(self._current_page) page_total = "---" if self._trsPanel.GetPageCount(): page_total = str(self._trsPanel.GetPageCount()) self._footer.SetLabel(" Page {:s} / {:s} ".format(page_nb, page_total)) # ---------------------------------------------------------------------- def _check_prefs(self, prefs): """ Check if preferences are set properly. Set new ones if required. Return the new version. """ if prefs is None: prefs = Preferences(sppasTheme()) else: try: prefs.GetValue('M_BG_COLOUR') prefs.GetValue('M_FG_COLOUR') prefs.GetValue('M_FONT') prefs.GetValue('M_ICON_THEME') except Exception: self._prefsIO.SetTheme(sppasTheme()) prefs = self._prefsIO prefs.SetValue('SND_AUTOREPLAY', 'bool', True) prefs.SetValue('SND_INFO', 'bool', True) prefs.SetValue('SND_PLAY', 'bool', True) prefs.SetValue('SND_PAUSE', 'bool', True) prefs.SetValue('SND_STOP', 'bool', True) prefs.SetValue('SND_NEXT', 'bool', False) prefs.SetValue('SND_REWIND', 'bool', False) return prefs # ---------------------------------------------------------------------- # Callbacks... Page navigation # ---------------------------------------------------------------------- def OnFirstPage(self, evt=None): """ Load the first page, except if the current page is already the first one! """ if self._current_page > 1: self._current_page = self._trsPanel.LoadPage(1) self.__set_footer() self._trsPanel.KillFocus() self._mediaPanel.SetOffsetPeriod(0, 0) # ---------------------------------------------------------------------- def OnLastPage(self, evt=None): """ Load the last page, except if the current page is already the last one! """ if self._current_page < self._trsPanel.GetPageCount(): self._current_page = self._trsPanel.LoadPage(self._trsPanel.GetPageCount()) self.__set_footer() self._trsPanel.KillFocus() self._mediaPanel.SetOffsetPeriod(0, 0) # ---------------------------------------------------------------------- def OnPrevPage(self, evt=None): """ Load the previous page, except if the current page is the first one!. """ if self._current_page > 1: self._current_page = self._trsPanel.LoadPage(self._current_page-1) self.__set_footer() self._trsPanel.KillFocus() self._mediaPanel.SetOffsetPeriod(0, 0) # ---------------------------------------------------------------------- def OnNextPage(self, evt=None): """ Load the next page, except if the current page is the last one. """ if self._current_page < self._trsPanel.GetPageCount(): self._current_page = self._trsPanel.LoadPage(self._current_page+1) self.__set_footer() self._trsPanel.KillFocus() self._mediaPanel.SetOffsetPeriod(0, 0) # ---------------------------------------------------------------------- def OnSpinPage(self, evt): """ Update the text about the number of IPUs by page. """ self._textpage.SetValue(str(evt.GetPosition())) # ---------------------------------------------------------------------- def OnChangeIPUbyPage(self, evt): """ Change the IPU_BY_PAGE value. """ try: v = int(self._textpage.GetValue()) except Exception: v = -1 if v <= 0: self._textpage.SetValue(str(IPU_BY_PAGE)) self._spinpage.SetValue(IPU_BY_PAGE) v = IPU_BY_PAGE self._current_page = self._trsPanel.SetState(ipu_by_page=v) self.__set_footer() # ------------------------------------------------------------------------ def OnFocus(self, event): """An IPU received the focus. """ obj = event.GetEventObject() if obj != self._trsPanel: return self._mediaPanel.FileSelected(self._sndname) (s, e) = self._trsPanel.GetSelectionStartEnd() self._mediaPanel.SetOffsetPeriod(int(s), int(e)) # ---------------------------------------------------------------------- # Functions... # ---------------------------------------------------------------------- def Save(self): """Save the transcription.""" self._trsPanel.Save() # ---------------------------------------------------------------------- def SetFont(self, font): """Change font of all texts.""" wx.Window.SetFont(self, font) # Apply on all panels self._trsPanel.SetFont(font) self._mediaPanel.SetFont(font) self._navPanel.SetFont(font) self._infoipus.SetFont(font) self._textpage.SetFont(font) self._footer.SetFont(font) self._txtinfo.SetFont(font) # ---------------------------------------------------------------------- def SetBackgroundColour(self, color): """Change background of all panels.""" wx.Window.SetBackgroundColour(self, color) # Apply as background on all panels self._trsPanel.SetBackgroundColour(color) self._mediaPanel.SetBackgroundColour(color) self._navPanel.SetBackgroundColour(color) self._infoipus.SetBackgroundColour(color) self._textpage.SetBackgroundColour(color) self._spinpage.SetBackgroundColour(color) self._footer.SetBackgroundColour(color) self._txtinfo.SetBackgroundColour(color) # ---------------------------------------------------------------------- def SetForegroundColour(self, color): """Change foreground of all panels.""" wx.Window.SetForegroundColour(self, color) # Apply as foreground on all panels self._trsPanel.SetForegroundColour(color) self._mediaPanel.SetForegroundColour(color) self._navPanel.SetForegroundColour(color) self._infoipus.SetForegroundColour(color) self._textpage.SetForegroundColour(color) self._spinpage.SetForegroundColour(color) self._footer.SetForegroundColour(color) if self._trsPanel.dirty is False: self._txtinfo.SetForegroundColour(color) # ---------------------------------------------------------------------- # Callbacks # ---------------------------------------------------------------------- def OnFileWander(self, event): """A file was selected/unselected. """ f = event.filename s = event.status if s is True: self.FileSelected(f) else: self.FileDeSelected() # ---------------------------------------------------------------------- def OnFileDirty(self, event): """The content of the file was modified. """ if event.dirty is True: self._txtinfo.SetForegroundColour(wx.Colour(20, 20, 230)) else: self._txtinfo.SetForegroundColour(self.GetForegroundColour()) self.Refresh() # ---------------------------------------------------------------------- # Data Management # ---------------------------------------------------------------------- def exists(self, filename): for x in os.listdir(os.path.dirname(filename)): try: if os.path.basename(filename.lower()) == x.lower(): return os.path.join(os.path.dirname(filename), x) except Exception: pass return None # ---------------------------------------------------------------------- def FileSelected(self, filename): """Add files.""" got = False name = os.path.splitext(filename)[0] for ext in anndata.aio.extensions: if ext in ['.pitchtier', '.hz', '.txt']: continue f = self.exists(name+ext) if got is False and f is not None: # create the object r = self._trsPanel.SetData(filename, f) if r is True: self._txtinfo.SetLabel("Transcription file: " + f) self._current_page = self._trsPanel.LoadPage(1) # show the current page and the total amount of pages at # the bottom of the window self.__set_footer() self.Layout() got = True else: self._trsPanel.UnsetData() self._sndname = filename if got is False: ShowInformation(self, self._prefsIO, "Missing IPUs: A file with an IPUs segmentation is required.", wx.ICON_ERROR) self.FileDeSelected() return # ------------------------------------------------------------------------ def FileDeSelected(self): """Remove the file.""" if self._trsPanel.dirty is True: # dlg to ask to save or not user_choice = ShowYesNoQuestion(None, self._prefsIO, "Do you want to save changes on the " "transcription of audio file {:s}?" "".format(self._sndname)) if user_choice == wx.ID_YES: self._trsPanel.Save() try: self._trsPanel.UnsetData() self._current_page = 0 self._txtinfo.SetLabel("") self._mediaPanel.FileDeSelected() self._mediaPanel.onClose(None) except Exception as e: logging.debug('ERROR for file %s: %s' % (self._sndname, str(e))) evt = FileWanderEvent(filename=self._sndname, status=False) evt.SetEventObject(self) wx.PostEvent(self.GetParent().GetParent().GetParent(), evt) self._sndname = None # ------------------------------------------------------------------------ def OnKeyPress(self, event): """Respond to a keypress event.""" keycode = event.GetKeyCode() # Media player # TAB -> PLay # F7 -> Pause # ESC -> Stop if keycode == wx.WXK_TAB: self._mediaPanel.onPlay(event) elif keycode == wx.WXK_F6: self._mediaPanel.onRewind(event) elif keycode == wx.WXK_F7: self._mediaPanel.onPause(event) elif keycode == wx.WXK_F8: self._mediaPanel.onNext(event) elif keycode == wx.WXK_ESCAPE: self._mediaPanel.onStop(event) else: event.Skip()
def onRewind(self, event): """Go backward in the music.""" SndPlayer.onRewind(self,event) self.UpdateRuler()