packages feed

Euterpea 2.0.4 → 2.0.5

raw patch · 122 files changed

+224/−117 lines, 122 filesdep ~PortMidibinary-addedPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: PortMidi

API changes (from Hackage documentation)

+ Euterpea.IO.MIDI.ToMidi2: resolveInstrumentName :: InstrumentName -> InstrumentName
+ Euterpea.IO.MIDI.ToMidi2: writeMidi2 :: ToMusic1 a => FilePath -> Music a -> IO ()
+ Euterpea.Music: instance Euterpea.Music.ToMusic1 (Euterpea.Music.AbsPitch, Euterpea.Music.Volume)
- Euterpea: importFile :: FilePath -> IO (Either String Midi)
+ Euterpea: importFile :: FilePath -> IO Either String Midi
- Euterpea.IO.Audio: writeWav :: (ToMusic1 a1, Clock p, AudioSample a) => String -> InstrMap (Signal p () a) -> Music a1 -> IO ()
+ Euterpea.IO.Audio: writeWav :: (Clock p, ToMusic1 a2, AudioSample a1) => String -> InstrMap Signal p () a1 -> Music a2 -> IO ()
- Euterpea.IO.Audio: writeWavNorm :: (ToMusic1 a1, Clock p, AudioSample a) => String -> InstrMap (Signal p () a) -> Music a1 -> IO ()
+ Euterpea.IO.Audio: writeWavNorm :: (Clock p, ToMusic1 a2, AudioSample a1) => String -> InstrMap Signal p () a1 -> Music a2 -> IO ()
- Euterpea.IO.Audio.CSound: oscil :: (ArrowCircuit a, Clock p) => Table -> Double -> ArrowP a p Double Double
+ Euterpea.IO.Audio.CSound: oscil :: (Clock p, ArrowCircuit a) => Table -> Double -> ArrowP a p Double Double
- Euterpea.IO.Audio.CSound: oscil1 :: (ArrowCircuit a, ArrowChoice a, Clock p) => Table -> Double -> Double -> ArrowP a p Double Double
+ Euterpea.IO.Audio.CSound: oscil1 :: (Clock p, ArrowChoice a, ArrowCircuit a) => Table -> Double -> Double -> ArrowP a p Double Double
- Euterpea.IO.Audio.CSound: oscil1i :: (ArrowCircuit a, ArrowChoice a, Clock p) => Table -> Double -> Double -> ArrowP a p Double Double
+ Euterpea.IO.Audio.CSound: oscil1i :: (Clock p, ArrowChoice a, ArrowCircuit a) => Table -> Double -> Double -> ArrowP a p Double Double
- Euterpea.IO.Audio.CSound: oscili :: (ArrowCircuit a, Clock p) => Table -> Double -> ArrowP a p Double Double
+ Euterpea.IO.Audio.CSound: oscili :: (Clock p, ArrowCircuit a) => Table -> Double -> ArrowP a p Double Double
- Euterpea.IO.Audio.CSound: oscils :: (ArrowCircuit a, Clock p) => Double -> ArrowP a p Double Double
+ Euterpea.IO.Audio.CSound: oscils :: (Clock p, ArrowCircuit a) => Double -> ArrowP a p Double Double
- Euterpea.IO.Audio.CSound: rand :: Int -> ArrowP SF p Double Double
+ Euterpea.IO.Audio.CSound: rand :: () => Int -> ArrowP SF p Double Double
- Euterpea.IO.MIDI: ChannelPrefix :: ~Channel -> Message
+ Euterpea.IO.MIDI: ChannelPrefix :: !Channel -> Message
- Euterpea.IO.MIDI: ChannelPressure :: ~Channel -> ~Pressure -> Message
+ Euterpea.IO.MIDI: ChannelPressure :: !Channel -> !Pressure -> Message
- Euterpea.IO.MIDI: ControlChange :: ~Channel -> ~Int -> ~Int -> Message
+ Euterpea.IO.MIDI: ControlChange :: !Channel -> !Int -> !Int -> Message
- Euterpea.IO.MIDI: Copyright :: ~String -> Message
+ Euterpea.IO.MIDI: Copyright :: !String -> Message
- Euterpea.IO.MIDI: CuePoint :: ~String -> Message
+ Euterpea.IO.MIDI: CuePoint :: !String -> Message
- Euterpea.IO.MIDI: DeviceName :: ~String -> Message
+ Euterpea.IO.MIDI: DeviceName :: !String -> Message
- Euterpea.IO.MIDI: InstrumentName :: ~String -> Message
+ Euterpea.IO.MIDI: InstrumentName :: !String -> Message
- Euterpea.IO.MIDI: KeyPressure :: ~Channel -> ~Key -> ~Pressure -> Message
+ Euterpea.IO.MIDI: KeyPressure :: !Channel -> !Key -> !Pressure -> Message
- Euterpea.IO.MIDI: KeySignature :: ~Int -> ~Int -> Message
+ Euterpea.IO.MIDI: KeySignature :: !Int -> !Int -> Message
- Euterpea.IO.MIDI: Lyrics :: ~String -> Message
+ Euterpea.IO.MIDI: Lyrics :: !String -> Message
- Euterpea.IO.MIDI: Marker :: ~String -> Message
+ Euterpea.IO.MIDI: Marker :: !String -> Message
- Euterpea.IO.MIDI: NoteOff :: ~Channel -> ~Key -> ~Velocity -> Message
+ Euterpea.IO.MIDI: NoteOff :: !Channel -> !Key -> !Velocity -> Message
- Euterpea.IO.MIDI: NoteOn :: ~Channel -> ~Key -> ~Velocity -> Message
+ Euterpea.IO.MIDI: NoteOn :: !Channel -> !Key -> !Velocity -> Message
- Euterpea.IO.MIDI: PitchWheel :: ~Channel -> ~PitchWheel -> Message
+ Euterpea.IO.MIDI: PitchWheel :: !Channel -> !PitchWheel -> Message
- Euterpea.IO.MIDI: ProgramChange :: ~Channel -> ~Preset -> Message
+ Euterpea.IO.MIDI: ProgramChange :: !Channel -> !Preset -> Message
- Euterpea.IO.MIDI: ProgramName :: ~String -> Message
+ Euterpea.IO.MIDI: ProgramName :: !String -> Message
- Euterpea.IO.MIDI: Reserved :: ~Int -> ~ByteString -> Message
+ Euterpea.IO.MIDI: Reserved :: !Int -> !ByteString -> Message
- Euterpea.IO.MIDI: SMPTEOffset :: ~Int -> ~Int -> ~Int -> ~Int -> ~Int -> Message
+ Euterpea.IO.MIDI: SMPTEOffset :: !Int -> !Int -> !Int -> !Int -> !Int -> Message
- Euterpea.IO.MIDI: SequenceNumber :: ~Int -> Message
+ Euterpea.IO.MIDI: SequenceNumber :: !Int -> Message
- Euterpea.IO.MIDI: Sysex :: ~Int -> ~ByteString -> Message
+ Euterpea.IO.MIDI: Sysex :: !Int -> !ByteString -> Message
- Euterpea.IO.MIDI: TempoChange :: ~Tempo -> Message
+ Euterpea.IO.MIDI: TempoChange :: !Tempo -> Message
- Euterpea.IO.MIDI: Text :: ~String -> Message
+ Euterpea.IO.MIDI: Text :: !String -> Message
- Euterpea.IO.MIDI: TimeSignature :: ~Int -> ~Int -> ~Int -> ~Int -> Message
+ Euterpea.IO.MIDI: TimeSignature :: !Int -> !Int -> !Int -> !Int -> Message
- Euterpea.IO.MIDI: TrackName :: ~String -> Message
+ Euterpea.IO.MIDI: TrackName :: !String -> Message
- Euterpea.IO.MIDI: [channel] :: Message -> ~Channel
+ Euterpea.IO.MIDI: [channel] :: Message -> !Channel
- Euterpea.IO.MIDI: [controllerNumber] :: Message -> ~Int
+ Euterpea.IO.MIDI: [controllerNumber] :: Message -> !Int
- Euterpea.IO.MIDI: [controllerValue] :: Message -> ~Int
+ Euterpea.IO.MIDI: [controllerValue] :: Message -> !Int
- Euterpea.IO.MIDI: [key] :: Message -> ~Key
+ Euterpea.IO.MIDI: [key] :: Message -> !Key
- Euterpea.IO.MIDI: [pitchWheel] :: Message -> ~PitchWheel
+ Euterpea.IO.MIDI: [pitchWheel] :: Message -> !PitchWheel
- Euterpea.IO.MIDI: [preset] :: Message -> ~Preset
+ Euterpea.IO.MIDI: [preset] :: Message -> !Preset
- Euterpea.IO.MIDI: [pressure] :: Message -> ~Pressure
+ Euterpea.IO.MIDI: [pressure] :: Message -> !Pressure
- Euterpea.IO.MIDI: [velocity] :: Message -> ~Velocity
+ Euterpea.IO.MIDI: [velocity] :: Message -> !Velocity
- Euterpea.IO.MIDI: data DeviceInfo :: *
+ Euterpea.IO.MIDI: data DeviceInfo
- Euterpea.IO.MIDI: data Message :: *
+ Euterpea.IO.MIDI: data Message
- Euterpea.IO.MIDI.MidiIO: ChannelPrefix :: ~Channel -> Message
+ Euterpea.IO.MIDI.MidiIO: ChannelPrefix :: !Channel -> Message
- Euterpea.IO.MIDI.MidiIO: ChannelPressure :: ~Channel -> ~Pressure -> Message
+ Euterpea.IO.MIDI.MidiIO: ChannelPressure :: !Channel -> !Pressure -> Message
- Euterpea.IO.MIDI.MidiIO: ControlChange :: ~Channel -> ~Int -> ~Int -> Message
+ Euterpea.IO.MIDI.MidiIO: ControlChange :: !Channel -> !Int -> !Int -> Message
- Euterpea.IO.MIDI.MidiIO: Copyright :: ~String -> Message
+ Euterpea.IO.MIDI.MidiIO: Copyright :: !String -> Message
- Euterpea.IO.MIDI.MidiIO: CuePoint :: ~String -> Message
+ Euterpea.IO.MIDI.MidiIO: CuePoint :: !String -> Message
- Euterpea.IO.MIDI.MidiIO: DeviceName :: ~String -> Message
+ Euterpea.IO.MIDI.MidiIO: DeviceName :: !String -> Message
- Euterpea.IO.MIDI.MidiIO: InstrumentName :: ~String -> Message
+ Euterpea.IO.MIDI.MidiIO: InstrumentName :: !String -> Message
- Euterpea.IO.MIDI.MidiIO: KeyPressure :: ~Channel -> ~Key -> ~Pressure -> Message
+ Euterpea.IO.MIDI.MidiIO: KeyPressure :: !Channel -> !Key -> !Pressure -> Message
- Euterpea.IO.MIDI.MidiIO: KeySignature :: ~Int -> ~Int -> Message
+ Euterpea.IO.MIDI.MidiIO: KeySignature :: !Int -> !Int -> Message
- Euterpea.IO.MIDI.MidiIO: Lyrics :: ~String -> Message
+ Euterpea.IO.MIDI.MidiIO: Lyrics :: !String -> Message
- Euterpea.IO.MIDI.MidiIO: Marker :: ~String -> Message
+ Euterpea.IO.MIDI.MidiIO: Marker :: !String -> Message
- Euterpea.IO.MIDI.MidiIO: NoteOff :: ~Channel -> ~Key -> ~Velocity -> Message
+ Euterpea.IO.MIDI.MidiIO: NoteOff :: !Channel -> !Key -> !Velocity -> Message
- Euterpea.IO.MIDI.MidiIO: NoteOn :: ~Channel -> ~Key -> ~Velocity -> Message
+ Euterpea.IO.MIDI.MidiIO: NoteOn :: !Channel -> !Key -> !Velocity -> Message
- Euterpea.IO.MIDI.MidiIO: PitchWheel :: ~Channel -> ~PitchWheel -> Message
+ Euterpea.IO.MIDI.MidiIO: PitchWheel :: !Channel -> !PitchWheel -> Message
- Euterpea.IO.MIDI.MidiIO: ProgramChange :: ~Channel -> ~Preset -> Message
+ Euterpea.IO.MIDI.MidiIO: ProgramChange :: !Channel -> !Preset -> Message
- Euterpea.IO.MIDI.MidiIO: ProgramName :: ~String -> Message
+ Euterpea.IO.MIDI.MidiIO: ProgramName :: !String -> Message
- Euterpea.IO.MIDI.MidiIO: Reserved :: ~Int -> ~ByteString -> Message
+ Euterpea.IO.MIDI.MidiIO: Reserved :: !Int -> !ByteString -> Message
- Euterpea.IO.MIDI.MidiIO: SMPTEOffset :: ~Int -> ~Int -> ~Int -> ~Int -> ~Int -> Message
+ Euterpea.IO.MIDI.MidiIO: SMPTEOffset :: !Int -> !Int -> !Int -> !Int -> !Int -> Message
- Euterpea.IO.MIDI.MidiIO: SequenceNumber :: ~Int -> Message
+ Euterpea.IO.MIDI.MidiIO: SequenceNumber :: !Int -> Message
- Euterpea.IO.MIDI.MidiIO: Sysex :: ~Int -> ~ByteString -> Message
+ Euterpea.IO.MIDI.MidiIO: Sysex :: !Int -> !ByteString -> Message
- Euterpea.IO.MIDI.MidiIO: TempoChange :: ~Tempo -> Message
+ Euterpea.IO.MIDI.MidiIO: TempoChange :: !Tempo -> Message
- Euterpea.IO.MIDI.MidiIO: Text :: ~String -> Message
+ Euterpea.IO.MIDI.MidiIO: Text :: !String -> Message
- Euterpea.IO.MIDI.MidiIO: TimeSignature :: ~Int -> ~Int -> ~Int -> ~Int -> Message
+ Euterpea.IO.MIDI.MidiIO: TimeSignature :: !Int -> !Int -> !Int -> !Int -> Message
- Euterpea.IO.MIDI.MidiIO: TrackName :: ~String -> Message
+ Euterpea.IO.MIDI.MidiIO: TrackName :: !String -> Message
- Euterpea.IO.MIDI.MidiIO: [channel] :: Message -> ~Channel
+ Euterpea.IO.MIDI.MidiIO: [channel] :: Message -> !Channel
- Euterpea.IO.MIDI.MidiIO: [controllerNumber] :: Message -> ~Int
+ Euterpea.IO.MIDI.MidiIO: [controllerNumber] :: Message -> !Int
- Euterpea.IO.MIDI.MidiIO: [controllerValue] :: Message -> ~Int
+ Euterpea.IO.MIDI.MidiIO: [controllerValue] :: Message -> !Int
- Euterpea.IO.MIDI.MidiIO: [key] :: Message -> ~Key
+ Euterpea.IO.MIDI.MidiIO: [key] :: Message -> !Key
- Euterpea.IO.MIDI.MidiIO: [pitchWheel] :: Message -> ~PitchWheel
+ Euterpea.IO.MIDI.MidiIO: [pitchWheel] :: Message -> !PitchWheel
- Euterpea.IO.MIDI.MidiIO: [preset] :: Message -> ~Preset
+ Euterpea.IO.MIDI.MidiIO: [preset] :: Message -> !Preset
- Euterpea.IO.MIDI.MidiIO: [pressure] :: Message -> ~Pressure
+ Euterpea.IO.MIDI.MidiIO: [pressure] :: Message -> !Pressure
- Euterpea.IO.MIDI.MidiIO: [velocity] :: Message -> ~Velocity
+ Euterpea.IO.MIDI.MidiIO: [velocity] :: Message -> !Velocity
- Euterpea.IO.MIDI.MidiIO: data DeviceInfo :: *
+ Euterpea.IO.MIDI.MidiIO: data DeviceInfo
- Euterpea.IO.MIDI.MidiIO: data Message :: *
+ Euterpea.IO.MIDI.MidiIO: data Message
- Euterpea.IO.MIDI.Play: PlayParams :: Bool -> ChannelMapFun -> Maybe OutputDeviceID -> Time -> (Music1 -> [MEvent]) -> PlayParams
+ Euterpea.IO.MIDI.Play: PlayParams :: Bool -> ChannelMapFun -> Maybe OutputDeviceID -> Time -> Music1 -> [MEvent] -> PlayParams
- Euterpea.IO.MIDI.ToMidi: toDelta :: (Integral b, RealFrac a) => a -> b
+ Euterpea.IO.MIDI.ToMidi: toDelta :: (RealFrac a, Integral b) => a -> b

Files

.git/COMMIT_EDITMSG view
@@ -1,1 +1,3 @@-Binary encoding fixes.+EnableGUI reference removed++Refernece removed to a file that no longer exists in Euterpea2.
.git/FETCH_HEAD view
@@ -1,1 +1,1 @@-02f0974406cb38a71a2bdfe8204e87bd0cd03892		branch 'master' of https://github.com/Euterpea/Euterpea2+77a0936d0edcb6a31830b464e6cc3eb066beffa9		branch 'master' of https://github.com/Euterpea/Euterpea2
.git/ORIG_HEAD view
@@ -1,1 +1,1 @@-bd913f30e7561f8c842deaed7b028823aa822203+b93609b90dd7ff47b06e8207118b7ced0423302b
.git/index view

binary file changed (2436 → 2532 bytes)

.git/logs/HEAD view
@@ -3,3 +3,11 @@ ef06402d714aa53dae0ba9c74b68d8b4ddea1329 957f3714d66fa6bd059f71b91a1e725b1d2e08a5 Donya Quick <donyaquick@gmail.com> 1499191363 -0400	commit: Misc changes 957f3714d66fa6bd059f71b91a1e725b1d2e08a5 bd913f30e7561f8c842deaed7b028823aa822203 Donya Quick <donyaquick@gmail.com> 1499192677 -0400	commit: Binary encoding fixes. bd913f30e7561f8c842deaed7b028823aa822203 02f0974406cb38a71a2bdfe8204e87bd0cd03892 Donya Quick <donyaquick@gmail.com> 1503766667 -0400	pull --no-rebase --progress origin: Fast-forward+02f0974406cb38a71a2bdfe8204e87bd0cd03892 b2090cd8ae9dc5c97258a85c28874be97a4236fb Donya Quick <donyaquick@gmail.com> 1503778592 -0400	pull --no-rebase --progress origin: Fast-forward+b2090cd8ae9dc5c97258a85c28874be97a4236fb b3318124d370ece16dadd88471b7da08edaec784 Donya Quick <donyaquick@gmail.com> 1503780940 -0400	commit: Documentation update+b3318124d370ece16dadd88471b7da08edaec784 1ebd6e31aa5d954bcc0ccb6ac76b82ed892efb69 Donya Quick <donyaquick@gmail.com> 1527371401 -0400	commit: HCodecs version bumped.+1ebd6e31aa5d954bcc0ccb6ac76b82ed892efb69 331bb2029ff2d4b87f05d3b9d0968c29e2a49c95 Donya Quick <donyaquick@gmail.com> 1530127543 -0400	pull --no-rebase --progress origin: Fast-forward+331bb2029ff2d4b87f05d3b9d0968c29e2a49c95 1ac4c067ddd2305527b67e2aa9e56b19dfb3c808 Donya Quick <donyaquick@gmail.com> 1530149500 -0400	pull --no-rebase --progress origin: Fast-forward+1ac4c067ddd2305527b67e2aa9e56b19dfb3c808 e4c9ce6d2f62995a25daa505e8211cf7b355dbf4 Donya Quick <donyaquick@gmail.com> 1530468209 -0400	commit: PortMidi version change (0.1.6.1)+e4c9ce6d2f62995a25daa505e8211cf7b355dbf4 b93609b90dd7ff47b06e8207118b7ced0423302b Donya Quick <donyaquick@gmail.com> 1530490248 -0400	commit: EnableGUI reference removed+b93609b90dd7ff47b06e8207118b7ced0423302b 77a0936d0edcb6a31830b464e6cc3eb066beffa9 Donya Quick <donyaquick@gmail.com> 1530492169 -0400	pull --no-rebase --progress origin: Fast-forward
.git/logs/refs/heads/master view
@@ -3,3 +3,11 @@ ef06402d714aa53dae0ba9c74b68d8b4ddea1329 957f3714d66fa6bd059f71b91a1e725b1d2e08a5 Donya Quick <donyaquick@gmail.com> 1499191363 -0400	commit: Misc changes 957f3714d66fa6bd059f71b91a1e725b1d2e08a5 bd913f30e7561f8c842deaed7b028823aa822203 Donya Quick <donyaquick@gmail.com> 1499192677 -0400	commit: Binary encoding fixes. bd913f30e7561f8c842deaed7b028823aa822203 02f0974406cb38a71a2bdfe8204e87bd0cd03892 Donya Quick <donyaquick@gmail.com> 1503766667 -0400	pull --no-rebase --progress origin: Fast-forward+02f0974406cb38a71a2bdfe8204e87bd0cd03892 b2090cd8ae9dc5c97258a85c28874be97a4236fb Donya Quick <donyaquick@gmail.com> 1503778592 -0400	pull --no-rebase --progress origin: Fast-forward+b2090cd8ae9dc5c97258a85c28874be97a4236fb b3318124d370ece16dadd88471b7da08edaec784 Donya Quick <donyaquick@gmail.com> 1503780940 -0400	commit: Documentation update+b3318124d370ece16dadd88471b7da08edaec784 1ebd6e31aa5d954bcc0ccb6ac76b82ed892efb69 Donya Quick <donyaquick@gmail.com> 1527371401 -0400	commit: HCodecs version bumped.+1ebd6e31aa5d954bcc0ccb6ac76b82ed892efb69 331bb2029ff2d4b87f05d3b9d0968c29e2a49c95 Donya Quick <donyaquick@gmail.com> 1530127543 -0400	pull --no-rebase --progress origin: Fast-forward+331bb2029ff2d4b87f05d3b9d0968c29e2a49c95 1ac4c067ddd2305527b67e2aa9e56b19dfb3c808 Donya Quick <donyaquick@gmail.com> 1530149500 -0400	pull --no-rebase --progress origin: Fast-forward+1ac4c067ddd2305527b67e2aa9e56b19dfb3c808 e4c9ce6d2f62995a25daa505e8211cf7b355dbf4 Donya Quick <donyaquick@gmail.com> 1530468209 -0400	commit: PortMidi version change (0.1.6.1)+e4c9ce6d2f62995a25daa505e8211cf7b355dbf4 b93609b90dd7ff47b06e8207118b7ced0423302b Donya Quick <donyaquick@gmail.com> 1530490248 -0400	commit: EnableGUI reference removed+b93609b90dd7ff47b06e8207118b7ced0423302b 77a0936d0edcb6a31830b464e6cc3eb066beffa9 Donya Quick <donyaquick@gmail.com> 1530492169 -0400	pull --no-rebase --progress origin: Fast-forward
.git/logs/refs/remotes/origin/master view
@@ -1,3 +1,11 @@ 23b0fe619f7f91be4123ef976dd9284c11c1093a ef06402d714aa53dae0ba9c74b68d8b4ddea1329 Donya Quick <donyaquick@gmail.com> 1496256683 -0500	fetch --progress --prune origin: fast-forward ef06402d714aa53dae0ba9c74b68d8b4ddea1329 bd913f30e7561f8c842deaed7b028823aa822203 Donya Quick <donyaquick@gmail.com> 1499192681 -0400	update by push bd913f30e7561f8c842deaed7b028823aa822203 02f0974406cb38a71a2bdfe8204e87bd0cd03892 Donya Quick <donyaquick@gmail.com> 1503766664 -0400	fetch --progress --prune origin: fast-forward+02f0974406cb38a71a2bdfe8204e87bd0cd03892 b2090cd8ae9dc5c97258a85c28874be97a4236fb Donya Quick <donyaquick@gmail.com> 1503778572 -0400	fetch --progress --prune origin: fast-forward+b2090cd8ae9dc5c97258a85c28874be97a4236fb b3318124d370ece16dadd88471b7da08edaec784 Donya Quick <donyaquick@gmail.com> 1503780945 -0400	update by push+b3318124d370ece16dadd88471b7da08edaec784 1ebd6e31aa5d954bcc0ccb6ac76b82ed892efb69 Donya Quick <donyaquick@gmail.com> 1527371408 -0400	update by push+1ebd6e31aa5d954bcc0ccb6ac76b82ed892efb69 331bb2029ff2d4b87f05d3b9d0968c29e2a49c95 Donya Quick <donyaquick@gmail.com> 1530127542 -0400	fetch --progress --prune origin: fast-forward+331bb2029ff2d4b87f05d3b9d0968c29e2a49c95 1ac4c067ddd2305527b67e2aa9e56b19dfb3c808 Donya Quick <donyaquick@gmail.com> 1530149467 -0400	fetch --progress --prune origin: fast-forward+1ac4c067ddd2305527b67e2aa9e56b19dfb3c808 e4c9ce6d2f62995a25daa505e8211cf7b355dbf4 Donya Quick <donyaquick@gmail.com> 1530468215 -0400	update by push+e4c9ce6d2f62995a25daa505e8211cf7b355dbf4 b93609b90dd7ff47b06e8207118b7ced0423302b Donya Quick <donyaquick@gmail.com> 1530490263 -0400	update by push+b93609b90dd7ff47b06e8207118b7ced0423302b 77a0936d0edcb6a31830b464e6cc3eb066beffa9 Donya Quick <donyaquick@gmail.com> 1530492166 -0400	fetch --progress --prune origin: fast-forward
+ .git/objects/01/024db2f04aee6d9f60a91476631c20da20a599 view

binary file changed (absent → 23035 bytes)

+ .git/objects/02/38550e704e099e5372a409461f44547ea79b98 view

binary file changed (absent → 1341 bytes)

+ .git/objects/02/727d144f7ab7d1800989ad4c5168028fd03247 view

binary file changed (absent → 1136 bytes)

+ .git/objects/03/5dbf6733fe0e251e1d6763cc2cf1f92ec45b97 view

binary file changed (absent → 137 bytes)

+ .git/objects/06/8ccf9b2b17b09afeb0945d8eea4e1ec9b5931b view

binary file changed (absent → 11835 bytes)

+ .git/objects/08/3f9c4ba34a66851c760b9606c31278e056e017 view

binary file changed (absent → 6897 bytes)

+ .git/objects/0a/43fe37ff7154b4ae2f767e21231fd4351d9af1 view

binary file changed (absent → 13537 bytes)

+ .git/objects/0a/761e547df00e9dc91da0a5099bf002fe064369 view
@@ -0,0 +1,1 @@+x+)JMU0´0f040031QðMÌÌÓËÈdH{6­Xûö‚÷¡<gþM¿Ìެ$Ÿañ‘kÂg®EíÙ}hßù¥<r‹ *ŠSKJôR+R¾?Üsùý3Ù]_’]Ît»xˆº-ƒ¢(£˜a­Õ„øÍùO|âùk¥?<ûµùr¶o"Šš²Ô¢âÌü<•Ðm‡O7H½:yM¢6¾ZíîänG‹O×
+ .git/objects/0d/3b143490c5d1bc828167dea1870dde9cd4a6ed view

binary file changed (absent → 1133 bytes)

+ .git/objects/0e/1c38b33561bb4a50232bd0c9afbdc9aeb4fc76 view

binary file changed (absent → 244 bytes)

+ .git/objects/0f/da2b43ce06c5f2bd8decb72778ac85da009fc5 view

binary file changed (absent → 82 bytes)

+ .git/objects/10/940a60108e8947be43e6c5454b36703f3af527 view

binary file changed (absent → 901 bytes)

+ .git/objects/17/e94f9e475ee049f36dfd19fee87e4e1fa9074a view

binary file changed (absent → 10296 bytes)

+ .git/objects/1a/c4c067ddd2305527b67e2aa9e56b19dfb3c808 view

binary file changed (absent → 251 bytes)

+ .git/objects/1b/74031fc6b4b883f5b04cd072f3b2d31251ee89 view

binary file changed (absent → 83 bytes)

+ .git/objects/1c/efbe95003d3a2016fb90f8131040cf38236ef3 view

binary file changed (absent → 187 bytes)

+ .git/objects/1e/bd6e31aa5d954bcc0ccb6ac76b82ed892efb69 view
@@ -0,0 +1,1 @@+xŽAnà E»æsZ`C¤¨ª”.²l0ÀТ€qm\5·¯s…îþûú_z¡Õš;(gŸúʘƄZÅəF9z´£É¡×˜Mætòr­<wðZ£Ce¢¶’㏹sÆ¢·‘¤ãH¬3‚öþÕVxkóàcÏáçø€ïG~ý¬”ËZ}•ՍDx–FJq´‡cçÿ½ÅõÒ"‡
~xÝr›Áïuá8qiu¡ž}.¹ß!å_H‡á•¶—ï…úÁÜ`5ˆ?³¯\s
+ .git/objects/1f/5f132d6440f505b17add35a81b31f4a6499b06 view

binary file changed (absent → 243 bytes)

+ .git/objects/24/55b6c3cb801aeac9d6187d5f7b26dd93b946c5 view

binary file changed (absent → 36 bytes)

+ .git/objects/29/529e1996bba392c92087b0f650514c6399bee7 view

binary file changed (absent → 155 bytes)

+ .git/objects/2a/9bea58331ca40b8b405f96ea5d3d247e7289f0 view

binary file changed (absent → 513632 bytes)

+ .git/objects/2b/1cbcde96e1c5090959a5874b0c692f87c33105 view

binary file changed (absent → 5567 bytes)

+ .git/objects/2e/6373695d1691df1d2172af4bab2e5d9a2b8cba view

binary file changed (absent → 487 bytes)

+ .git/objects/2f/6595b291855c3afb62baa5f782de4acc472782 view

binary file changed (absent → 4179 bytes)

+ .git/objects/2f/f6fa63f2e9efaa4004c30e4a5f491bbe2dce79 view

binary file changed (absent → 244 bytes)

+ .git/objects/33/1bb2029ff2d4b87f05d3b9d0968c29e2a49c95 view
@@ -0,0 +1,1 @@+xŽAnÂ0E»ö)æ qìØ©ªXpzƒ±=Q1	‘³àö
W`÷ߓžôËÜÚÔapö«¯" CŒN-¹@™RÈ^5Ä+YÒÂQh ¯l^åÑ!—D"Ä>jÆ :¦S@Âàc"åLäÙÞúm^á<?^—m*ð]ßð|ïÓµñt?–¹ý€¢£%8 G4»Ý?vù¬6¿Âµ	lKå.Õü*I
+ .git/objects/37/f795427c8e51b753de9d7ee5b858d9394bb50d view

binary file changed (absent → 244 bytes)

+ .git/objects/39/463363d990ed242c0be4bcdcd09b6f1f4ddf51 view

binary file changed (absent → 13697 bytes)

+ .git/objects/3a/3f19d55b74d7aec2bd414cc388f0c581d037f5 view

binary file changed (absent → 272 bytes)

+ .git/objects/3b/5d8b976e4848d4a39e7b0004bbf070df857f56 view

binary file changed (absent → 1152 bytes)

+ .git/objects/3c/4d533b912c3934c8f5d31f74ecd1738a14d1ea view

binary file changed (absent → 82 bytes)

+ .git/objects/40/f7e1bcd3efe61dbaf46344cc8b4449c05adb1c view

file too large to diff

+ .git/objects/41/cd1beb04060f4de58355deec1958f1879357b9 view

binary file changed (absent → 3984 bytes)

+ .git/objects/42/a10db85f8de9ab90bd19b81ee041a157360902 view

binary file changed (absent → 1133 bytes)

+ .git/objects/44/ab1907cf3f73e27e932b5f9adbc1aff0055bd9 view

binary file changed (absent → 75 bytes)

+ .git/objects/46/a33e2dc6a3ec2742374414f9bc62e88613f7b0 view

binary file changed (absent → 13286 bytes)

+ .git/objects/49/cb068c76678f59d50ff054d774c193fb8fb0ee view

binary file changed (absent → 1138 bytes)

+ .git/objects/4d/e09d19a52859416eebe7337b734228c36eeaea view

binary file changed (absent → 5445 bytes)

+ .git/objects/51/cd2dac70f36461ce75efa6dd04f4191cfb85a2 view

binary file changed (absent → 8785 bytes)

+ .git/objects/52/e61beeaa81f6b0c835d6c85fc13eac3efa4370 view

binary file changed (absent → 262 bytes)

+ .git/objects/56/1a90e094ad0eb02d529258e705dc2eb8567006 view

binary file changed (absent → 521 bytes)

+ .git/objects/58/0c534bc0e4a8acd956e26c44fdbe771daaeaee view

binary file changed (absent → 4780 bytes)

+ .git/objects/5b/3b5b7a40203f6670d667ccf1490af895b2532e view

binary file changed (absent → 9778 bytes)

+ .git/objects/5f/076dc7ec4d470f347d83ebdac8a52b61089ed6 view

binary file changed (absent → 107 bytes)

+ .git/objects/64/b3cbe8b2375dc3a504cc49645a7c302d3bb03e view

binary file changed (absent → 100 bytes)

+ .git/objects/66/ea5696732fb7b770ef550c4058ccfe97df5307 view

binary file changed (absent → 1919 bytes)

+ .git/objects/6a/3307ad57c076c3495045be348827023ba172f3 view

binary file changed (absent → 39242 bytes)

+ .git/objects/77/a0936d0edcb6a31830b464e6cc3eb066beffa9 view
@@ -0,0 +1,1 @@+xŽKnÃ0D»Ö)xÔϔ€"È"ÈL‘nZQã(zûÚWÈnæó0¥Õ:wp~øè«*xš(Çà¨$–)zÑ,¤9Å$ÙçÀQÌï¸ê­g?`æŒ"4MMÉÚÄTT08ïѱŸý»­pi·¿®Ï¹üÀ§ìå¾çóWçåXZ=Cv68`@4Ý>v}omd~t˜Ú"›`ÕÚ^*æ²K
+ .git/objects/78/da1cc02000e99d137b8e57cdac5cfa0e1d61f0 view

binary file changed (absent → 3363 bytes)

+ .git/objects/7d/ee88664cf47d7a9c21afea2d12124baeba342a view

binary file changed (absent → 272 bytes)

+ .git/objects/7e/4055ac6f1a57043bf851e0ac6895e48701dfb6 view

binary file changed (absent → 6252 bytes)

+ .git/objects/85/d332148dd5d2895c168281bd8f722082fb4642 view

binary file changed (absent → 52183 bytes)

+ .git/objects/8a/8fe51cee7f28ddddda4a8ea391fc12c9535fd4 view

binary file changed (absent → 136 bytes)

+ .git/objects/8b/db3e4a0a2d31a39225a6dce662d10354bb03fb view

binary file changed (absent → 1554 bytes)

+ .git/objects/8e/4353c7c431de8e9b96c548c56404725cebf8d7 view

binary file changed (absent → 26705 bytes)

+ .git/objects/90/7abff0690c0ed58be55989ef2baadd94ec74d6 view

binary file changed (absent → 21992 bytes)

+ .git/objects/91/319c18ed3cd939faff2d9ddece6f22b3f3ff89 view

binary file changed (absent → 4886 bytes)

+ .git/objects/91/7dd66d08b00840b6875838915e705cf274b67b view

binary file changed (absent → 6403 bytes)

+ .git/objects/92/1a567f84fd3c619896da656e8c6215500b0ee8 view

binary file changed (absent → 16081 bytes)

+ .git/objects/98/a4d35831b52864d3c04205efcf32d97fa71141 view

binary file changed (absent → 159997 bytes)

+ .git/objects/9d/13ddca6950d8ab266b2af51b7cfff182897246 view

binary file changed (absent → 6754 bytes)

+ .git/objects/9d/34353ee46571bf1ae1cd47576fd101f90adc6c view

binary file changed (absent → 80 bytes)

+ .git/objects/9f/96656243a99efc634be16ce9bbc37153ddf901 view

binary file changed (absent → 7599 bytes)

+ .git/objects/a1/22b4153c502a959c1781b50c2d7a7c4aee9236 view

binary file changed (absent → 17388 bytes)

+ .git/objects/a2/1ce4cc33277796834cce54e132c455745fdc4a view

binary file changed (absent → 94853 bytes)

+ .git/objects/a3/0a6d1ed203bc1d93004fd1b0dad1d1375bd83a view

binary file changed (absent → 662399 bytes)

+ .git/objects/a3/c414d613cc00d65abcb35bc2becfd8750c1ea2 view

binary file changed (absent → 1514 bytes)

+ .git/objects/a4/5ecb0d529ba48d8eca951b686178162bb56fed view

binary file changed (absent → 1813 bytes)

+ .git/objects/a7/759cfaaf8d9cb9689de568e618cfdd0117725c view

binary file changed (absent → 297 bytes)

+ .git/objects/aa/54f8d378706ccebc9f919eb858343684c0db35 view

binary file changed (absent → 42041 bytes)

+ .git/objects/ab/968e1f5138259bf03a437adf6aeab81d2305f7 view

binary file changed (absent → 73 bytes)

+ .git/objects/ac/4e27878b2d3c880435a26a956fc06090678680 view

binary file changed (absent → 4195 bytes)

+ .git/objects/af/7a81d59cb968562885db868d11c23397fe76c4 view

binary file changed (absent → 4867 bytes)

+ .git/objects/b1/13c29eb1f0e31fabe30a3806d50c684682ce7b view

binary file changed (absent → 136 bytes)

+ .git/objects/b2/090cd8ae9dc5c97258a85c28874be97a4236fb view
@@ -0,0 +1,2 @@+x•ŽA E]s+. ZhbŒ/2CtQŠ-5éí­½›ÿÿâ½äó4ޝ¦­ÅS›E4ˆa±ëMŒŽ:°hc(Ç´§D—Ù÷ªÒ,¥i°ïô17´ÓY‚'ÁÿÄ«hmÏiÖi*éëQŸ÷½H[˜ª\öqÓ¦ô> óú@ññ®É¿žzH•’¤ð¦×š¨É¢¾“üGÿ
+ .git/objects/b3/318124d370ece16dadd88471b7da08edaec784 view

binary file changed (absent → 169 bytes)

+ .git/objects/b4/54931a04f9f5ed704efee42f581efd7bab6ea6 view

binary file changed (absent → 243 bytes)

+ .git/objects/b5/2e7337b8ceb6af3917335286122e5583beb623 view

binary file changed (absent → 8653 bytes)

+ .git/objects/b8/d039f25c74aae5847108e06578fabd6044b08f view

binary file changed (absent → 1161 bytes)

+ .git/objects/b9/3609b90dd7ff47b06e8207118b7ced0423302b view

binary file changed (absent → 216 bytes)

+ .git/objects/ba/79d76d21f4f8570c2291f34c4e6a7c032ba6a6 view

binary file changed (absent → 24169 bytes)

+ .git/objects/bc/44a1c3065f4425ff4bd0bdeea06c9148d54b69 view

binary file changed (absent → 244 bytes)

+ .git/objects/bc/89ee9a47fb06ef5908208609064789fab994a3 view

binary file changed (absent → 270 bytes)

+ .git/objects/c0/f9a2c81ce54e952d2c2345e8181cbd1fad4e5e view

binary file changed (absent → 355 bytes)

+ .git/objects/c1/0871f26e532d8caecda1aaa201b3e8dc9e14a9 view

binary file changed (absent → 4866 bytes)

+ .git/objects/c2/71a1a77c1de0661216fa046482d63798131c7d view

binary file changed (absent → 142866 bytes)

+ .git/objects/c4/441dcae1ecbcf7950a80c92988f2e2e11fa204 view

binary file changed (absent → 15615 bytes)

+ .git/objects/c6/8c3a9f599e56b40150c0f49e8ee9bd86f3341a view

binary file changed (absent → 715 bytes)

+ .git/objects/c8/5202f17668f31b25d58e0868e6da237523220b view

binary file changed (absent → 8225 bytes)

+ .git/objects/ce/8098efc2f498451b940e76ce332d69d455e46a view

binary file changed (absent → 1549 bytes)

+ .git/objects/d2/68f5a8f9eeddb031e901170352e31333b42733 view

binary file changed (absent → 82 bytes)

+ .git/objects/d2/72327d92a665b172ef4cfaaf7a5c20d5db5b90 view

binary file changed (absent → 5131 bytes)

+ .git/objects/d2/b862f369c5ac596bf5f12063d78d6b8a6ee225 view

binary file changed (absent → 3975 bytes)

+ .git/objects/d9/65d92c5335eadacaf9a72230f79d4dff573b27 view

binary file changed (absent → 108550 bytes)

+ .git/objects/db/c4cd70d46015b2e76f28354b4f938d2cd070ff view

binary file changed (absent → 297 bytes)

+ .git/objects/dc/354a20d31288878085d56b43ebfe3aa820522a view

binary file changed (absent → 244 bytes)

+ .git/objects/df/0bbaa2086cf56f42500389a0bff5d532e7fc63 view

binary file changed (absent → 23317 bytes)

+ .git/objects/e3/836fe2cf6a77d8ec3d8a7bbbe3822251fb5ed9 view
@@ -0,0 +1,1 @@+x­SÁnÓ@“@ˆ"õ€qé66	¤œ,5ˆ©4"=õ²ØÉ&]ՎÃzSÑ=q@|„¸ò|0»öÆ6J9@Vڙ7Oo_v=“8Éb×ëööaòùèõøoPˆd¤ÁW†ïÈ$’QM n£ÏÜzmá`ø•Äynˆ¿„Z'š†ê¥—=Š~Á^×VWgý»{Þó†àVŸÖø5Dµâq
khÞ-ùV™_.%íú¤Cz»a¾ßžª~ØúÏ..ޞѬŠ„Çä(„åaL¯Ü>ñ‰_Qp±71Þ2Hß½àvVœ‹h·O0^7¨³Bdʆ•^?̜itn‰‚6ñA‰õùV£÷ú½-ûèR¥S½ï׌&À¨»]­zÏõwZëSëwÛhšý²n¶zR[ÎmK7²WVú>z(q"1Ì÷’©4ñuÚ½ÒdÈèo]i¾!ã6˜íÂ9ëü¢ÁP¬Ì7"‚%DdPö#¥Œ¼÷¯#šY')ÍåŒÏ¹¤vHTê+ÞQ¼§ÒbœN՟Uiyx¬¸©ÿ;NÕDŠ£l²LX—Æ—’å«¡ý·ûԟÒq’åKÁ6géoúŽÞæï¸rœUº<¥øoWüärÁrz"ÞD)Ñq6§|>Í`­ªèH%ú
ÈNÉ
+ .git/objects/e4/c9ce6d2f62995a25daa505e8211cf7b355dbf4 view

binary file changed (absent → 222 bytes)

+ .git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 view

binary file changed (absent → 15 bytes)

+ .git/objects/e9/5fe8336982a811e3ddc1e3fcf64f5a3767ac1b view

binary file changed (absent → 1161 bytes)

+ .git/objects/ee/5e4a1390a0d0f1e9d0ce02680a74f952b32955 view

binary file changed (absent → 242 bytes)

+ .git/objects/f0/ad62e4e42168fd3ab7e5945083d01e058c6231 view

binary file changed (absent → 7502 bytes)

+ .git/objects/f2/773f0019369b986b4ff6750d919fca7e9294fa view

binary file changed (absent → 243 bytes)

+ .git/objects/f8/214bd47c4577ee917f6f53f61fc6a12422a996 view

binary file changed (absent → 158 bytes)

+ .git/objects/f9/918de49c23fa56c9da20dcf3fd47ce0cf37b99 view

binary file changed (absent → 244 bytes)

+ .git/objects/ff/910b318efc137a01b3fd719c0c603c06260935 view

binary file changed (absent → 27874 bytes)

.git/refs/heads/master view
@@ -1,1 +1,1 @@-02f0974406cb38a71a2bdfe8204e87bd0cd03892+77a0936d0edcb6a31830b464e6cc3eb066beffa9
.git/refs/remotes/origin/master view
@@ -1,1 +1,1 @@-02f0974406cb38a71a2bdfe8204e87bd0cd03892+77a0936d0edcb6a31830b464e6cc3eb066beffa9
Euterpea.cabal view
@@ -1,17 +1,17 @@ name:           Euterpea
-version:        2.0.4
+version:        2.0.5
 Cabal-Version:  >= 1.8
 license:        BSD3
 license-file:	License
-copyright:      Copyright (c) 2008-2016 Euterpea authors
+copyright:      Copyright (c) 2008-2017 Euterpea authors
 category:       Sound
 stability:      experimental
 build-type:     Custom
 author:         Paul Hudak <paul.hudak@yale.edu>, 
                 Eric Cheng <eric.cheng@aya.yale.edu>,
                 Hai (Paul) Liu <hai.liu@aya.yale.edu>,
-				Donya Quick <donyaquick@gmail.com>,
-				Dan Winograd-Cort <dwincort@gmail.com >
+                Donya Quick <donyaquick@gmail.com>,
+                Dan Winograd-Cort <dwincort@gmail.com >
 maintainer:     Donya Quick <donyaquick@gmail.com>
 bug-reports:    https://github.com/Euterpea/Euterpea2/issues
 homepage:       http://www.euterpea.com
@@ -27,8 +27,7 @@         MIDI; and low-level audio processing, sound synthesis, and instrument
         design.  
 extra-source-files:
-        ReadMe.txt,
-        Euterpea/Examples/EnableGUI.hs
+        ReadMe.txt
 
 Library
   hs-source-dirs: .
@@ -52,20 +51,21 @@         Euterpea.IO.MIDI.FromMidi2,
         Euterpea.IO.MIDI.GeneralMidi,
         Euterpea.IO.MIDI.ToMidi,
+        Euterpea.IO.MIDI.ToMidi2,
         Euterpea.IO.MIDI.Play,
         Euterpea.IO.MIDI.ExportMidiFile,
         Euterpea.IO.MIDI
   other-modules:
   build-depends:
         base >= 4 && < 5, 
-        arrows == 0.4.4.1, 
-        array>=0.5.0.0 && <=0.5.2.0, 
-        deepseq>=1.3.0.2 && <=1.4.3.0, 
-        random>=1.0.1.1 && <=1.1,
-        PortMidi==0.1.5.2, 
-        HCodecs == 0.5, 
-        stm==2.4.4.1, 
-        containers>=0.5.5.1 && <=0.5.7.1, 
+        arrows >= 0.4 && < 0.5, 
+        array>=0.5.0.0 && <=0.6, 
+        deepseq>=1.3.0.2 && <=1.5, 
+        random>=1.0.1.1 && <=1.2,
+        PortMidi==0.1.6.1, 
+        HCodecs == 0.5.1, 
+        stm >= 2.4 && <2.5, 
+        containers>=0.5.5.1 && <0.6, 
         bytestring>=0.10.4.0 && <= 0.10.9,
         heap >= 1.0 && < 2.0, 
         ghc-prim
Euterpea/IO/MIDI/MidiIO.lhs view
@@ -21,7 +21,8 @@ >                        openInput, openOutput, readEvents,
 >                        close, writeShort, getErrorText, terminate, initialize,
 >                        PMError (NoError, BufferOverflow), PMStream,
->                        PMEvent (..), PMMsg (PMMsg))
+>                        PMEvent (..), PMMsg (PMMsg), 
+>                        encodeMsg, decodeMsg)
 > import Control.Exception (finally)
 > import Control.Concurrent
 > import Control.Concurrent.STM.TChan
@@ -272,7 +273,7 @@ >           else reportError "pollMidiCB" e
 >         Left l -> do
 >           now <- getTimeNow
->           case mapMaybe (msgToMidi . message) l of
+>           case mapMaybe (msgToMidi . decodeMsg . message) l of
 >             [] -> return ()
 >             ms -> callback (now, ms)
 
@@ -296,7 +297,7 @@ >           else reportError "pollMIDI" e >> return Nothing
 >         Left l -> do
 >           now <- getTimeNow
->           case mapMaybe (msgToMidi . message) l of
+>           case mapMaybe (msgToMidi . decodeMsg . message) l of
 >             [] -> return Nothing
 >             ms -> return $ Just (now, ms)
 
@@ -421,7 +422,7 @@ >           if isTrackEnd msg
 >               then return ()
 >               else case midiEvent msg of
->                 Just m  -> writeMsg s t m
+>                 Just m  -> writeMsg s t $ encodeMsg m
 >                 Nothing -> return ()
 >     writeMsg s t m = do
 >               e <- writeShort s (PMEvent m (round (t * 1e3)))
@@ -486,7 +487,7 @@ >             process t msg = if isTrackEnd msg
 >               then return True
 >               else case midiEvent msg of
->                 Just m  -> writeMsg t m
+>                 Just m  -> writeMsg t $ encodeMsg m
 >                 Nothing -> return False
 >             writeMsg t m = do
 >               e <- writeShort s (PMEvent m (round (t * 1e3)))
@@ -650,7 +651,7 @@ >         sendEvts start now [] = loop start s fin
 >         sendEvts start now (e@(PMEvent m t):l) = do
 >           let t0 = maybe t id start
->           case msgToMidi m of
+>           case msgToMidi $ decodeMsg m of
 >             Just m' -> do
 >               done <- callback (now + fromIntegral (t - t0) / 1E3, m')
 >               if done then close s >> return () else sendEvts (Just t0) now l
Euterpea/IO/MIDI/Play.lhs view
@@ -42,9 +42,9 @@ >     perfAlg :: Music1 -> [MEvent]
 >     }
 
-Default parameters are the default pmap+context, allowing for infinite playback, 
-using a linear channel assignment policy for 16 channels with percussion on 
-channel 9 (which is channel 10 when indexing from 1), using the default MIDI 
+Default parameters are the default pmap+context, allowing for infinite playback,
+using a linear channel assignment policy for 16 channels with percussion on
+channel 9 (which is channel 10 when indexing from 1), using the default MIDI
 device as set by the operating system, and using a closing offset of 1.0sec.
 
 > defParams = PlayParams False (linearCP 16 9) Nothing 1.0 perform1
@@ -68,15 +68,15 @@ > playC :: (ToMusic1 a, NFData a) => PlayParams -> Music a -> IO ()
 > playC p = if strict p then playStrict p else playInf p
 
-Getting a list of all MIDI input and output devices, showing both 
-their device IDs and names. 
+Getting a list of all MIDI input and output devices, showing both
+their device IDs and names.
 
 > devices = do
 >   (devsIn, devsOut) <- getAllDevices
 >   let f (devid, devname) = "  "++show devid ++ "\t" ++ name devname ++ "\n"
 >       strIn = concatMap f devsIn
 >       strOut = concatMap f devsOut
->   putStrLn "\nInput devices: " >> putStrLn strIn 
+>   putStrLn "\nInput devices: " >> putStrLn strIn
 >   putStrLn "Output devices: " >> putStrLn strOut
 
 
@@ -85,16 +85,16 @@ ------------------------------------
 
 Strict playback: timing will be as close to perfect as possible, but the
-Music value must be finite. Timing will be correct starting from the first 
-note, even if there is a long computation offset prior to any sound. 
+Music value must be finite. Timing will be correct starting from the first
+note, even if there is a long computation offset prior to any sound.
 
 > playStrict :: (ToMusic1 a, NFData a) => PlayParams -> Music a -> IO ()
 > playStrict p m = m `deepseq`
->     let x = toMidi (perfAlg p $ toMusic1 m) 
+>     let x = toMidi (perfAlg p $ toMusic1 m)
 >     in  x `deepseq` playM' (devID p) x
 
 > playM' :: Maybe OutputDeviceID -> Midi -> IO ()
-> playM' devID midi = handleCtrlC $ do 
+> playM' devID midi = handleCtrlC $ do
 >     initialize
 >     (maybe (defaultOutput playMidi) playMidi devID) midi
 >     terminate
@@ -103,7 +103,7 @@ >     handleCtrlC op = onException op terminate
 
 
-Infinite playback: arbitrarily long music values can be played, although 
+Infinite playback: arbitrarily long music values can be played, although
 with the compromise that timing may be imperfect due to lazy evaluation of
 the Music value. Delays may happen if a section of the Music value is time-
 consuming to compute. Infinite parallelism is not supported.
@@ -115,12 +115,19 @@ >     threadDelay $ round (closeDelay p * 1000000)
 >     terminateMidi
 >     return () where
+>     resolveOutDev Nothing = unsafeOutputID 0
+>     resolveOutDev (Just x) = x
 >     handleCtrlC :: IO a -> IO a
->     handleCtrlC op = onException op terminateMidi
+>     handleCtrlC op = onException op (stopMidiOut (resolveOutDev $ devID p) 16)
 
+> stopMidiOut :: OutputDeviceID -> Channel -> IO ()
+> stopMidiOut dev i = if i<0 then threadDelay 1000000 >> terminateMidi else do
+>     deliverMidiEvent dev (0, Std $ ControlChange i 123 0)
+>     stopMidiOut dev (i-1)
+
 > playRec dev [] = return ()
-> playRec dev (x@(t,m):ms) = 
->     if t > 0 then threadDelay (toMicroSec t) >> playRec dev ((0,m):ms) else 
+> playRec dev (x@(t,m):ms) =
+>     if t > 0 then threadDelay (toMicroSec t) >> playRec dev ((0,m):ms) else
 >     let mNow = x : takeWhile ((<=0).fst) ms
 >         mLater = drop (length mNow - 1) ms
 >     in  doMidiOut dev (Just $ mNow) >> playRec dev mLater where
@@ -136,13 +143,13 @@ ---------------------------------
 
 Music to message conversion will take place differently depending
-on the channel assignment method. Using linearCP will assign the first 
-n instruments to channels 0 through n-1 (or 1 through n). Using 
-dynamicCP will fill up n channels and then replace the last-used 
+on the channel assignment method. Using linearCP will assign the first
+n instruments to channels 0 through n-1 (or 1 through n). Using
+dynamicCP will fill up n channels and then replace the last-used
 instrument's channel with the new instrument.
 
 Some synthesizers only recognize 10 unique channels, others use the
-full 16 allowed by general MIDI. Drums are usually on channel 9 
+full 16 allowed by general MIDI. Drums are usually on channel 9
 (channel 10 when indexing from 1), but not always.  Sometimes drums
 can be assigned to a custom channel.
 
@@ -153,20 +160,20 @@ > type ChannelMap = [(InstrumentName, Channel)]
 
 Given an InstrumentName and a ChannelMap, a ChannelMapFun picks a new
-channel to assign to the instrument and retruns both that and the 
+channel to assign to the instrument and retruns both that and the
 updated ChannelMap. This is done each time a new InstrumentName is
 encountered (in other words, it is not in the current ChannelMap).
 
 > type ChannelMapFun = InstrumentName -> ChannelMap -> (Channel, ChannelMap)
 
-The function below first converts to ANote values and then to Std On/Off 
+The function below first converts to ANote values and then to Std On/Off
 pairs. This is needed to avoid timing issues associated with using ANote
 and trying to call terminateMIDI, since if there is an ANote at the end
 it will sometimes have its NoteOff lost, which can cause errors.
 
 > musicToMsgs' :: (ToMusic1 a) => PlayParams -> Music a -> [(Time, MidiMessage)]
-> musicToMsgs' p m = 
->     let perf = perfAlg p $ toMusic1 m -- obtain the performance 
+> musicToMsgs' p m =
+>     let perf = perfAlg p $ toMusic1 m -- obtain the performance
 >         evsA = channelMap (chanPolicy p) [] perf -- time-stamped ANote values
 >         evs = stdMerge evsA -- merged On/Off events sorted by absolute time
 >         times = map fst evs -- absolute times in seconds
@@ -175,49 +182,49 @@ >     -- stdMerge: converts ANotes into a sorted list of On/Off events
 >     stdMerge :: [(Time, MidiMessage)] -> [(Time, MidiMessage)]
 >     stdMerge [] = []
->     stdMerge ((t,ANote c k v d):es) = 
->         (t, Std $ NoteOn c k v) : 
->         stdMerge (insertBy (\(a,b) (x,y) -> compare a x) (t+d, Std $ NoteOff c k v) es) 
->     stdMerge (e1:es) = e1 : stdMerge es 
+>     stdMerge ((t,ANote c k v d):es) =
+>         (t, Std $ NoteOn c k v) :
+>         stdMerge (insertBy (\(a,b) (x,y) -> compare a x) (t+d, Std $ NoteOff c k v) es)
+>     stdMerge (e1:es) = e1 : stdMerge es
 >     -- channelMap: performs instrument assignment for a list of Events
 >     channelMap :: ChannelMapFun -> ChannelMap -> [MEvent] -> [(Time, MidiMessage)]
 >     channelMap cf cMap [] = []
->     channelMap cf cMap (e:es) = 
+>     channelMap cf cMap (e:es) =
 >         let i = eInst e
 >             ((chan, cMap'), newI) = case lookup i cMap of Nothing -> (cf i cMap, True)
 >                                                           Just x  -> ((x, cMap), False)
->             e' = (fromRational (eTime e), 
->                   ANote chan (ePitch e) (eVol e) (fromRational $ eDur e)) 
+>             e' = (fromRational (eTime e),
+>                   ANote chan (ePitch e) (eVol e) (fromRational $ eDur e))
 >             es' = channelMap cf cMap' es
 >             iNum = if i==Percussion then 0 else fromEnum i
->         in  if newI then (fst e', Std $ ProgramChange chan iNum) : e' : es' 
->             else e' : es' 
+>         in  if newI then (fst e', Std $ ProgramChange chan iNum) : e' : es'
+>             else e' : es'
 
-The linearCP channel map just fills up channels left to right until it hits 
-the maximum number and then throws an error. Percussion is handled as a 
+The linearCP channel map just fills up channels left to right until it hits
+the maximum number and then throws an error. Percussion is handled as a
 special case.
 
 > type NumChannels = Int -- maximum number of channels (i.e. 0-15 is 16 channels)
 > type PercChan = Int -- percussion channel, using indexing from zero
 
-> linearCP :: NumChannels -> PercChan -> ChannelMapFun 
-> linearCP cLim pChan i cMap = if i==Percussion then (pChan, (i,pChan):cMap) else 
+> linearCP :: NumChannels -> PercChan -> ChannelMapFun
+> linearCP cLim pChan i cMap = if i==Percussion then (pChan, (i,pChan):cMap) else
 >     let n = length $ filter ((/=Percussion). fst) cMap
->         newChan = if n>=pChan then n+1 else n -- step over the percussion channel 
+>         newChan = if n>=pChan then n+1 else n -- step over the percussion channel
 >     in if newChan < cLim then (newChan, (i, newChan) : cMap) else
->        error ("Cannot use more than "++show cLim++" instruments.")   
+>        error ("Cannot use more than "++show cLim++" instruments.")
 
-For the dynamicCP channel map, new assignements are added in the left side 
-of the channel map/list. This means that the item farthest to the right 
+For the dynamicCP channel map, new assignements are added in the left side
+of the channel map/list. This means that the item farthest to the right
 is the oldest and should be replaced when the table is full. Percussion
 is handled separately.
 
-> dynamicCP :: NumChannels -> PercChan -> ChannelMapFun 
-> dynamicCP cLim pChan i cMap = 
+> dynamicCP :: NumChannels -> PercChan -> ChannelMapFun
+> dynamicCP cLim pChan i cMap =
 >     if i==Percussion then (pChan, (i, pChan):cMap) else
 >         let cMapNoP = filter ((/=Percussion). fst) cMap
 >             extra = if length cMapNoP == length cMap then [] else [(Percussion, pChan)]
->             newChan = snd $ last cMapNoP 
+>             newChan = snd $ last cMapNoP
 >         in  if length cMapNoP < cLim - 1 then linearCP cLim pChan i cMap
 >         else (newChan, (i, newChan) : (take (length cMapNoP - 1) cMapNoP)++extra)
 
@@ -226,7 +233,7 @@ instruments are found that are not accounted for, an error is thrown.
 
 > predefinedCP :: ChannelMap -> ChannelMapFun
-> predefinedCP cMapFixed i _ = case lookup i cMapFixed of 
+> predefinedCP cMapFixed i _ = case lookup i cMapFixed of
 >     Nothing -> error (show i ++ " is not included in the channel map.")
 >     Just c -> (c, cMapFixed)
 
@@ -254,7 +261,7 @@ >     rnf (TempoChange t) = rnf t
 >     rnf x = () -- no other message types are currently used by Euterpea
 
-> instance NFData MidiMessage where 
+> instance NFData MidiMessage where
 >     rnf (Std m) = rnf m
 >     rnf (ANote c k v d) = rnf c `seq` rnf k `seq` rnf v `seq` rnf d
 
+ Euterpea/IO/MIDI/ToMidi2.lhs view
@@ -0,0 +1,65 @@+ToMidi2: a module for allowing multiple tracks with the same GM instrument.
+Author: Donya Quick
+
+The writeMidi2 function allows use of the CustomInstrument constructor
+in a very specific way to permit two tracks that have the same instrument.
+The expected format is:
+
+CustomInstrument "GMInstrumentName UniqueIdentifier"
+
+For example:
+
+ import Euterpea
+ import Euterpea.IO.MIDI.ToMidi2
+ m = instrument (CustomInstrument "Flute A") (c 4 qn :+: d 4 qn) :=:
+     instrument (CustomInstrument "Flute B") (c 5 qn) :=:
+     instrument HonkyTonkPiano (rest hn :+: c 4 hn)
+ main = writeMidi2 "test.mid" m
+
+This will create a MIDI file with three tracks, two of which are assigned
+the Flute instrument and the third with the HonkyTonkPiano instrument.
+
+Note: this module does NOT allow specification of particular track numbers.
+The order in which the tracks appear in the MIDI file is determined by the
+structure of the particular Music value.
+
+> module Euterpea.IO.MIDI.ToMidi2 (writeMidi2, resolveInstrumentName) where
+> import Euterpea.IO.MIDI.ToMidi
+> import Euterpea.IO.MIDI.GeneralMidi
+> import Euterpea.IO.MIDI.MEvent
+> import Euterpea.Music
+> import Euterpea.IO.MIDI.ExportMidiFile
+> import Data.List
+> import Codec.Midi
+
+> instNameOnly :: String -> String
+> instNameOnly [] = []
+> instNameOnly (x:xs) = if x==' ' then [] else x : instNameOnly xs
+
+> resolveInstrumentName :: InstrumentName -> InstrumentName
+> resolveInstrumentName x@(CustomInstrument s) =
+>     let iName = instNameOnly s
+>         allInsts = take 128 $ enumFrom AcousticGrandPiano
+>         i = maybe (-1) id $ findIndex (==iName) $ map show $ allInsts
+>     in  if i >= 0 then allInsts !! i else x
+> resolveInstrumentName x = x
+
+> resolveMEventInsts :: [(InstrumentName, [MEvent])] -> [(InstrumentName, [MEvent])]
+> resolveMEventInsts = map f1 where
+>     f1 (iname, mevs) = (resolveInstrumentName iname, map f2 mevs)
+>     f2 mev = mev{eInst = resolveInstrumentName (eInst mev)}
+
+
+> writeMidi2 :: ToMusic1 a => FilePath -> Music a -> IO ()
+> writeMidi2 fn m = exportMidiFile fn $ toMidiUPM2 defUpm $ perform m
+
+> toMidiUPM2 :: UserPatchMap -> [MEvent] -> Midi
+> toMidiUPM2 upm pf =
+>    let split     = resolveMEventInsts $ splitByInst pf
+>        insts     = map fst split
+>        rightMap  =  if (allValid upm insts) then upm
+>                     else (makeGMMap insts)
+>    in Midi  (if length split == 1  then SingleTrack
+>                                    else MultiTrack)
+>             (TicksPerBeat division)
+>             (map (fromAbsTime . mevsToMessages rightMap) split)
Euterpea/Music.lhs view
@@ -9,18 +9,18 @@ > type Octave = Int
 > type Pitch = (PitchClass, Octave)
 > type Dur   = Rational
-> data PitchClass  =  Cff | Cf | C | Dff | Cs | Df | Css | D | Eff | Ds 
+> data PitchClass  =  Cff | Cf | C | Dff | Cs | Df | Css | D | Eff | Ds
 >                  |  Ef | Fff | Dss | E | Ff | Es | F | Gff | Ess | Fs
->                  |  Gf | Fss | G | Aff | Gs | Af | Gss | A | Bff | As 
+>                  |  Gf | Fss | G | Aff | Gs | Af | Gss | A | Bff | As
 >                  |  Bf | Ass | B | Bs | Bss
 >      deriving (Show, Eq, Ord, Read, Enum, Bounded)
 
-> data Primitive a  =  Note Dur a        
->                   |  Rest Dur          
+> data Primitive a  =  Note Dur a
+>                   |  Rest Dur
 >      deriving (Show, Eq, Ord)
 
-> data Music a  = 
->        Prim (Primitive a)               --  primitive value 
+> data Music a  =
+>        Prim (Primitive a)               --  primitive value
 >     |  Music a :+: Music a              --  sequential composition
 >     |  Music a :=: Music a              --  parallel composition
 >     |  Modify Control (Music a)         --  modifier
@@ -35,26 +35,26 @@ >        |  Custom      String			   --  for user-specified controls
 >   deriving (Show, Eq, Ord)
 
-> data Mode = Major | Minor | 
->             Ionian | Dorian | Phrygian | Lydian | Mixolydian | Aeolian | Locrian | 
+> data Mode = Major | Minor |
+>             Ionian | Dorian | Phrygian | Lydian | Mixolydian | Aeolian | Locrian |
 >             CustomMode String
 >   deriving (Show, Eq, Ord)
 
 > data InstrumentName =
 >      AcousticGrandPiano     | BrightAcousticPiano    | ElectricGrandPiano
 >   |  HonkyTonkPiano         | RhodesPiano            | ChorusedPiano
->   |  Harpsichord            | Clavinet               | Celesta 
->   |  Glockenspiel           | MusicBox               | Vibraphone  
+>   |  Harpsichord            | Clavinet               | Celesta
+>   |  Glockenspiel           | MusicBox               | Vibraphone
 >   |  Marimba                | Xylophone              | TubularBells
->   |  Dulcimer               | HammondOrgan           | PercussiveOrgan 
+>   |  Dulcimer               | HammondOrgan           | PercussiveOrgan
 >   |  RockOrgan              | ChurchOrgan            | ReedOrgan
 >   |  Accordion              | Harmonica              | TangoAccordion
 >   |  AcousticGuitarNylon    | AcousticGuitarSteel    | ElectricGuitarJazz
 >   |  ElectricGuitarClean    | ElectricGuitarMuted    | OverdrivenGuitar
 >   |  DistortionGuitar       | GuitarHarmonics        | AcousticBass
 >   |  ElectricBassFingered   | ElectricBassPicked     | FretlessBass
->   |  SlapBass1              | SlapBass2              | SynthBass1   
->   |  SynthBass2             | Violin                 | Viola  
+>   |  SlapBass1              | SlapBass2              | SynthBass1
+>   |  SynthBass2             | Violin                 | Viola
 >   |  Cello                  | Contrabass             | TremoloStrings
 >   |  PizzicatoStrings       | OrchestralHarp         | Timpani
 >   |  StringEnsemble1        | StringEnsemble2        | SynthStrings1
@@ -62,8 +62,8 @@ >   |  SynthVoice             | OrchestraHit           | Trumpet
 >   |  Trombone               | Tuba                   | MutedTrumpet
 >   |  FrenchHorn             | BrassSection           | SynthBrass1
->   |  SynthBrass2            | SopranoSax             | AltoSax 
->   |  TenorSax               | BaritoneSax            | Oboe  
+>   |  SynthBrass2            | SopranoSax             | AltoSax
+>   |  TenorSax               | BaritoneSax            | Oboe
 >   |  Bassoon                | EnglishHorn            | Clarinet
 >   |  Piccolo                | Flute                  | Recorder
 >   |  PanFlute               | BlownBottle            | Shakuhachi
@@ -77,8 +77,8 @@ >   |  FX4Atmosphere          | FX5Brightness          | FX6Goblins
 >   |  FX7Echoes              | FX8SciFi               | Sitar
 >   |  Banjo                  | Shamisen               | Koto
->   |  Kalimba                | Bagpipe                | Fiddle 
->   |  Shanai                 | TinkleBell             | Agogo  
+>   |  Kalimba                | Bagpipe                | Fiddle
+>   |  Shanai                 | TinkleBell             | Agogo
 >   |  SteelDrums             | Woodblock              | TaikoDrum
 >   |  MelodicDrum            | SynthDrum              | ReverseCymbal
 >   |  GuitarFretNoise        | BreathNoise            | Seashore
@@ -125,7 +125,7 @@ > addVolume    :: Volume -> Music Pitch -> Music (Pitch,Volume)
 > addVolume v  = mMap (\p -> (p,v))
 
-> data NoteAttribute = 
+> data NoteAttribute =
 >         Volume  Int   --  MIDI convention: 0=min, 127=max
 >      |  Fingering Integer
 >      |  Dynamics String
@@ -155,6 +155,9 @@ > instance ToMusic1 (AbsPitch) where
 >     toMusic1 = mMap (\a -> (pitch a, []))
 
+> instance ToMusic1 (AbsPitch, Volume) where
+>     toMusic1 = mMap (\(p,v) -> (pitch p, [Volume v]))
+
 > note            :: Dur -> a -> Music a
 > note d p        = Prim (Note d p)
 
@@ -177,7 +180,7 @@ > keysig pc mo m  = Modify (KeySig pc mo) m
 
 > cff,cf,c,cs,css,dff,df,d,ds,dss,eff,ef,e,es,ess,fff,ff,f,
->   fs,fss,gff,gf,g,gs,gss,aff,af,a,as,ass,bff,bf,b,bs,bss :: 
+>   fs,fss,gff,gf,g,gs,gss,aff,af,a,as,ass,bff,bf,b,bs,bss ::
 >     Octave -> Dur -> Music Pitch
 
 > cff  o d = note d (Cff,  o);  cf   o d = note d (Cf,   o)
@@ -200,10 +203,10 @@ > bss  o d = note d (Bss,  o)
 
 
-> bn, wn, hn, qn, en, sn, tn, sfn, dwn, dhn, 
+> bn, wn, hn, qn, en, sn, tn, sfn, dwn, dhn,
 >     dqn, den, dsn, dtn, ddhn, ddqn, dden :: Dur
 
-> bnr, wnr, hnr, qnr, enr, snr, tnr, sfnr, dwnr, dhnr, 
+> bnr, wnr, hnr, qnr, enr, snr, tnr, sfnr, dwnr, dhnr,
 >      dqnr, denr, dsnr, dtnr, ddhnr, ddqnr, ddenr :: Music Pitch
 
 > bn    = 2;     bnr    = rest bn    --  brevis rest
@@ -228,10 +231,10 @@ 
 The conversion for Pitch and AbsPitch differs from previous versions
 of Euterpea. In Euterpea 1.x, (C,5) was pitch number 60, which is not
-the most common interpretation. While there is no universal standard 
+the most common interpretation. While there is no universal standard
 for which octave should be octave 0, it is far more common to have the
-pitch number relationship that (C,4) = 60. Since this change has been 
-requested many times in previous versions of Euterpea, the following 
+pitch number relationship that (C,4) = 60. Since this change has been
+requested many times in previous versions of Euterpea, the following
 standard is now in place as of version 2.0.0:
 
 pitch 0 = (C,-1)
@@ -243,16 +246,16 @@ 
 > pcToInt     :: PitchClass -> Int
 > pcToInt pc  = case pc of
->   Cff  -> -2;  Cf  -> -1;  C  -> 0;   Cs  -> 1;   Css  -> 2; 
->   Dff  -> 0;   Df  -> 1;   D  -> 2;   Ds  -> 3;   Dss  -> 4; 
->   Eff  -> 2;   Ef  -> 3;   E  -> 4;   Es  -> 5;   Ess  -> 6; 
->   Fff  -> 3;   Ff  -> 4;   F  -> 5;   Fs  -> 6;   Fss  -> 7; 
->   Gff  -> 5;   Gf  -> 6;   G  -> 7;   Gs  -> 8;   Gss  -> 9; 
+>   Cff  -> -2;  Cf  -> -1;  C  -> 0;   Cs  -> 1;   Css  -> 2;
+>   Dff  -> 0;   Df  -> 1;   D  -> 2;   Ds  -> 3;   Dss  -> 4;
+>   Eff  -> 2;   Ef  -> 3;   E  -> 4;   Es  -> 5;   Ess  -> 6;
+>   Fff  -> 3;   Ff  -> 4;   F  -> 5;   Fs  -> 6;   Fss  -> 7;
+>   Gff  -> 5;   Gf  -> 6;   G  -> 7;   Gs  -> 8;   Gss  -> 9;
 >   Aff  -> 7;   Af  -> 8;   A  -> 9;   As  -> 10;  Ass  -> 11;
 >   Bff  -> 9;   Bf  -> 10;  B  -> 11;  Bs  -> 12;  Bss  -> 13
 
 > pitch     :: AbsPitch -> Pitch
-> pitch ap  = 
+> pitch ap  =
 >     let (oct, n) = divMod ap 12
 >     in  ([C,Cs,D,Ds,E,F,Fs,G,Gs,A,As,B] !! n, oct-1)
 
@@ -288,7 +291,7 @@ > lineToList                    :: Music a -> [Music a]
 > lineToList (Prim (Rest 0))    = []
 > lineToList (n :+: ns)         = n : lineToList ns
-> lineToList _                  = 
+> lineToList _                  =
 >     error "lineToList: argument not created by function line"
 
 > invertAt :: Pitch -> Music Pitch -> Music Pitch
@@ -298,7 +301,7 @@ > invertAt1 pRef = mMap (\(p,x) -> (pitch (2 * absPitch pRef - absPitch p),x))
 
 > invert :: Music Pitch -> Music Pitch
-> invert m = 
+> invert m =
 >     let pRef = mFold pFun (++) (++) (flip const) m
 >     in  if null pRef then m -- no pitches in the structure!
 >         else invertAt (head pRef) m
@@ -306,7 +309,7 @@ >           pFun _ = []
 
 > invert1 :: Music (Pitch,a) -> Music (Pitch,a)
-> invert1 m = 
+> invert1 m =
 >     let pRef = mFold pFun (++) (++) (flip const) m
 >     in  if null pRef then m -- no pitches!
 >         else invertAt1 (head pRef) m
@@ -317,7 +320,7 @@ > retro n@(Prim _)    = n
 > retro (Modify c m)  = Modify c (retro m)
 > retro (m1 :+: m2)   = retro m2 :+: retro m1
-> retro (m1 :=: m2)   =  
+> retro (m1 :=: m2)   =
 >    let  d1 = dur m1
 >         d2 = dur m2
 >    in if d1>d2  then retro m1 :=: (rest (d1-d2) :+: retro m2)
@@ -360,7 +363,7 @@ 
 > removeZeros :: Music a -> Music a
 > removeZeros (Prim p)      = Prim p
-> removeZeros (m1 :+: m2)   = 
+> removeZeros (m1 :+: m2)   =
 >   let  m'1  = removeZeros m1
 >        m'2  = removeZeros m2
 >   in case (m'1,m'2) of
@@ -387,12 +390,12 @@ >                               in d1 ++ map (+(last d1)) (durL m2)
 > durL (m1 :=: m2)           =  mergeLD (durL m1) (durL m2)
 > durL (Modify (Tempo r) m)  =  map (/r) (durL m)
-> durL (Modify _ m)          =  durL m 
+> durL (Modify _ m)          =  durL m
 
 > mergeLD :: LazyDur -> LazyDur -> LazyDur
 > mergeLD [] ld = ld
 > mergeLD ld [] = ld
-> mergeLD ld1@(d1:ds1) ld2@(d2:ds2) = 
+> mergeLD ld1@(d1:ds1) ld2@(d2:ds2) =
 >   if d1<d2  then  d1 : mergeLD ds1 ld2
 >             else  d2 : mergeLD ld1 ds2
 
@@ -407,7 +410,7 @@ > cutL ld (Prim (Note oldD p))  = note (minL ld oldD) p
 > cutL ld (Prim (Rest oldD))    = rest (minL ld oldD)
 > cutL ld (m1 :=: m2)           = cutL ld m1 :=: cutL ld m2
-> cutL ld (m1 :+: m2)           =  
+> cutL ld (m1 :+: m2)           =
 >    let  m'1 = cutL ld m1
 >         m'2 = cutL (map (\d -> d - dur m'1) ld) m2
 >    in m'1 :+: m'2
@@ -456,7 +459,7 @@ >     fmap = mMap
 
 
-> mFold ::  (Primitive a -> b) -> (b->b->b) -> (b->b->b) -> 
+> mFold ::  (Primitive a -> b) -> (b->b->b) -> (b->b->b) ->
 >           (Control -> b -> b) -> Music a -> b
 > mFold f (+:) (=:) g m =
 >   let rec = mFold f (+:) (=:) g
@@ -483,7 +486,7 @@ > scaleDurations r (Prim (Rest d)) = rest (d/r)
 > scaleDurations r (m1 :+: m2) = scaleDurations r m1 :+: scaleDurations r m2
 > scaleDurations r (m1 :=: m2) = scaleDurations r m1 :=: scaleDurations r m2
-> scaleDurations r (Modify c m) = Modify c (scaleDurations r m) 
+> scaleDurations r (Modify c m) = Modify c (scaleDurations r m)
 
 > changeInstrument :: InstrumentName -> Music a -> Music a
 > changeInstrument i m = Modify (Instrument i) $ removeInstruments m
@@ -494,6 +497,3 @@ > removeInstruments (m1 :+: m2) = removeInstruments m1 :+: removeInstruments m2
 > removeInstruments (m1 :=: m2) = removeInstruments m1 :=: removeInstruments m2
 > removeInstruments m = m
-
-
-
ReadMe.txt view
@@ -1,5 +1,5 @@-Version 2.0.4
-Last modified: 04-July-2017
+Version 2.0.5
+Last modified: 26-June-2018
 Website: http://www.euterpea.com
  _____      _                             
 |  ___|    | |                            
@@ -10,15 +10,16 @@                         | |               
                         |_|               
 
+
+Maintainers:
+  Donya Quick <donyaquick@gmail.com>
+
 Authors:
   Paul Hudak
   Eric Cheng
   Hai (Paul) Liu
   Donya Quick 
   Dan Winograd-Cort 
-
-Maintainers:
-  Donya Quick <donyaquick@gmail.com>
 
 Euterpea is a domain-specific language embedded in Haskell for 
 computer music research, education, and development, providing