m๒
} Cc           @   s  d  Z  d k Z d k Z d k Z d k Z d k Z d k Z d k Z d k Td k	 Td k TyO e i
 i e i i e i e i    d d d g   d k l Z l Z Wn n Xy# d k l Z e i d d	  Z Wn6 d Z d
 GHy d k l Z Wqe d  qXn Xe Z d   Z d f  d     YZ d e f d     YZ d e  f d     YZ! d e" f d     YZ# e$ d j o e# i% e#    n d S(   s7  
    pyano.py - funky keyboard to help write lilypond source
    Copyright (C) 2004  John Comeau <jc@jcomeau.com>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
    N(   t   *i   t   libt   python(   s   gpls	   jclicense(   s   pymidis	   /dev/midit   wbs;   pymidi module is preferred, fetch from http://jcomeau.com/.(   s   beeps5   Must have either pymidi (preferred) or beep installedc         C   s   t  o	 |  GHn d  S(   N(   t   debugt   string(   R   (    (    t   pyano.pyt   dbgprint.   s    t   keymapc        #   B   sฮ   t  Z d  Z h  d d d d d d d d d	 d
 d d d g d f <d d; <d d d d d  d! d" d# d$ d% d& d' d( d) g f <d* d+ d, d- d. d/ d0 d1 d2 d3 d4 d5 d6 g d7 d8 g f <Z d< Z d9 d:  Z RS(=   s>   Create and pack buttons according to selected keyboard scheme.i    t   1t   2t   3t   4t   5t   6t   7t   8t   9t   0t   -t   minust   =i   t   Qt   Wt   Et   Rt   Tt   Yt   Ut   It   Ot   Pt   [t   ]i   t   At   St   Dt   Ft   Gt   Ht   Jt   Kt   Lt   ;t   'u   โt   Returni   t   Zt   Xt   Ct   Vt   Bt   Nt   Mt   ,t   .t   /u   โt   Upu   โฒt   Shift_Rt   qwertyc         C   sง   | |  _ | d j o x t d d  D]u } xl t d d  D][ } |  i | | } | d | } t
 | | |  | i | <| i | i h  d d < q< Wq& Wn d  S(   NR:   i    i   i   t   sidet   left(   t   mastert   selft   parentt   mappingt   ranget   rowt   keyR:   t   textt   valuet   pyanokeyt   buttont   pack(   R>   R=   R@   RD   RE   RC   RB   (    (    R   t   __init__F   s    	  (   R   R   R   R   R   R   R   R   R   R   R    R!   (#   R	   R
   R   R   R   R   R   R"   R2   R0   R$   R   R%   R&   R'   R   R(   R)   R*   R4   R3   R   R   R   R   R#   R   R   R1   R   R/   R   R.   R5   R6   (   t   __name__t
   __module__t   __doc__R:   t   alphabetRI   (    (    (    R   R   4   s    ฎ
RF   c           B   s2   t  Z d  Z e Z e d  Z d   Z d   Z RS(   sJ  Create a button capable of playing a note.

    Also binds the corresponding key to the same note in the root window,
    which is assumed to be the parent widget's parent. NOTE that clicking
    in this window will cause all remaining keyboard hits to echo the key's
    character in addition to the lilypond note representation.c         C   s  d }	 d d d d g } t i |  |  | |  _ | i }
 t | d  | d } } |	 | | | |  _ d |  _ | d  j ot | t  o& | \ } } t d | d |  n | | } } | |  d <| d j o: |
 i d | d |  i  |
 i d | d |  i  n t |  d j oY | | i   j oF |
 i d | i   d |  i  |
 i d | i   d |  i  qn |  i |  d <t t  t j o t i | | f |  _ n d d | d | |  _ |  i d |  i  |  i d |  i  d  S(   Nt   ct   dft   dt   eft   et   ft   gft   gt   aft   at   bft   bR5   t    R,   s   ''i   i    s   list: s   , RD   R9   s
   <KeyPress-t   >s   <KeyRelease-i   i   s   <ButtonRelease-1>s   <1>(   RN   RO   RP   RQ   RR   RS   RT   RU   RV   RW   RX   RY   (    t	   lilynotest
   lilymarkupt   ButtonRI   R>   R=   R?   t   roott   intRE   t   octavet   notet   lilynotet   countRC   t   Nonet
   isinstancet   listRD   t   X11keyR   t   bindt   playt   stopplayt   lent   lowert   typet   midioutt   NoneTypet   beept   notest   tone(   R>   R=   RE   RC   RD   R]   Rb   Ra   Rh   R\   R_   (    (    R   RI   Z   s4    			
&!)c         C   sฌ   t  t  t j	 o  t i t d |  i d g  n |  i o t d t	 |    nT t
 |  _ t d t	 |    |  i i } | i i   | i i |   | i i   d S(   s   Queue a note to start playing.i   i@   s   already playing: s   play: N(   Rn   Ro   Rp   t   pymidit   writeR>   Rs   t   isactiveR   t   reprt   TrueR?   R_   t   playlockt   acquiret   notelistt   appendt   release(   R>   t   eventR_   (    (    R   Rj   |   s      
	c         C   s   t  d t |    t t  t j	 o  t i t d |  i d g  n t	 |  _
 |  i i } | i i   | i i |   | i i   d S(   s)   Remove this button's note from the queue.s
   stopplay: i   i@   N(   R   Rw   R>   Rn   Ro   Rp   Rt   Ru   Rs   t   FalseRv   R?   R_   Ry   Rz   R{   t   removeR}   (   R>   R~   R_   (    (    R   Rk      s      	(	   RJ   RK   RL   R   Rv   Re   RI   Rj   Rk   (    (    (    R   RF   P   s
    "	t   pyanokeyboardc           B   s   t  Z d  Z d   Z RS(   s>   A frame to hold the graphical representation of the pyano keysc         C   s6   t  i |  |  | |  _ t   |  _ t |  d  d  S(   NR:   (   t   FrameRI   R>   R=   R?   t   dictRG   R   (   R>   R=   (    (    R   RI      s    	(   RJ   RK   RL   RI   (    (    (    R   R      s    t   pyanoc           B   sv   t  Z d  Z e Z g  Z e Z d Z e o d Z	 d Z
 n d Z	 d Z
 e Z e d  Z d   Z d   Z d	   Z RS(
   s   Root window of the applicationi    f0.10000000000000001i   f0.050000000000000003i   c         C   sX   t  i |  |  t |  h  d t < |  _ t |   |  _ |  i i	   |  i i	   d S(   s   Put everything togethert   undoN(
   t   TkRI   R>   R=   t   ScrolledTextRx   t   textboxR   t   keyboardRH   (   R>   R=   (    (    R   RI   ฌ   s     c         C   sG   |  } | i d  |  i d |  i  t i |  i f   | i   d S(   s	  Get everything running.

        Binding 'Destroy' to the 'pleasestop' method solved the problem
        of the application being difficult to shut down; clicking the
        big red button just left it churning away, and WinXT had to
        force it to shut down.t   Pyanos	   <Destroy>N(	   R>   t   appt   titleRi   t
   pleasestopt   threadt   start_new_threadt   pyanoplayert   mainloop(   R>   R   (    (    R   t   mainด   s     c         C   s   t  |  _ t i d  d S(   s?   Just set a boolean variable that child threads need to monitor.i    N(   Rx   R>   t   stoppedt   syst   exit(   R>   t   reason(    (    R   R   ม   s     	c         C   s|  yGt  i   |  _ x$|  i pt d t |  i   t d t |  i   t d t	 |  i
   |  i i   t |  i  d j oว |  i |  i d j o |  i d j o? |  i
 |  i j  o t d  |  i i   qํ |  i i   n |  i d |  _ d |  _
 |  i i |  i i d  |  i d i d f   qฏ|  i
 d |  _
 nb |  i d j oQ d |  _ |  i
 |  i j  o t d	  |  i i   n |  i i   d |  _
 n |  i i   t t  t j oK |  i d j o; t d
 |  i i  t i |  i i |  i  t d  q t d  t i |  i  q Wt i d  Wn. t d t t  i!     t  i d  n Xd S(   sแ  Watch the note queue, play music and update textbox.

        This is the main workhorse of the program, and it is really
        crappy. It would be much better to find a way to access the
        standard MIDI function of the sound card, and send MIDI 'on'
        and 'off' messages to it. For the Windows 'Beep' service
        to work you have to know in advance the duration of the beep,
        which procludes a real-time response except for a kludge
        like this one.s
   notelist: s   activenote: s
   duration: i    s   deleting before new notet   endt    i   s   deleting, no new notes   playing note: s   done playing notes!   nothing to play, sleeping insteads   exception receivedN("   R   t   allocate_lockR>   Ry   R   R   Rw   R{   t
   activenotet   strt   durationRz   Rl   Re   t	   thresholdR   t	   edit_undot
   edit_resett   insertt   indexRc   R}   Rn   Ro   Rp   Rq   Rs   t   intervalt   timet   sleept   systemR   R   t   exc_info(   R>   (    (    R   R   ฦ   sN    	  

		
#
(   RJ   RK   RL   Re   Ry   R{   R   R   R   Rข   R   R   R   RI   R   R   R   (    (    (    R   R      s    
		t   __main__(&   t	   CopyrightR   Rฃ   R   t   ost   typest   ret   pwdt   TkinterR   t   pathR|   t   sept   joint   getpwuidt   geteuidt   com.jcomeaut   gplt	   jclicenset   com.jcomeau.midiRt   t   openRo   Re   Rq   t	   ExceptionR   R   R   R   R^   RF   R   R   R   R   RJ   R   (   Rt   Rจ   R   RF   Rด   Ro   Rq   Rซ   Rต   R   R   Rฌ   Rช   R   R   R   Rฃ   R   Rฉ   (    (    R   t   ?   s8   ?8	E_ 