From 842de22970d531582965f284eed4ec25982e80bd Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Tue, 3 Dec 2019 10:48:53 -0800 Subject: [PATCH 01/13] use sef --- src/builder.rs | 8 ++++---- src/lib.rs | 6 +++--- src/meta.rs | 20 ++++++++++---------- src/midi.rs | 36 ++++++++++++++++++------------------ src/writer.rs | 10 +++++----- 5 files changed, 40 insertions(+), 40 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 3a46cd2..c404f19 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -13,13 +13,13 @@ pub struct AbsoluteEvent { } impl AbsoluteEvent { - pub fn new_midi(time: u64, midi: MidiMessage) -> AbsoluteEvent { + pub fn new_midi(time: u64, midi: MidiMessage) -> Self { AbsoluteEvent { time: time, event: Event::Midi(midi), } } - pub fn new_meta(time: u64, meta: MetaEvent) -> AbsoluteEvent { + pub fn new_meta(time: u64, meta: MetaEvent) -> Self { AbsoluteEvent { time: time, event: Event::Meta(meta), @@ -187,8 +187,8 @@ pub struct SMFBuilder { impl SMFBuilder { /// Create a new SMFBuilder. Initially the builder will have no tracks - pub fn new() -> SMFBuilder { - SMFBuilder { + pub fn new() -> Self { + Self { tracks: Vec::new(), } } diff --git a/src/lib.rs b/src/lib.rs index 745f9af..ae64026 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -256,20 +256,20 @@ pub struct SMF { impl SMF { /// Read an SMF file at the given path - pub fn from_file(path: &Path) -> Result { + pub fn from_file(path: &Path) -> Result { let mut file = try!(File::open(path)); SMFReader::read_smf(&mut file) } /// Read an SMF from the given reader - pub fn from_reader(reader: &mut dyn Read) -> Result { + pub fn from_reader(reader: &mut dyn Read) -> Result { SMFReader::read_smf(reader) } /// Convert a type 0 (single track) to type 1 (multi track) SMF /// Does nothing if the SMF is already in type 1 /// Returns None if the SMF is in type 2 (multi song) - pub fn to_multi_track(&self) -> Option { + pub fn to_multi_track(&self) -> Option { match self.format { SMFFormat::MultiTrack => Some(self.clone()), SMFFormat::MultiSong => None, diff --git a/src/meta.rs b/src/meta.rs index afec7d1..b64bfa4 100644 --- a/src/meta.rs +++ b/src/meta.rs @@ -17,7 +17,7 @@ pub enum MetaError { } impl From for MetaError { - fn from(err: Error) -> MetaError { + fn from(err: Error) -> Self { MetaError::Error(err) } } @@ -82,8 +82,8 @@ pub struct MetaEvent { } impl Clone for MetaEvent { - fn clone(&self) -> MetaEvent { - MetaEvent { + fn clone(&self) -> Self { + Self { command: self.command, length: self.length, data: self.data.clone(), @@ -151,22 +151,22 @@ impl MetaEvent { } /// Extract the next meta event from a reader - pub fn next_event(reader: &mut dyn Read) -> Result { + pub fn next_event(reader: &mut dyn Read) -> Result { let command = match MetaCommand::from_u8(try!(read_byte(reader))) { Some(c) => {c}, None => MetaCommand::Unknown, }; - let len = match SMFReader::read_vtime(reader) { + let length = match SMFReader::read_vtime(reader) { Ok(t) => { t } Err(_) => { return Err(MetaError::OtherErr("Couldn't read time for meta command")); } }; let mut data = Vec::new(); - try!(read_amount(reader,&mut data,len as usize)); - Ok(MetaEvent{ - command: command, - length: len, - data: data + try!(read_amount(reader,&mut data, length as usize)); + Ok(Self{ + command, + length, + data }) } diff --git a/src/midi.rs b/src/midi.rs index 89fdd4f..147a664 100644 --- a/src/midi.rs +++ b/src/midi.rs @@ -16,7 +16,7 @@ pub enum MidiError { } impl From for MidiError { - fn from(err: Error) -> MidiError { + fn from(err: Error) -> Self { MidiError::Error(err) } } @@ -141,9 +141,9 @@ impl MidiMessage { /// Create a midi message from a vector of bytes #[inline(always)] - pub fn from_bytes(bytes: Vec) -> MidiMessage{ + pub fn from_bytes(bytes: Vec) -> Self { // TODO: Validate bytes - MidiMessage { + Self { data: bytes, } } @@ -186,7 +186,7 @@ impl MidiMessage { /// Get the next midi message from the reader given that the /// status `stat` has just been read - pub fn next_message_given_status(stat: u8, reader: &mut dyn Read) -> Result { + pub fn next_message_given_status(stat: u8, reader: &mut dyn Read) -> Result { let mut ret:Vec = Vec::with_capacity(3); ret.push(stat); match MidiMessage::data_bytes(stat) { @@ -235,23 +235,23 @@ impl MidiMessage { // Functions to build midi messages /// Create a note on message - pub fn note_on(note: u8, velocity: u8, channel: u8) -> MidiMessage { - MidiMessage { + pub fn note_on(note: u8, velocity: u8, channel: u8) -> Self { + Self { data: vec![make_status(Status::NoteOn,channel), note, velocity], } } /// Create a note off message - pub fn note_off(note: u8, velocity: u8, channel: u8) -> MidiMessage { - MidiMessage { + pub fn note_off(note: u8, velocity: u8, channel: u8) -> Self { + Self { data: vec![make_status(Status::NoteOff,channel), note, velocity], } } /// Create a polyphonic aftertouch message /// This message is most often sent by pressing down on the key after it "bottoms out". - pub fn polyphonic_aftertouch(note: u8, pressure: u8, channel: u8) -> MidiMessage { - MidiMessage { + pub fn polyphonic_aftertouch(note: u8, pressure: u8, channel: u8) -> Self { + Self { data: vec![make_status(Status::PolyphonicAftertouch,channel), note, pressure], } } @@ -259,16 +259,16 @@ impl MidiMessage { /// Create a control change message /// This message is sent when a controller value changes. Controllers include devices such as /// pedals and levers. Controller numbers 120-127 are reserved as "Channel Mode Messages". - pub fn control_change(controler: u8, data: u8, channel: u8) -> MidiMessage { - MidiMessage { + pub fn control_change(controler: u8, data: u8, channel: u8) -> Self { + Self { data: vec![make_status(Status::ControlChange,channel), controler, data], } } /// Create a program change message /// This message sent when the patch number changes. `program` is the new program number. - pub fn program_change(program: u8, channel: u8) -> MidiMessage { - MidiMessage { + pub fn program_change(program: u8, channel: u8) -> Self { + Self { data: vec![make_status(Status::ProgramChange,channel), program], } } @@ -277,8 +277,8 @@ impl MidiMessage { /// This message is most often sent by pressing down on the key after it "bottoms out". This message /// is different from polyphonic after-touch. Use this message to send the single greatest pressure /// value (of all the current depressed keys). `pressure` is the pressure value. - pub fn channel_aftertouch(pressure: u8, channel: u8) -> MidiMessage { - MidiMessage { + pub fn channel_aftertouch(pressure: u8, channel: u8) -> Self { + Self { data: vec![make_status(Status::ChannelAftertouch,channel), pressure], } } @@ -288,8 +288,8 @@ impl MidiMessage { /// The pitch bender is measured by a fourteen bit value. Center (no pitch change) is 2000H. /// Sensitivity is a function of the transmitter. `lsb` are the least significant 7 bits. /// `msb` are the most significant 7 bits. - pub fn pitch_bend(lsb: u8, msb: u8, channel: u8) -> MidiMessage { - MidiMessage { + pub fn pitch_bend(lsb: u8, msb: u8, channel: u8) -> Self { + Self { data: vec![make_status(Status::PitchBend,channel), lsb, msb], } } diff --git a/src/writer.rs b/src/writer.rs index 7866074..5e1f69d 100644 --- a/src/writer.rs +++ b/src/writer.rs @@ -32,8 +32,8 @@ impl SMFWriter { /// Create a new SMFWriter with the given number of units per /// beat. The SMFWriter will initially have no tracks. - pub fn new_with_division(ticks: i16) -> SMFWriter { - SMFWriter { + pub fn new_with_division(ticks: i16) -> Self { + Self { format: 1, ticks: ticks, tracks: Vec::new(), @@ -42,8 +42,8 @@ impl SMFWriter { /// Create a new SMFWriter with the given format and number of /// units per beat. The SMFWriter will initially have no tracks. - pub fn new_with_division_and_format(format: SMFFormat, ticks: i16) -> SMFWriter { - SMFWriter { + pub fn new_with_division_and_format(format: SMFFormat, ticks: i16) -> Self { + Self { format: format as u16, ticks: ticks, tracks: Vec::new(), @@ -51,7 +51,7 @@ impl SMFWriter { } /// Create a writer that has all the tracks from the given SMF already added - pub fn from_smf(smf: SMF) -> SMFWriter { + pub fn from_smf(smf: SMF) -> Self { let mut writer = SMFWriter::new_with_division_and_format (smf.format, smf.division); From 995c32db95a28377a8ac5111321efff0ad54bf2f Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Tue, 3 Dec 2019 10:50:31 -0800 Subject: [PATCH 02/13] use self --- src/meta.rs | 64 ++++++++++++++++++++++++++--------------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/src/meta.rs b/src/meta.rs index b64bfa4..67ba1b4 100644 --- a/src/meta.rs +++ b/src/meta.rs @@ -191,8 +191,8 @@ impl MetaEvent { // event constructors below /// Create a sequence number meta event - pub fn sequence_number(sequence_number: u16) -> MetaEvent { - MetaEvent { + pub fn sequence_number(sequence_number: u16) -> Self { + Self { command: MetaCommand::SequenceNumber, length: 0x02, data: MetaEvent::u16_to_vec(sequence_number), @@ -200,8 +200,8 @@ impl MetaEvent { } /// Create a text meta event - pub fn text_event(text: String) -> MetaEvent { - MetaEvent { + pub fn text_event(text: String) -> Self { + Self { command: MetaCommand::TextEvent, length: text.len() as u64, data: text.into_bytes(), @@ -209,8 +209,8 @@ impl MetaEvent { } /// Create a copyright notice meta event - pub fn copyright_notice(copyright: String) -> MetaEvent { - MetaEvent { + pub fn copyright_notice(copyright: String) -> Self { + Self { command: MetaCommand::CopyrightNotice, length: copyright.len() as u64, data: copyright.into_bytes(), @@ -218,8 +218,8 @@ impl MetaEvent { } /// Create a name meta event - pub fn sequence_or_track_name(name: String) -> MetaEvent { - MetaEvent { + pub fn sequence_or_track_name(name: String) -> Self { + Self { command: MetaCommand::SequenceOrTrackName, length: name.len() as u64, data: name.into_bytes(), @@ -227,8 +227,8 @@ impl MetaEvent { } /// Create an instrument name meta event - pub fn instrument_name(name: String) -> MetaEvent { - MetaEvent { + pub fn instrument_name(name: String) -> Self { + Self { command: MetaCommand::InstrumentName, length: name.len() as u64, data: name.into_bytes(), @@ -236,8 +236,8 @@ impl MetaEvent { } /// Create a lyric text meta event - pub fn lyric_text(text: String) -> MetaEvent { - MetaEvent { + pub fn lyric_text(text: String) -> Self { + Self { command: MetaCommand::LyricText, length: text.len() as u64, data: text.into_bytes(), @@ -246,8 +246,8 @@ impl MetaEvent { /// Create a marker text meta event - pub fn marker_text(text: String) -> MetaEvent { - MetaEvent { + pub fn marker_text(text: String) -> Self { + Self { command: MetaCommand::MarkerText, length: text.len() as u64, data: text.into_bytes(), @@ -255,8 +255,8 @@ impl MetaEvent { } /// Create a cue point meta event - pub fn cue_point(text: String) -> MetaEvent { - MetaEvent { + pub fn cue_point(text: String) -> Self { + Self { command: MetaCommand::CuePoint, length: text.len() as u64, data: text.into_bytes(), @@ -264,8 +264,8 @@ impl MetaEvent { } /// Create a midi channel prefix assignment meta event - pub fn midichannel_prefix_assignment(channel: u8) -> MetaEvent { - MetaEvent { + pub fn midichannel_prefix_assignment(channel: u8) -> Self { + Self { command: MetaCommand::MIDIChannelPrefixAssignment, length: 1, data: vec![channel], @@ -273,8 +273,8 @@ impl MetaEvent { } /// Create a midi port prefix assignment meta event - pub fn midiport_prefix_assignment(port: u8) -> MetaEvent { - MetaEvent { + pub fn midiport_prefix_assignment(port: u8) -> Self { + Self { command: MetaCommand::MIDIPortPrefixAssignment, length: 1, data: vec![port], @@ -282,8 +282,8 @@ impl MetaEvent { } /// Create an end of track meta event - pub fn end_of_track() -> MetaEvent { - MetaEvent { + pub fn end_of_track() -> Self { + Self { command: MetaCommand::EndOfTrack, length: 0, data: vec![], @@ -293,8 +293,8 @@ impl MetaEvent { /// Create an event to set track tempo. This is stored /// as a 24-bit value. This method will fail an assertion if /// the supplied tempo is greater than 2^24. - pub fn tempo_setting(tempo: u32) -> MetaEvent { - MetaEvent { + pub fn tempo_setting(tempo: u32) -> Self { + Self { command: MetaCommand::TempoSetting, length: 3, data: MetaEvent::u24_to_vec(tempo), @@ -302,8 +302,8 @@ impl MetaEvent { } /// Create an smpte offset meta event - pub fn smpte_offset(hours: u8, minutes: u8, seconds: u8, frames: u8, fractional: u8) -> MetaEvent { - MetaEvent { + pub fn smpte_offset(hours: u8, minutes: u8, seconds: u8, frames: u8, fractional: u8) -> Self { + Self { command: MetaCommand::SMPTEOffset, length: 5, data: vec![hours,minutes,seconds,frames,fractional], @@ -322,8 +322,8 @@ impl MetaEvent { /// The parameter `num_32nd_notes_per_24_clocks` defines this in terms of the /// number of 1/32 notes which make up the usual 24 MIDI Clocks /// (the 'standard' quarter note). 8 is standard - pub fn time_signature(numerator: u8, denominator: u8, clocks_per_tick: u8, num_32nd_notes_per_24_clocks: u8) -> MetaEvent { - MetaEvent { + pub fn time_signature(numerator: u8, denominator: u8, clocks_per_tick: u8, num_32nd_notes_per_24_clocks: u8) -> Self { + Self { command: MetaCommand::TimeSignature, length: 4, data: vec![numerator,denominator,clocks_per_tick,num_32nd_notes_per_24_clocks], @@ -335,8 +335,8 @@ impl MetaEvent { /// `sharps_flats` of 0 represents a key of C, negative numbers represent /// 'flats', while positive numbers represent 'sharps'. - pub fn key_signature(sharps_flats: u8, major_minor: u8) -> MetaEvent { - MetaEvent { + pub fn key_signature(sharps_flats: u8, major_minor: u8) -> Self { + Self { command: MetaCommand::KeySignature, length: 2, data: vec![sharps_flats, major_minor], @@ -346,8 +346,8 @@ impl MetaEvent { /// This is the MIDI-file equivalent of the System Exclusive Message. /// sequencer-specific directives can be incorporated into a /// MIDI file using this event. - pub fn sequencer_specific_event(data: Vec) -> MetaEvent { - MetaEvent { + pub fn sequencer_specific_event(data: Vec) -> Self { + Self { command: MetaCommand::SequencerSpecificEvent, length: data.len() as u64, data: data, From 150fe41f1faa5acc43d5663c6e5c16da4e134003 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Tue, 3 Dec 2019 10:54:01 -0800 Subject: [PATCH 03/13] from_smf -> from --- src/bin/copy.rs | 2 +- src/writer.rs | 55 ++++++++++++++++++++++++++----------------------- 2 files changed, 30 insertions(+), 27 deletions(-) diff --git a/src/bin/copy.rs b/src/bin/copy.rs index 174fac4..bd53176 100644 --- a/src/bin/copy.rs +++ b/src/bin/copy.rs @@ -17,7 +17,7 @@ fn main() { }; match SMF::from_file(&Path::new(&pathstr[..])) { Ok(smf) => { - let writer = SMFWriter::from_smf(smf); + let writer = SMFWriter::from(smf); writer.write_to_file(&Path::new(&deststr[..])).unwrap(); } Err(e) => { diff --git a/src/writer.rs b/src/writer.rs index 5e1f69d..c54c91c 100644 --- a/src/writer.rs +++ b/src/writer.rs @@ -1,6 +1,8 @@ -use std::fs::OpenOptions; -use std::io::{Error,Write}; -use std::path::Path; +use std::{ + fs::OpenOptions, + io::{Error,Write}, + path::Path +}; use byteorder::{BigEndian, WriteBytesExt}; @@ -50,29 +52,6 @@ impl SMFWriter { } } - /// Create a writer that has all the tracks from the given SMF already added - pub fn from_smf(smf: SMF) -> Self { - let mut writer = SMFWriter::new_with_division_and_format - (smf.format, smf.division); - - for track in smf.tracks.iter() { - let mut length = 0; - let mut saw_eot = false; - let mut vec = Vec::new(); - writer.start_track_header(&mut vec); - - for event in track.events.iter() { - length += SMFWriter::write_vtime(event.vtime as u64, &mut vec).unwrap(); // TODO: Handle error - writer.write_event(&mut vec, &(event.event), &mut length, &mut saw_eot); - } - - writer.finish_track_write(&mut vec, &mut length, saw_eot); - writer.tracks.push(vec); - } - - writer - } - pub fn vtime_to_vec(val: u64) -> Vec { let mut storage = Vec::new(); let mut cur = val; @@ -218,6 +197,30 @@ impl SMFWriter { } } +impl From for SMFWriter { + /// Create a writer that has all the tracks from the given SMF already added + fn from(smf: SMF) -> Self { + let mut writer = Self::new_with_division_and_format + (smf.format, smf.division); + + for track in smf.tracks.iter() { + let mut length = 0; + let mut saw_eot = false; + let mut vec = Vec::new(); + writer.start_track_header(&mut vec); + + for event in track.events.iter() { + length += Self::write_vtime(event.vtime as u64, &mut vec).unwrap(); // TODO: Handle error + writer.write_event(&mut vec, &(event.event), &mut length, &mut saw_eot); + } + + writer.finish_track_write(&mut vec, &mut length, saw_eot); + writer.tracks.push(vec); + } + + writer + } +} #[test] fn vwrite() { From c7d752b06d5115c454b92d3bfdbecc42983223d7 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Tue, 3 Dec 2019 11:11:39 -0800 Subject: [PATCH 04/13] use tryfrom trait --- src/bin/copy.rs | 3 ++- src/bin/test.rs | 3 ++- src/lib.rs | 24 +++++++++++++++--------- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/bin/copy.rs b/src/bin/copy.rs index bd53176..f447cba 100644 --- a/src/bin/copy.rs +++ b/src/bin/copy.rs @@ -3,6 +3,7 @@ extern crate rimd; use rimd::{SMF,SMFError,SMFWriter}; use std::env::{args,Args}; use std::path::Path; +use std::convert::TryFrom; fn main() { let mut args: Args = args(); @@ -15,7 +16,7 @@ fn main() { Some(s) => s, None => { panic!("Need a destination path") }, }; - match SMF::from_file(&Path::new(&pathstr[..])) { + match SMF::try_from(Path::new(&pathstr[..])) { Ok(smf) => { let writer = SMFWriter::from(smf); writer.write_to_file(&Path::new(&deststr[..])).unwrap(); diff --git a/src/bin/test.rs b/src/bin/test.rs index 63b642d..66a0506 100644 --- a/src/bin/test.rs +++ b/src/bin/test.rs @@ -3,6 +3,7 @@ extern crate rimd; use rimd::{SMF,SMFError}; use std::env::{args,Args}; use std::path::Path; +use std::convert::TryFrom; fn main() { let mut args: Args = args(); @@ -12,7 +13,7 @@ fn main() { None => { panic!("Please pass a path to an SMF to test") }, }; println!("Reading: {}",pathstr); - match SMF::from_file(&Path::new(&pathstr[..])) { + match SMF::try_from(Path::new(&pathstr[..])) { Ok(smf) => { println!("format: {}",smf.format); println!("tracks: {}",smf.tracks.len()); diff --git a/src/lib.rs b/src/lib.rs index ae64026..4cbac44 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -256,15 +256,6 @@ pub struct SMF { impl SMF { /// Read an SMF file at the given path - pub fn from_file(path: &Path) -> Result { - let mut file = try!(File::open(path)); - SMFReader::read_smf(&mut file) - } - - /// Read an SMF from the given reader - pub fn from_reader(reader: &mut dyn Read) -> Result { - SMFReader::read_smf(reader) - } /// Convert a type 0 (single track) to type 1 (multi track) SMF /// Does nothing if the SMF is already in type 1 @@ -320,3 +311,18 @@ impl SMF { } } +impl<'a> std::convert::TryFrom<&'a Path> for SMF { + type Error = SMFError; + fn try_from(path: &'a Path) -> Result { + let mut file = try!(File::open(path)); + SMFReader::read_smf(&mut file) + } +} + +impl<'a> std::convert::TryFrom<&'a mut dyn Read> for SMF { + type Error = SMFError; + /// Read an SMF from the given reader + fn try_from(reader: &'a mut dyn Read) -> Result { + SMFReader::read_smf(reader) + } +} From c6f8e929d9c191a17011cd9a0bee7dc9817bdd35 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Tue, 3 Dec 2019 11:13:31 -0800 Subject: [PATCH 05/13] fixed test --- src/writer.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/writer.rs b/src/writer.rs index c54c91c..1952c12 100644 --- a/src/writer.rs +++ b/src/writer.rs @@ -21,7 +21,7 @@ use ::{Event,AbsoluteEvent,MetaEvent,MetaCommand,SMFFormat}; /// let mut builder = SMFBuilder::new(); /// // add some events to builder /// let smf = builder.result(); -/// let writer = SMFWriter::from_smf(smf); +/// let writer = SMFWriter::from(smf); /// let result = writer.write_to_file(Path::new("/path/to/file.smf")); /// // handle result pub struct SMFWriter { From 07aa7e92cb8a4f70dbc0a34efeebce51683a0c73 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Tue, 3 Dec 2019 11:14:40 -0800 Subject: [PATCH 06/13] smfwriter::new --- src/writer.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/writer.rs b/src/writer.rs index 1952c12..9678824 100644 --- a/src/writer.rs +++ b/src/writer.rs @@ -32,6 +32,14 @@ pub struct SMFWriter { impl SMFWriter { + pub fn new(format: u16, ticks: i16, tracks: Vec>) -> Self { + Self { + format, + ticks, + tracks, + } + } + /// Create a new SMFWriter with the given number of units per /// beat. The SMFWriter will initially have no tracks. pub fn new_with_division(ticks: i16) -> Self { From 8358d12d5e6bb6095d5da486eb00c2e11af401de Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Tue, 3 Dec 2019 11:18:28 -0800 Subject: [PATCH 07/13] refactoring --- src/builder.rs | 2 +- src/writer.rs | 16 ++++++---------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index c404f19..9a6c93c 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -194,7 +194,7 @@ impl SMFBuilder { } /// Get the number of tracks currenly in the builder - pub fn num_tracks(&self) -> usize { + pub fn len(&self) -> usize { self.tracks.len() } diff --git a/src/writer.rs b/src/writer.rs index 9678824..3cb8da3 100644 --- a/src/writer.rs +++ b/src/writer.rs @@ -43,21 +43,17 @@ impl SMFWriter { /// Create a new SMFWriter with the given number of units per /// beat. The SMFWriter will initially have no tracks. pub fn new_with_division(ticks: i16) -> Self { - Self { - format: 1, - ticks: ticks, - tracks: Vec::new(), - } + Self::new(1, ticks, Vec::new()) } /// Create a new SMFWriter with the given format and number of /// units per beat. The SMFWriter will initially have no tracks. pub fn new_with_division_and_format(format: SMFFormat, ticks: i16) -> Self { - Self { - format: format as u16, - ticks: ticks, - tracks: Vec::new(), - } + Self::new( + format as u16, + ticks, + Vec::new() + ) } pub fn vtime_to_vec(val: u64) -> Vec { From 18dcd2e6c890f2c2f13ed711ad63b48c2040f265 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Tue, 3 Dec 2019 11:27:28 -0800 Subject: [PATCH 08/13] fix warnings by changing try! to ? --- src/lib.rs | 2 +- src/meta.rs | 4 ++-- src/midi.rs | 12 ++++++------ src/reader.rs | 24 ++++++++++++------------ src/util.rs | 4 ++-- src/writer.rs | 20 ++++++++++---------- 6 files changed, 33 insertions(+), 33 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 4cbac44..4e8d6d0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -314,7 +314,7 @@ impl SMF { impl<'a> std::convert::TryFrom<&'a Path> for SMF { type Error = SMFError; fn try_from(path: &'a Path) -> Result { - let mut file = try!(File::open(path)); + let mut file = File::open(path)?; SMFReader::read_smf(&mut file) } } diff --git a/src/meta.rs b/src/meta.rs index 67ba1b4..b50310f 100644 --- a/src/meta.rs +++ b/src/meta.rs @@ -153,7 +153,7 @@ impl MetaEvent { /// Extract the next meta event from a reader pub fn next_event(reader: &mut dyn Read) -> Result { let command = - match MetaCommand::from_u8(try!(read_byte(reader))) { + match MetaCommand::from_u8(read_byte(reader)?) { Some(c) => {c}, None => MetaCommand::Unknown, }; @@ -162,7 +162,7 @@ impl MetaEvent { Err(_) => { return Err(MetaError::OtherErr("Couldn't read time for meta command")); } }; let mut data = Vec::new(); - try!(read_amount(reader,&mut data, length as usize)); + read_amount(reader,&mut data, length as usize)?; Ok(Self{ command, length, diff --git a/src/midi.rs b/src/midi.rs index 147a664..10c8029 100644 --- a/src/midi.rs +++ b/src/midi.rs @@ -191,14 +191,14 @@ impl MidiMessage { ret.push(stat); match MidiMessage::data_bytes(stat) { 0 => {} - 1 => { ret.push(try!(read_byte(reader))); } - 2 => { ret.push(try!(read_byte(reader))); - ret.push(try!(read_byte(reader))); } + 1 => { ret.push(read_byte(reader)?); } + 2 => { ret.push(read_byte(reader)?); + ret.push(read_byte(reader)?); } -1 => { return Err(MidiError::OtherErr("Don't handle variable sized yet")); } -2 => { // skip SysEx message while { - let byte = try!(read_byte(reader)); + let byte = read_byte(reader)?; ret.push(byte); byte != Status::SysExEnd as u8 } {} @@ -217,7 +217,7 @@ impl MidiMessage { match MidiMessage::data_bytes(stat) { 0 => { panic!("Can't have zero length message with running status"); } 1 => { } // already read it - 2 => { ret.push(try!(read_byte(reader))); } // only need one more byte + 2 => { ret.push(read_byte(reader)?); } // only need one more byte -1 => { return Err(MidiError::OtherErr("Don't handle variable sized yet")); } -2 => { return Err(MidiError::OtherErr("Running status not permitted with meta and sysex event")); } _ => { return Err(MidiError::InvalidStatus(stat)); } @@ -227,7 +227,7 @@ impl MidiMessage { /// Extract next midi message from a reader pub fn next_message(reader: &mut dyn Read) -> Result { - let stat = try!(read_byte(reader)); + let stat = read_byte(reader)?; MidiMessage::next_message_given_status(stat,reader) } diff --git a/src/reader.rs b/src/reader.rs index fe2127c..84fbae6 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -12,7 +12,7 @@ pub struct SMFReader; impl SMFReader { fn parse_header(reader: &mut dyn Read) -> Result { let mut header:[u8;14] = [0;14]; - try!(fill_buf(reader,&mut header)); + fill_buf(reader,&mut header)?; // skip RIFF header if present if header[0] == 0x52 && @@ -20,8 +20,8 @@ impl SMFReader { header[2] == 0x46 && header[3] == 0x46 { let mut skip:[u8; 6] = [0; 6]; - try!(fill_buf(reader, &mut skip)); - try!(fill_buf(reader, &mut header)); + fill_buf(reader, &mut skip)?; + fill_buf(reader, &mut header)?; } if header[0] != 0x4D || @@ -46,8 +46,8 @@ impl SMFReader { } fn next_event(reader: &mut dyn Read, laststat: u8, was_running: &mut bool) -> Result { - let time = try!(SMFReader::read_vtime(reader)); - let stat = try!(read_byte(reader)); + let time = Self::read_vtime(reader)?; + let stat = read_byte(reader)?; if (stat & 0x80) == 0 { *was_running = true; @@ -57,7 +57,7 @@ impl SMFReader { match stat { 0xFF => { - let event = try!(MetaEvent::next_event(reader)); + let event = MetaEvent::next_event(reader)?; Ok( TrackEvent { vtime: time, event: Event::Meta(event), @@ -67,9 +67,9 @@ impl SMFReader { let msg = if (stat & 0x80) == 0 { // this is a running status, so assume we have the same status as last time - try!(MidiMessage::next_message_running_status(laststat,stat,reader)) + MidiMessage::next_message_running_status(laststat,stat,reader)? } else { - try!(MidiMessage::next_message_given_status(stat,reader)) + MidiMessage::next_message_given_status(stat,reader)? }; Ok( TrackEvent { vtime: time, @@ -86,14 +86,14 @@ impl SMFReader { let mut copyright = None; let mut name = None; - try!(fill_buf(reader,&mut buf)); + fill_buf(reader,&mut buf)?; if buf[0] != 0x4D || // "MTrk" buf[1] != 0x54 || buf[2] != 0x72 || buf[3] != 0x6B { return Err(SMFError::InvalidSMFFile("Invalid track magic")); } - try!(fill_buf(reader,&mut buf)); + fill_buf(reader,&mut buf)?; let len = ((buf[0] as u32) << 24 | (buf[1] as u32) << 16 | @@ -174,7 +174,7 @@ impl SMFReader { if i > 9 { return Err(SMFError::InvalidSMFFile("Variable length value too long")); } - let next = try!(read_byte(reader)); + let next = read_byte(reader)?; res |= next as u64 & val_mask; if (next & cont_mask) == 0 { break; @@ -190,7 +190,7 @@ impl SMFReader { match smf { Ok(ref mut s) => { for _ in 0..s.tracks.capacity() { - s.tracks.push(try!(SMFReader::parse_track(reader))); + s.tracks.push(SMFReader::parse_track(reader)?); } } _ => {} diff --git a/src/util.rs b/src/util.rs index ea36718..31a02a8 100644 --- a/src/util.rs +++ b/src/util.rs @@ -21,7 +21,7 @@ pub fn note_num_to_name(num: u32) -> String { /// Read a single byte from a Reader pub fn read_byte(reader: &mut dyn Read) -> Result { let mut b = [0; 1]; - try!(reader.read(&mut b)); + reader.read(&mut b)?; Ok(b[0]) } @@ -29,7 +29,7 @@ pub fn read_byte(reader: &mut dyn Read) -> Result { pub fn fill_buf(reader: &mut dyn Read, buf: &mut [u8]) -> Result<(),Error> { let mut read = 0; while read < buf.len() { - let bytes_read = try!(reader.read(&mut buf[read..])); + let bytes_read = reader.read(&mut buf[read..])?; if bytes_read == 0 { return Err(Error::new(ErrorKind::InvalidData, "file ends before it should")); } diff --git a/src/writer.rs b/src/writer.rs index 3cb8da3..90c151e 100644 --- a/src/writer.rs +++ b/src/writer.rs @@ -80,7 +80,7 @@ impl SMFWriter { // Write a variable length value. Return number of bytes written. pub fn write_vtime(val: u64, writer: &mut dyn Write) -> Result { let storage = SMFWriter::vtime_to_vec(val); - try!(writer.write_all(&storage[..])); + writer.write_all(&storage[..])?; Ok(storage.len() as u32) } @@ -174,20 +174,20 @@ impl SMFWriter { // actual writing stuff below fn write_header(&self, writer: &mut dyn Write) -> Result<(),Error> { - try!(writer.write_all(&[0x4D,0x54,0x68,0x64])); - try!(writer.write_u32::(6)); - try!(writer.write_u16::(self.format)); - try!(writer.write_u16::(self.tracks.len() as u16)); - try!(writer.write_i16::(self.ticks)); + writer.write_all(&[0x4D,0x54,0x68,0x64])?; + writer.write_u32::(6)?; + writer.write_u16::(self.format)?; + writer.write_u16::(self.tracks.len() as u16)?; + writer.write_i16::(self.ticks)?; Ok(()) } /// Write out all the tracks that have been added to this /// SMFWriter to the passed writer pub fn write_all(self, writer: &mut dyn Write) -> Result<(),Error> { - try!(self.write_header(writer)); + self.write_header(writer)?; for track in self.tracks.into_iter() { - try!(writer.write_all(&track[..])); + writer.write_all(&track[..])?; } Ok(()) } @@ -196,11 +196,11 @@ impl SMFWriter { /// file. /// Warning: This will overwrite an existing file pub fn write_to_file(self, path: &Path) -> Result<(),Error> { - let mut file = try!(OpenOptions::new().write(true).truncate(true).create(true).open(path)); + let mut file = OpenOptions::new().write(true).truncate(true).create(true).open(path)?; self.write_all(&mut file) } - } + impl From for SMFWriter { /// Create a writer that has all the tracks from the given SMF already added fn from(smf: SMF) -> Self { From 73535e18a300dc9dc7d5ef93741dd1d3cec4e8bd Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Tue, 3 Dec 2019 11:39:50 -0800 Subject: [PATCH 09/13] refactoring --- src/bin/test.rs | 7 +------ src/lib.rs | 8 ++++---- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/src/bin/test.rs b/src/bin/test.rs index 66a0506..0710761 100644 --- a/src/bin/test.rs +++ b/src/bin/test.rs @@ -30,12 +30,7 @@ fn main() { } } Err(e) => { - match e { - SMFError::InvalidSMFFile(s) => {println!("{}",s);} - SMFError::Error(e) => {println!("io: {}",e);} - SMFError::MidiError(e) => {println!("Midi Error: {}",e);} - SMFError::MetaError(_) => {println!("Meta Error");} - } + println!("{}", e); } } } diff --git a/src/lib.rs b/src/lib.rs index 4e8d6d0..20c71fb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -185,25 +185,25 @@ pub enum SMFError { } impl From for SMFError { - fn from(err: Error) -> SMFError { + fn from(err: Error) -> Self { SMFError::Error(err) } } impl From for SMFError { - fn from(err: MidiError) -> SMFError { + fn from(err: MidiError) -> Self { SMFError::MidiError(err) } } impl From for SMFError { - fn from(err: MetaError) -> SMFError { + fn from(err: MetaError) -> Self { SMFError::MetaError(err) } } impl From for SMFError { - fn from(_: FromUtf8Error) -> SMFError { + fn from(_: FromUtf8Error) -> Self { SMFError::InvalidSMFFile("Invalid UTF8 data in file") } } From 560df72b5863fc390b0b93a38b3488096ede3454 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Tue, 3 Dec 2019 11:49:52 -0800 Subject: [PATCH 10/13] refactoring --- src/bin/copy.rs | 9 ++------- src/bin/test.rs | 6 ++---- src/lib.rs | 10 ++++++++++ 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/bin/copy.rs b/src/bin/copy.rs index f447cba..add9f72 100644 --- a/src/bin/copy.rs +++ b/src/bin/copy.rs @@ -1,6 +1,6 @@ extern crate rimd; -use rimd::{SMF,SMFError,SMFWriter}; +use rimd::{SMF,SMFWriter}; use std::env::{args,Args}; use std::path::Path; use std::convert::TryFrom; @@ -22,12 +22,7 @@ fn main() { writer.write_to_file(&Path::new(&deststr[..])).unwrap(); } Err(e) => { - match e { - SMFError::InvalidSMFFile(s) => {println!("{}",s);} - SMFError::Error(e) => {println!("io: {}",e);} - SMFError::MidiError(_) => {println!("Midi Error");} - SMFError::MetaError(_) => {println!("Meta Error");} - } + println!("{}",e) } } } diff --git a/src/bin/test.rs b/src/bin/test.rs index 0710761..9c9b521 100644 --- a/src/bin/test.rs +++ b/src/bin/test.rs @@ -1,6 +1,6 @@ extern crate rimd; -use rimd::{SMF,SMFError}; +use rimd::{SMF}; use std::env::{args,Args}; use std::path::Path; use std::convert::TryFrom; @@ -15,9 +15,7 @@ fn main() { println!("Reading: {}",pathstr); match SMF::try_from(Path::new(&pathstr[..])) { Ok(smf) => { - println!("format: {}",smf.format); - println!("tracks: {}",smf.tracks.len()); - println!("division: {}",smf.division); + println!("{}", smf); let mut tnum = 1; for track in smf.tracks.iter() { let mut time: u64 = 0; diff --git a/src/lib.rs b/src/lib.rs index 20c71fb..dd0d373 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -255,6 +255,10 @@ pub struct SMF { impl SMF { + + pub fn len(&self) -> usize { + self.tracks.len() + } /// Read an SMF file at the given path /// Convert a type 0 (single track) to type 1 (multi track) SMF @@ -311,6 +315,12 @@ impl SMF { } } +impl fmt::Display for SMF { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "format: {}, tracks: {}, division: {}", self.format, self.len(), self.division) + } +} + impl<'a> std::convert::TryFrom<&'a Path> for SMF { type Error = SMFError; fn try_from(path: &'a Path) -> Result { From 177eebbae41a829950fb71de4ad14942ca8a1fa2 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Tue, 3 Dec 2019 11:53:09 -0800 Subject: [PATCH 11/13] refactoring --- src/builder.rs | 10 ++-------- src/lib.rs | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 9a6c93c..9ebcddb 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -29,19 +29,13 @@ impl AbsoluteEvent { /// Return true if the event inside this AbsoluteEvent is a midi /// event, false if it's a meta event pub fn is_midi(&self) -> bool { - match self.event { - Event::Midi(_) => true, - Event::Meta(_) => false, - } + self.event.is_midi() } /// Return true if the event inside this AbsoluteEvent is a meta /// event, false if it's a midi event pub fn is_meta(&self) -> bool { - match self.event { - Event::Midi(_) => false, - Event::Meta(_) => true, - } + self.event.is_meta() } pub fn get_event(&self) -> &Event { diff --git a/src/lib.rs b/src/lib.rs index dd0d373..dfdb9f6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -117,6 +117,20 @@ impl Event { } } } + + pub fn is_midi(&self) -> bool { + match self { + Event::Midi(_) => true, + Event::Meta(_) => false, + } + } + + pub fn is_meta(&self) -> bool { + match self { + Event::Midi(_) => false, + Event::Meta(_) => true, + } + } } /// An event occuring in the track. From 0d1efea67db6163ae07c557bd0922f9e6be0b108 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Tue, 3 Dec 2019 11:54:18 -0800 Subject: [PATCH 12/13] refactoring --- src/builder.rs | 16 ++++------------ src/writer.rs | 4 ++-- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 9ebcddb..82d74c0 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -8,19 +8,19 @@ use ::{SMF,Event,SMFFormat,MetaEvent,MidiMessage,Track,TrackEvent}; /// This is useful for apps that want to store events internally /// with absolute times and then quickly build an SMF file for saving etc... pub struct AbsoluteEvent { - time: u64, - event: Event, + pub time: u64, + pub event: Event, } impl AbsoluteEvent { pub fn new_midi(time: u64, midi: MidiMessage) -> Self { - AbsoluteEvent { + Self { time: time, event: Event::Midi(midi), } } pub fn new_meta(time: u64, meta: MetaEvent) -> Self { - AbsoluteEvent { + Self { time: time, event: Event::Meta(meta), } @@ -37,14 +37,6 @@ impl AbsoluteEvent { pub fn is_meta(&self) -> bool { self.event.is_meta() } - - pub fn get_event(&self) -> &Event { - &self.event - } - - pub fn get_time(&self) -> u64 { - self.time - } } impl Eq for AbsoluteEvent {} diff --git a/src/writer.rs b/src/writer.rs index 90c151e..ca219f3 100644 --- a/src/writer.rs +++ b/src/writer.rs @@ -160,10 +160,10 @@ impl SMFWriter { } for ev in track { - let vtime = ev.get_time() - cur_time; + let vtime = ev.time - cur_time; cur_time = vtime; length += SMFWriter::write_vtime(vtime as u64,&mut vec).unwrap(); // TODO: Handle error - self.write_event(&mut vec, ev.get_event(), &mut length, &mut saw_eot); + self.write_event(&mut vec, &ev.event, &mut length, &mut saw_eot); } self.finish_track_write(&mut vec, &mut length, saw_eot); From 290e3f333cb7863c681bd6b9d6343833eb82cc5c Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Tue, 3 Dec 2019 11:55:28 -0800 Subject: [PATCH 13/13] refactoring --- src/writer.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/writer.rs b/src/writer.rs index ca219f3..e8df1c3 100644 --- a/src/writer.rs +++ b/src/writer.rs @@ -40,6 +40,10 @@ impl SMFWriter { } } + pub fn len(&self) -> usize { + self.tracks.len() + } + /// Create a new SMFWriter with the given number of units per /// beat. The SMFWriter will initially have no tracks. pub fn new_with_division(ticks: i16) -> Self { @@ -177,7 +181,7 @@ impl SMFWriter { writer.write_all(&[0x4D,0x54,0x68,0x64])?; writer.write_u32::(6)?; writer.write_u16::(self.format)?; - writer.write_u16::(self.tracks.len() as u16)?; + writer.write_u16::(self.len() as u16)?; writer.write_i16::(self.ticks)?; Ok(()) }