Subject: bin/20388: Let midiplay(1) play MIDI files
To: None <gnats-bugs@gnats.netbsd.org>
From: None <cube@cubidou.net>
List: netbsd-bugs
Date: 02/17/2003 14:32:08
>Number:         20388
>Category:       bin
>Synopsis:       midiplay(1) doesn't play RMID files, fix included
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    bin-bug-people
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Mon Feb 17 05:33:01 PST 2003
>Closed-Date:
>Last-Modified:
>Originator:     Quentin Garnier
>Release:        NetBSD 1.6M
>Organization:
	
>Environment:
	
	
System: NetBSD chewie 1.6M NetBSD 1.6M (CHEWIE) #1: Thu Jan 23 14:37:25 CET 2003 cube@chewie:/home/cube/sys/src/NetBSD/src/sys/arch/i386/compile/CHEWIE i386
Architecture: i386
Machine: i386
>Description:
	RMID files are Standard MIDI Files embedded in a RIFF container.
	They're usually found in Windows. Some additionnal information can
	be found in other chunks of data, but included patch doesn't parse
	them.

	midiplay(1) doesn't play such files.
>How-To-Repeat:
>Fix:
	All that's needed is a simple parsing of RIFF headers.

Index: midiplay.1
===================================================================
RCS file: /cvsroot/src/usr.bin/midiplay/midiplay.1,v
retrieving revision 1.12
diff -r1.12 midiplay.1
40c40
< .Nd play MIDI files
---
> .Nd play MIDI and RMID files
56c56
< command plays MIDI files using the sequencer device.
---
> command plays MIDI and RMID files using the sequencer device.
58a59,64
> .Pp
> RMID files are Standard MIDI Files embedded in a RIFF container and
> can usually be found with the 'rmi' extension. They contain some
> additionnal information in other chunks which are not parsed by
> .Nm
> yet.
Index: midiplay.c
===================================================================
RCS file: /cvsroot/src/usr.bin/midiplay/midiplay.c,v
retrieving revision 1.17
diff -r1.17 midiplay.c
118a119,122
> #define	RMID_SIG "RIFF"
> #define	RMID_MIDI_ID "RMID"
> #define	RMID_DATA_ID "data"
> 
125a130
> #define GET32_LE(p) (((p)[3] << 24) | ((p)[2] << 16) | ((p)[1] << 8) | (p)[0])
292a298,342
> 	if (tot < (MARK_LEN + 4)) {
> 		warnx("Not a MIDI file, too short");
> 		return;
> 	}
> 
> 	if (memcmp(buf, RMID_SIG, MARK_LEN) == 0) {
> 		u_char *eod;
> 		/* Detected a RMID file, let's just check if it's
> 		 * a MIDI file */
> 		if (GET32_LE(buf + MARK_LEN) != (tot - 8)) {
> 			warnx("Not a RMID file, bad header");
> 			return;
> 		}
> 
> 		buf += MARK_LEN + 4;
> 		if (memcmp(buf, RMID_MIDI_ID, MARK_LEN) != 0) {
> 			warnx("Not a RMID file, bad ID");
> 			return;
> 		}
> 
> 		/* Now look for the 'data' chunk, which contains
> 		 * MIDI data */
> 		buf += MARK_LEN;
> 
> 		/* Test against end-8 since we must have at least 8 bytes
> 		 * left to read */
> 		while(buf < (end-8) && memcmp(buf, RMID_DATA_ID, MARK_LEN))
> 			buf += GET32_LE(buf+4) + 8; /* MARK_LEN + 4 */
> 
> 		if (buf >= (end-8)) {
> 			warnx("Not a valid RMID file, no data chunk");
> 			return;
> 		}
> 
> 		buf += MARK_LEN; /* "data" */
> 		eod = buf + 4 + GET32_LE(buf);
> 		if (eod >= end) {
> 			warnx("Not a valid RMID file, bad data chunk size");
> 			return;
> 		}
> 
> 		end = eod;
> 		buf += 4;
> 	}
> 
296a347
> 
>Release-Note:
>Audit-Trail:
>Unformatted: