Пример #1
0
 def __init__(self, name='', description='', public=False, tracks=[]):
     """After creation will add all the tracks provided."""
     assert public in [True, False]
     assert isinstance(name, six.string_types)
     assert isinstance(description, six.string_types)
     assert isinstance(tracks, list)
     super(CreatePlaylist, self).__init__(None, title='Create Playlist')
     add_accelerator(self, 'ESCAPE', lambda event: self.Close(True))
     self.tracks = tracks
     p = self.GetContentsPane()
     wx.StaticText(p, label='&Name')
     self.name = wx.TextCtrl(p, value=name, style=wx.TE_RICH2)
     wx.StaticText(p, label='&Description')
     self.description = wx.TextCtrl(p,
                                    value=description,
                                    style=wx.TE_MULTILINE | wx.TE_RICH2)
     self.public = wx.CheckBox(p, label='&Public')
     self.public.SetValue(public)
     l = '&Create'
     if self.tracks:
         l = '%s and add %s %s' % (l, len(
             self.tracks), 'track' if len(self.tracks) == 1 else 'tracks')
     self.done = wx.Button(p, label=l)
     self.done.SetDefault()
     self.done.Bind(wx.EVT_BUTTON, self.on_done)
Пример #2
0
def key(key, func):
 """
 Add a hotkey.
 
 Arguments:
  key - The key to assign.
  func - The function to call when this key is pressed. Function must be prepared to take a wx event as it's first argument.
 """
 keys.add_accelerator(application.frame, key, func)
Пример #3
0
 def add_menu_item(self, menu, func, name, hotkey = None, id = None, help = None):
  if id == None:
   id = wx.NewId()
  if help == None:
   help = getdoc(func) or 'No description available.'
  if hotkey:
   keys.add_accelerator(self, hotkey, func, id = id)
   name += ' (%s)' % hotkey
  self.Bind(wx.EVT_MENU, func, id = id)
  menu.Append(id, name, help)
Пример #4
0
 def __init__(self, playlist):
  """Initialise with a playlist."""
  self.playlist = playlist
  super(EditPlaylistFrame, self).__init__(None, title = 'Playlist Editor')
  add_accelerator(self, 'ESCAPE', lambda event: self.Close(True))
  p = self.GetContentsPane()
  p.SetSizerType('form')
  wx.StaticText(p, label = '&Name')
  self.name = wx.TextCtrl(p, value = playlist.name, style = wx.TE_RICH2)
  wx.StaticText(p, label = '&Description')
  self.description = wx.TextCtrl(p, value = playlist.description, style = wx.TE_MULTILINE | wx.TE_RICH2)
  self.delete = wx.Button(p, label = 'D&elete')
  self.ok = wx.Button(p, label = '&OK')
  self.delete.Bind(wx.EVT_BUTTON, self.on_delete)
  self.ok.Bind(wx.EVT_BUTTON, self.on_ok)
Пример #5
0
 def __init__(self):
  super(GenreStation, self).__init__(None, title = 'Create A Genre Station')
  add_accelerator(self, 'ESCAPE', lambda event: self.Close(True))
  p = self.GetContentsPane()
  wx.StaticText(p, label = '&Name')
  self.name = wx.TextCtrl(p, style = wx.TE_RICH2)
  self.genres = [] # The ids for add_station.
  wx.StaticText(p, label = '&Genre')
  self.genre = wx.ListBox(p)
  self.genre.Bind(wx.EVT_LISTBOX, self.update_name)
  do_login(callback = self.update_genres)
  self.ok = wx.Button(p, label = '&OK')
  self.ok.SetDefault()
  self.ok.Bind(wx.EVT_BUTTON, self.on_ok)
  wx.Button(p, label = '&Cancel').Bind(wx.EVT_BUTTON, lambda event: self.Close(True))
Пример #6
0
 def __init__(self):
     super(GenreStation, self).__init__(None,
                                        title='Create A Genre Station')
     add_accelerator(self, 'ESCAPE', lambda event: self.Close(True))
     p = self.GetContentsPane()
     wx.StaticText(p, label='&Name')
     self.name = wx.TextCtrl(p, style=wx.TE_RICH2)
     self.genres = []  # The ids for add_station.
     wx.StaticText(p, label='&Genre')
     self.genre = wx.ListBox(p)
     self.genre.Bind(wx.EVT_LISTBOX, self.update_name)
     do_login(callback=self.update_genres)
     self.ok = wx.Button(p, label='&OK')
     self.ok.SetDefault()
     self.ok.Bind(wx.EVT_BUTTON, self.on_ok)
     wx.Button(p, label='&Cancel').Bind(wx.EVT_BUTTON,
                                        lambda event: self.Close(True))
Пример #7
0
 def __init__(self, playlist):
     """Initialise with a playlist."""
     self.playlist = playlist
     super(EditPlaylistFrame, self).__init__(None, title='Playlist Editor')
     add_accelerator(self, 'ESCAPE', lambda event: self.Close(True))
     p = self.GetContentsPane()
     p.SetSizerType('form')
     wx.StaticText(p, label='&Name')
     self.name = wx.TextCtrl(p, value=playlist.name, style=wx.TE_RICH2)
     wx.StaticText(p, label='&Description')
     self.description = wx.TextCtrl(p,
                                    value=playlist.description,
                                    style=wx.TE_MULTILINE | wx.TE_RICH2)
     self.delete = wx.Button(p, label='D&elete')
     self.ok = wx.Button(p, label='&OK')
     self.delete.Bind(wx.EVT_BUTTON, self.on_delete)
     self.ok.Bind(wx.EVT_BUTTON, self.on_ok)
Пример #8
0
 def __init__(self):
  super(AudioOptions, self).__init__(application.frame, title = 'Audio Options')
  p = self.GetContentsPane()
  add_accelerator(self, 'ESCAPE', lambda event: self.Close(True))
  self.default_volume = config.system['volume']
  self.default_frequency = config.system['frequency']
  self.default_pan = config.system['pan']
  p.SetSizerType('form')
  wx.StaticText(p, label = '&Output Device')
  self.device = wx.Choice(p, choices = sorted(application.output.get_device_names()))
  self.device.SetStringSelection(config.system['output_device_name'])
  self.device.Bind(wx.EVT_CHOICE, lambda event: set_output_device(self.device.GetStringSelection()))
  wx.StaticText(p, label = '&Volume')
  self.volume = wx.Slider(p, style = wx.VERTICAL)
  self.volume.SetValue(self.default_volume)
  self.volume.Bind(wx.EVT_SLIDER, lambda event: set_volume(self.volume.GetValue()))
  wx.StaticText(p, label = '&Pan')
  self.pan = wx.Slider(p, style = wx.HORIZONTAL)
  self.pan.SetValue(self.default_pan)
  self.pan.Bind(wx.EVT_SLIDER, lambda event: set_pan(self.pan.GetValue()))
  wx.StaticText(p, label = '&Frequency')
  self.frequency = IntCtrl(p, value = self.default_frequency, min = min_frequency, max = max_frequency, limited = True)
  self.frequency.Bind(EVT_INT, set_frequency(self.frequency.GetValue()))
  add_accelerator(self.frequency, 'UP', lambda event: self.update_frequency(min(self.frequency.GetMax(), self.frequency.GetValue() + 100)))
  add_accelerator(self.frequency, 'DOWN', lambda event: self.update_frequency(max(self.frequency.GetMin(), self.frequency.GetValue() - 100)))
  self.ok = wx.Button(p, label = '&OK')
  self.ok.Bind(wx.EVT_BUTTON, lambda event: self.Close(True))
  self.restore = wx.Button(p, label = '&Restore Defaults')
  self.restore.Bind(wx.EVT_BUTTON, self.on_restore)
  self.Show(True)
  self.Maximize(True)
Пример #9
0
 def __init__(self, name = '', description = '', public = False, tracks = []):
  """After creation will add all the tracks provided."""
  assert public in [True, False]
  assert isinstance(name, six.string_types)
  assert isinstance(description, six.string_types)
  assert isinstance(tracks, list)
  super(CreatePlaylist, self).__init__(None, title = 'Create Playlist')
  add_accelerator(self, 'ESCAPE', lambda event: self.Close(True))
  self.tracks = tracks
  p = self.GetContentsPane()
  wx.StaticText(p, label = '&Name')
  self.name = wx.TextCtrl(p, value = name, style = wx.TE_RICH2)
  wx.StaticText(p, label = '&Description')
  self.description = wx.TextCtrl(p, value = description, style = wx.TE_MULTILINE | wx.TE_RICH2)
  self.public = wx.CheckBox(p, label = '&Public')
  self.public.SetValue(public)
  l = '&Create'
  if self.tracks:
   l = '%s and add %s %s' % (l, len(self.tracks), 'track' if len(self.tracks) == 1 else 'tracks')
  self.done = wx.Button(p, label = l)
  self.done.SetDefault()
  self.done.Bind(wx.EVT_BUTTON, self.on_done)
Пример #10
0
 def __init__(self):
     super(AudioOptions, self).__init__(application.frame,
                                        title='Audio Options')
     p = self.GetContentsPane()
     add_accelerator(self, 'ESCAPE', lambda event: self.Close(True))
     self.default_volume = config.system['volume']
     self.default_frequency = config.system['frequency']
     self.default_pan = config.system['pan']
     p.SetSizerType('form')
     wx.StaticText(p, label='&Output Device')
     self.device = wx.Choice(p,
                             choices=sorted(
                                 application.output.get_device_names()))
     self.device.SetStringSelection(config.system['output_device_name'])
     self.device.Bind(
         wx.EVT_CHOICE,
         lambda event: set_output_device(self.device.GetStringSelection()))
     wx.StaticText(p, label='&Volume')
     self.volume = wx.Slider(p, style=wx.VERTICAL)
     self.volume.SetValue(self.default_volume)
     self.volume.Bind(wx.EVT_SLIDER,
                      lambda event: set_volume(self.volume.GetValue()))
     wx.StaticText(p, label='&Pan')
     self.pan = wx.Slider(p, style=wx.HORIZONTAL)
     self.pan.SetValue(self.default_pan)
     self.pan.Bind(wx.EVT_SLIDER,
                   lambda event: set_pan(self.pan.GetValue()))
     wx.StaticText(p, label='&Frequency')
     self.frequency = IntCtrl(p,
                              value=self.default_frequency,
                              min=min_frequency,
                              max=max_frequency,
                              limited=True)
     self.frequency.Bind(EVT_INT, set_frequency(self.frequency.GetValue()))
     add_accelerator(
         self.frequency, 'UP', lambda event: self.update_frequency(
             min(self.frequency.GetMax(),
                 self.frequency.GetValue() + 100)))
     add_accelerator(
         self.frequency, 'DOWN', lambda event: self.update_frequency(
             max(self.frequency.GetMin(),
                 self.frequency.GetValue() - 100)))
     self.ok = wx.Button(p, label='&OK')
     self.ok.Bind(wx.EVT_BUTTON, lambda event: self.Close(True))
     self.restore = wx.Button(p, label='&Restore Defaults')
     self.restore.Bind(wx.EVT_BUTTON, self.on_restore)
     self.Show(True)
     self.Maximize(True)
Пример #11
0
 def __init__(self, *args, **kwargs):
     self.commands = []  # Commands to be executed from the context menu.
     self.initialised = False  # Set to True when everything's done.
     self.cast_device = None  # The device to cast to.
     super(MainFrame, self).__init__(*args, **kwargs)
     try:
         add_hotkey(self, 'MEDIA_PLAY_PAUSE', self.play_pause)
         add_hotkey(self, 'MEDIA_PREV_TRACK', self.on_previous)
         add_hotkey(self, 'MEDIA_NEXT_TRACK', self.on_next)
     except RuntimeError:
         logger.warning(
             'Media keys will not be available because no win32con found.')
     self.played = [
     ]  # The tracks from the current view which have already been played.
     self.last_playlist = None  # The playlist that most recently had a track added to it.
     self.playlist_action = None  # An action to be called when all playlists have been localised.
     self.autoload = []  # Tracks to autoload in order.
     self.showing = None  # Set it to the currently showing playlist or one of the showing.* constants from functions.sound.
     self.queue = []  # The play queue.
     self.results = []
     p = wx.Panel(self)
     s = wx.BoxSizer(wx.VERTICAL)
     s1 = wx.BoxSizer(wx.HORIZONTAL)
     self.previous = wx.Button(p, label='&Previous')
     self.previous.Bind(wx.EVT_BUTTON, self.on_previous)
     self.play = wx.Button(p, label=PLAY_LABEL)
     self.play.Bind(wx.EVT_BUTTON, self.play_pause)
     self.next = wx.Button(p, label='&Next')
     self.next.Bind(wx.EVT_BUTTON, self.on_next)
     self.menu = wx.Button(p, label='&Menu')
     self.search_label = wx.StaticText(p, label=SEARCH_LABEL)
     self.search = wx.TextCtrl(p, style=wx.TE_PROCESS_ENTER)
     self.search.Bind(wx.EVT_TEXT_ENTER, self.on_text_enter)
     s1.AddMany([(self.previous, 0, wx.GROW), (self.play, 0, wx.GROW),
                 (self.next, 0, wx.GROW), (self.menu, 0, wx.GROW),
                 (self.search_label, 0, wx.GROW),
                 (self.search, 1, wx.GROW)])
     s2 = wx.BoxSizer(wx.HORIZONTAL)
     vs = wx.BoxSizer(wx.VERTICAL)
     vs.Add(wx.StaticText(p, label='&Tracks'), 0, wx.GROW)
     self.view = wx.ListBox(p)
     add_accelerator(self.view, 'RETURN', self.on_activate)
     self.view.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.on_activate)
     add_accelerator(self.view, 'SPACE', self.play_pause)
     self.view.Bind(wx.EVT_LISTBOX_DCLICK, self.on_activate)
     self.view.SetFocus()
     self.view.Bind(wx.EVT_CONTEXT_MENU, self.on_context)
     if sys.platform == 'darwin':
         add_accelerator(self.view, 'SHIFT+F10', self.on_context)
     vs.Add(self.view, 1, wx.GROW)
     ls = wx.BoxSizer(wx.VERTICAL)
     ls.Add(wx.StaticText(p, label='&Lyrics'), 0, wx.GROW)
     self.lyrics = wx.TextCtrl(p,
                               value='Play a song to view lyrics.',
                               style=wx.TE_MULTILINE | wx.TE_READONLY)
     ls.Add(self.lyrics, 1, wx.GROW)
     ls.Add(wx.StaticText(p, label='Artist &Biography'), 0, wx.GROW)
     self.artist_bio = wx.TextCtrl(p,
                                   style=wx.TE_MULTILINE | wx.TE_READONLY)
     ls.Add(self.artist_bio, 0, wx.GROW)
     s2.AddMany([
         (vs, 1, wx.GROW),
         (ls, 1, wx.GROW),
     ])
     s3 = wx.BoxSizer(wx.HORIZONTAL)
     s3.Add(wx.StaticText(p, label='&Volume'), 0, wx.GROW)
     self.volume = wx.Slider(p,
                             value=config.system['volume'],
                             style=wx.SL_VERTICAL)
     self.volume.Bind(wx.EVT_SLIDER,
                      lambda event: set_volume(self.volume.GetValue()))
     s3.Add(self.volume, 1, wx.GROW)
     s3.Add(wx.StaticText(p, label='&Position'), 0, wx.GROW)
     self.position = wx.Slider(p, style=wx.SL_HORIZONTAL)
     self.position.Bind(
         wx.EVT_SLIDER, lambda event: application.stream.set_position(
             (int(application.stream.get_length() / 100) * self.position.
              GetValue())) if not isinstance(application.track, URLStream)
         and application.stream else None)
     add_accelerator(self, 'SHIFT+LEFT', self.rewind)
     add_accelerator(self, 'SHIFT+RIGHT', self.fastforward)
     self.position_timer = wx.Timer(self)
     self.Bind(wx.EVT_TIMER, self.play_manager, self.position_timer)
     self.position_timer.Start(50)
     s.AddMany([
         (s1, 0, wx.GROW),
         (s2, 1, wx.GROW),
         (s3, 0, wx.GROW),
     ])
     p.SetSizerAndFit(s)
     self.SetTitle()
     self.Bind(wx.EVT_CLOSE, self.on_close)
     self.Bind(wx.EVT_SHOW, self.on_show)
     self.playlists = {}  # A list of playlist: id key: value pairs.
     self.stations = {}  # The same as .playlists except for radio stations.
     self.status = self.CreateStatusBar()
     self.status.SetStatusText('Nothing playing yet')
     add_accelerator(self, 'CTRL+R', self.cycle_repeat)
     self.getting_stream_title = False
Пример #12
0
 def __init__(self, *args, **kwargs):
     self.commands = [] # Commands to be executed from the context menu.
     self.initialised = False  # Set to True when everything's done.
     self.cast_device = None  # The device to cast to.
     super(MainFrame, self).__init__(*args, **kwargs)
     try:
         add_hotkey(self, 'MEDIA_PLAY_PAUSE', self.play_pause)
         add_hotkey(self, 'MEDIA_PREV_TRACK', self.on_previous)
         add_hotkey(self, 'MEDIA_NEXT_TRACK', self.on_next)
     except RuntimeError:
         logger.warning('Media keys will not be available because no win32con found.')
     self.played = [] # The tracks from the current view which have already been played.
     self.last_playlist = None # The playlist that most recently had a track added to it.
     self.playlist_action = None # An action to be called when all playlists have been localised.
     self.autoload = [] # Tracks to autoload in order.
     self.showing = None # Set it to the currently showing playlist or one of the showing.* constants from functions.sound.
     self.queue = [] # The play queue.
     self.results = []
     p = wx.Panel(self)
     s = wx.BoxSizer(wx.VERTICAL)
     s1 = wx.BoxSizer(wx.HORIZONTAL)
     self.previous = wx.Button(p, label = '&Previous')
     self.previous.Bind(wx.EVT_BUTTON, self.on_previous)
     self.play = wx.Button(p, label = PLAY_LABEL)
     self.play.Bind(wx.EVT_BUTTON, self.play_pause)
     self.next = wx.Button(p, label = '&Next')
     self.next.Bind(wx.EVT_BUTTON, self.on_next)
     self.menu = wx.Button(p, label = '&Menu')
     self.search_label = wx.StaticText(p, label = SEARCH_LABEL)
     self.search = wx.TextCtrl(p, style = wx.TE_PROCESS_ENTER)
     self.search.Bind(wx.EVT_TEXT_ENTER, self.on_text_enter)
     s1.AddMany([
         (self.previous, 0, wx.GROW),
         (self.play, 0, wx.GROW),
         (self.next, 0, wx.GROW),
         (self.menu, 0, wx.GROW),
         (self.search_label, 0, wx.GROW),
         (self.search, 1, wx.GROW)
     ])
     s2 = wx.BoxSizer(wx.HORIZONTAL)
     vs = wx.BoxSizer(wx.VERTICAL)
     vs.Add(wx.StaticText(p, label = '&Tracks'), 0, wx.GROW)
     self.view = wx.ListBox(p)
     add_accelerator(self.view, 'RETURN', self.on_activate)
     self.view.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.on_activate)
     add_accelerator(self.view, 'SPACE', self.play_pause)
     self.view.Bind(wx.EVT_LISTBOX_DCLICK, self.on_activate)
     self.view.SetFocus()
     self.view.Bind(wx.EVT_CONTEXT_MENU, self.on_context)
     if sys.platform == 'darwin':
         add_accelerator(self.view, 'SHIFT+F10', self.on_context)
     vs.Add(self.view, 1, wx.GROW)
     ls = wx.BoxSizer(wx.VERTICAL)
     ls.Add(wx.StaticText(p, label = '&Lyrics'), 0, wx.GROW)
     self.lyrics = wx.TextCtrl(p, value = 'Play a song to view lyrics.', style = wx.TE_MULTILINE | wx.TE_READONLY)
     ls.Add(self.lyrics, 1, wx.GROW)
     ls.Add(wx.StaticText(p, label = 'Artist &Biography'), 0, wx.GROW)
     self.artist_bio = wx.TextCtrl(p, style = wx.TE_MULTILINE | wx.TE_READONLY)
     ls.Add(self.artist_bio, 0, wx.GROW)
     s2.AddMany([
         (vs, 1, wx.GROW),
         (ls, 1, wx.GROW),
     ])
     s3 = wx.BoxSizer(wx.HORIZONTAL)
     s3.Add(wx.StaticText(p, label = '&Volume'), 0, wx.GROW)
     self.volume = wx.Slider(p, value = config.system['volume'], style = wx.SL_VERTICAL)
     self.volume.Bind(wx.EVT_SLIDER, lambda event: set_volume(self.volume.GetValue()))
     s3.Add(self.volume, 1, wx.GROW)
     s3.Add(wx.StaticText(p, label = '&Position'), 0, wx.GROW)
     self.position= wx.Slider(p, style = wx.SL_HORIZONTAL)
     self.position.Bind(wx.EVT_SLIDER, lambda event: application.stream.set_position((int(application.stream.get_length() / 100) * self.position.GetValue())) if not isinstance(application.track, URLStream) and application.stream else None)
     add_accelerator(self, 'SHIFT+LEFT', self.rewind)
     add_accelerator(self, 'SHIFT+RIGHT', self.fastforward)
     self.position_timer = wx.Timer(self)
     self.Bind(wx.EVT_TIMER, self.play_manager, self.position_timer)
     self.position_timer.Start(50)
     s.AddMany([
         (s1, 0, wx.GROW),
         (s2, 1, wx.GROW),
         (s3, 0, wx.GROW),
     ])
     p.SetSizerAndFit(s)
     self.SetTitle()
     self.Bind(wx.EVT_CLOSE, self.on_close)
     self.Bind(wx.EVT_SHOW, self.on_show)
     self.playlists = {} # A list of playlist: id key: value pairs.
     self.stations = {} # The same as .playlists except for radio stations.
     self.status = self.CreateStatusBar()
     self.status.SetStatusText('Nothing playing yet')
     add_accelerator(self, 'CTRL+R', self.cycle_repeat)
     self.getting_stream_title = False
Пример #13
0
 def __init__(self):
  application.frame = self
  self.last_review = [0.0, None, None]
  super(MainFrame, self).__init__(None, title = application.name)
  self._review = 0 # The current position of the review cursor.
  self.commands = [] # Command history.
  self._command_pos = 0 # The current position in the command history.
  p = wx.Panel(self)
  self.CreateStatusBar()
  self.SetStatusText('Not connected.')
  s = wx.BoxSizer(wx.VERTICAL)
  self.output = MyTextCtrl(p, style = wx.TE_READONLY | wx.TE_MULTILINE)
  s.Add(self.output, 1, wx.GROW)
  s1 = wx.BoxSizer(wx.HORIZONTAL)
  self.prompt = wx.StaticText(p, label = '&Entry')
  s1.Add(self.prompt, 0, wx.GROW)
  self.entry = wx.TextCtrl(p, style = wx.TE_RICH2)
  self.entry.SetFocus()
  s1.Add(self.entry, 1, wx.GROW)
  s.Add(s1, 0, wx.GROW)
  p.SetSizerAndFit(s)
  keys.add_accelerator(self.entry, 'RETURN', self.do_send)
  keys.add_accelerator(self.entry, 'ESCAPE', lambda event: self.do_clear(save = True))
  keys.add_accelerator(self.entry, 'UP', lambda event: self.do_command_history(self._command_pos - 1)) # Commands are entered using append.
  keys.add_accelerator(self.entry, 'DOWN', lambda event: self.do_command_history(self._command_pos + 1))
  keys.add_accelerator(self.entry, 'CTRL+HOME', lambda event: self.do_command_history(-1))
  keys.add_accelerator(self.entry, 'CTRL+END', lambda event: self.do_command_history(0))
  keys.add_accelerator(self.entry, 'SHIFT+RETURN', lambda event: self.do_send(event, clear = False))
  keys.add_accelerator(self.entry, 'CTRL+RETURN', lambda event: functions.send(self.commands[0]) if self.commands else functions.bell())
  for x in xrange(10):
   keys.add_accelerator(self, 'ALT+%s' % x, lambda event, i = x: self.do_review(-10 if not i else (i * -1), move = False))
   keys.add_accelerator(self, 'ALT+%s' % x, lambda event, i = x: self.output.SpeakLineText(10 if not i else i))
  keys.add_accelerator(self, 'CTRL+SHIFT+Y', lambda event: self.do_review(0))
  keys.add_accelerator(self, 'CTRL+SHIFT+P', lambda event: self.do_review(-1))
  keys.add_accelerator(self, 'CTRL+SHIFT+U', lambda event: self.do_review(max(self._review - 1, 0)))
  keys.add_accelerator(self, 'CTRL+SHIFT+I', lambda event: self.do_review(self._review))
  keys.add_accelerator(self, 'CTRL+SHIFT+O', lambda event: self.do_review(self._review + 1))
  functions.output('Welcome to %s (V%s).\nType %scommands() for help with builtin functions.' % (application.name, application.version, application.config.get('application', 'command_char')))
  mb = wx.MenuBar()
  self.file_menu = wx.Menu()
  self.Bind(wx.EVT_MENU, self.do_load, self.file_menu.Append(wx.ID_ANY, '&Load Script...', 'Load a script.'))
  self.Bind(wx.EVT_MENU, lambda event: application.config.get_gui().Show(True), self.file_menu.Append(wx.ID_PREFERENCES, '&Preferences...', 'Change program configuration.'))
  self.Bind(wx.EVT_MENU, lambda event: functions.quit(), self.file_menu.Append(wx.ID_EXIT, '&Quit', 'Quit the program.'))
  mb.Append(self.file_menu, '&File')
  self.connect_menu = wx.Menu()
  self.Bind(wx.EVT_MENU, lambda event: do_connect(), self.connect_menu.Append(wx.ID_ANY, '&Connect...', 'Create a new connection.'))
  self.Bind(wx.EVT_MENU, lambda event: functions.disconnect(), self.connect_menu.Append(wx.ID_ANY, '&Disconnect', 'Disconnect from the MUD.'))
  mb.Append(self.connect_menu, '&Connect')
  self.SetMenuBar(mb)
  self.Bind(wx.EVT_CLOSE, self.on_close)