def graphics(self, stdscr):
    self.stdscr = stdscr
    self.my, self.mx = self.stdscr.getmaxyx()
    self.height = 4
    self.width = self.mx - 30
    self.posy = int(self.my / 2.0 - self.height / 2.0)
    self.posx = int(self.mx / 2.0 - self.width / 2.0)

    self.midipad = curses.newpad(self.height, 1) 
    self.annotationpad = curses.newpad(self.height, 1)
    self.com_buffer = curses.newwin(1, self.width, self.posy, self.posx)

    self.buf = ''
    self.stdscr.refresh()

    if annotationcorpus.exists('autosave', 'autosave'):
      if cgui.menu(self.stdscr, 'Annotator quit unexpectedly. Restore last session?', ['Yes', 'No']) == 0:
        self.load('autosave', 'autosave')

    while True:
      exp = re.compile(r'(?P<repetitions>[0-9]+)?(?P<action>[iqpsx ])$|:(?P<command>set |play|stop|pause|save|strip|subtract|q|load|score|restore)(?P<arg1>resolution|correction|beatsperbar|beatdiv)?(?P<arg2> (-)?[0-9]+)?\n$')
      if self.mode == self.INSERT:
        exp = re.compile(r'(?P<command>[ wsrge]|t(?P<arg>[0-9]+))$') 
      # Check if the buffer contains a command
      m = exp.match(self.buf)
      if m:
        if not self.execute(m):
          break
        self.buf = ''

      self.updateScr(self.stdscr)
      c = self.stdscr.getch()
      if c == curses.ERR: continue
      self.status = ''

      if c == 27: # or c == curses.KEY_BACKSPACE:
        if self.mode == self.INSERT:
          self.mode = self.ANNOTATING
          self.status = 'Leaving insert mode'
        # Empty buffer
        self.buf = ''
      elif c == curses.KEY_BACKSPACE:
        # Empty buffer
        self.buf = ''
      elif c == curses.KEY_LEFT:
        self.curs_left()
      elif c == curses.KEY_RIGHT:
        self.curs_right()
      elif c == curses.KEY_UP and self.mode != self.INSERT:
        if self.mode == self.ANNOTATING:
          self.mode = self.PLAYING
      elif c == curses.KEY_DOWN and self.mode != self.INSERT:
        if self.mode == self.PLAYING:
          self.mode = self.ANNOTATING
      else:
        if c in range(32, 128) + [10]:
          self.buf += chr(c)
 def annotator(self):
   # Initialise sequencer
   self.seq.start()
   self.seq.control(self.seq.LOADFILE, self.midifile)
   self.seq.control(self.seq.LOADTRACK, 1)
   self.seq.control(self.seq.SETOUTPUT, 0)
   # Start gui
   try:
     curses.wrapper(self.graphics)
     if annotationcorpus.exists('autosave', 'autosave'):
       annotationcorpus.remove('autosave', 'autosave')
       self.save('autosave', 'lastsession', force=True)
   finally:
     # Make sure to stop the sequencer 
     self.seq.control(self.seq.QUIT, None)
 def save(self, collection=None, name=None, force=False):
   """Save the annotation to the corpus"""
   if not collection:
     choice = cgui.menu(self.stdscr, 'Collection', annotationcorpus.collections() + ['Add new collection'])
     if choice == -1: return
     elif choice == len(annotationcorpus.collections()):
       collection = cgui.prompt(self.stdscr, 'Collection?')
     else: collection = annotationcorpus.collections()[choice]
   
   if not name:
     name = self.name
   metadata = {'beatdiv':self.meter.beatdiv, 'beatspb':self.meter.beatspb, 'offset':self.offset, 'bpm':self.bpm, 'name':self.name}
   if annotationcorpus.exists(collection, name) and not force:
     if cgui.menu(self.stdscr, 'Item exists, overwrite?', ['No', 'Yes']) != 1: return
   annotationcorpus.save(collection, name, metadata, sorted(self.annotations, key=lambda x: x[0]), self.notelist, self.midifile)