+(defclass base-mode ()
+ ((connection :initarg :connection :accessor connection)))
+(defclass init-mode (base-mode)
+ ((play-sent-p :initform nil
+ :documentation "Have we already sent the play command?")))
+(defclass play-mode (base-mode) nil)
+
+(defun make-mode (connection mode)
+ (make-instance mode :connection connection))
+
+(defgeneric set-new-mode (base-mode new-mode))
+(defmethod set-new-mode ((m base-mode) new-mode)
+ (let* ((c (connection m))
+ (mode (make-mode c new-mode)))
+ (setf (connection-mode c) mode)))
+
+(defgeneric handle-data (base-mode message))
+(defgeneric handle-init (base-mode message))
+(defgeneric handle-exit (base-mode message))
+(defgeneric handle-prompt (base-mode message))
+(defgeneric handle-flush (base-mode message))
+(defgeneric handle-simple-message (base-mode message))
+
+(defmethod handle-init ((m init-mode) message)
+ (declare (ignorable message))
+ (with-slots (play-sent-p) m
+ (if (not play-sent-p)
+ (progn
+ (play (connection m))
+ (setf play-sent-p t))
+ (set-new-mode m 'play-mode))))
+
+(defmethod handle-exit ((m init-mode) message)
+ (declare (ignorable message))
+ (quit (connection m)))
+
+(defmethod handle-exit ((m play-mode) message)