Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
5ff94358
Commit
5ff94358
authored
Feb 21, 2024
by
Yuxuan Shui
Committed by
Alexandre Julliard
Mar 06, 2024
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
dmime: Parse note on/off events and generate a seqtrack.
parent
1df0e342
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
235 additions
and
17 deletions
+235
-17
dmime_private.h
dlls/dmime/dmime_private.h
+2
-0
midi.c
dlls/dmime/midi.c
+121
-4
seqtrack.c
dlls/dmime/seqtrack.c
+8
-0
dmime.c
dlls/dmime/tests/dmime.c
+104
-13
No files found.
dlls/dmime/dmime_private.h
View file @
5ff94358
...
...
@@ -89,6 +89,8 @@ extern BOOL segment_state_has_track(IDirectMusicSegmentState *iface, DWORD track
extern
HRESULT
wave_track_create_from_chunk
(
IStream
*
stream
,
struct
chunk_entry
*
parent
,
IDirectMusicTrack8
**
ret_iface
);
extern
void
sequence_track_set_items
(
IDirectMusicTrack8
*
track
,
DMUS_IO_SEQ_ITEM
*
items
,
unsigned
int
count
);
extern
HRESULT
performance_get_dsound
(
IDirectMusicPerformance8
*
iface
,
IDirectSound
**
dsound
);
extern
HRESULT
performance_send_segment_start
(
IDirectMusicPerformance8
*
iface
,
MUSIC_TIME
music_time
,
IDirectMusicSegmentState
*
state
);
...
...
dlls/dmime/midi.c
View file @
5ff94358
...
...
@@ -49,8 +49,20 @@ struct midi_event
};
};
struct
midi_seqtrack_item
{
struct
list
entry
;
DMUS_IO_SEQ_ITEM
item
;
};
struct
midi_parser
{
IDirectMusicTrack8
*
seqtrack
;
ULONG
seqtrack_items_count
;
struct
list
seqtrack_items
;
/* Track the initial note on event generated for a note that is currently on. NULL if the note is off. */
struct
midi_seqtrack_item
*
note_states
[
128
*
16
];
IDirectMusicTrack
*
chordtrack
;
IDirectMusicTrack
*
bandtrack
;
IDirectMusicTrack
*
tempotrack
;
...
...
@@ -174,9 +186,9 @@ static HRESULT read_midi_event(IStream *stream, struct midi_event *event, BYTE *
}
status_type
=
event
->
status
&
0xf0
;
event
->
data
[
0
]
=
byte
;
if
(
status_type
==
MIDI_PROGRAM_CHANGE
)
{
event
->
data
[
0
]
=
byte
;
TRACE
(
"MIDI program change event status %#02x, data: %#02x, time +%lu
\n
"
,
event
->
status
,
event
->
data
[
0
],
delta_time
);
}
...
...
@@ -184,7 +196,12 @@ static HRESULT read_midi_event(IStream *stream, struct midi_event *event, BYTE *
{
if
(
status_type
!=
MIDI_CHANNEL_PRESSURE
&&
(
hr
=
stream_read_at_most
(
stream
,
&
byte
,
1
,
bytes_left
))
!=
S_OK
)
return
hr
;
FIXME
(
"MIDI event status %#02x, time +%lu, not supported
\n
"
,
event
->
status
,
delta_time
);
event
->
data
[
1
]
=
byte
;
if
(
status_type
==
MIDI_NOTE_ON
||
status_type
==
MIDI_NOTE_OFF
)
TRACE
(
"MIDI note event status %#02x, data: %#02x, %#02x, time +%lu
\n
"
,
event
->
status
,
event
->
data
[
0
],
event
->
data
[
1
],
delta_time
);
else
FIXME
(
"MIDI event status %#02x, time +%lu, not supported
\n
"
,
event
->
status
,
delta_time
);
}
return
S_OK
;
...
...
@@ -234,11 +251,71 @@ static HRESULT midi_parser_handle_program_change(struct midi_parser *parser, str
return
hr
;
}
static
HRESULT
midi_parser_handle_note_on_off
(
struct
midi_parser
*
parser
,
struct
midi_event
*
event
)
{
BYTE
new_velocity
=
(
event
->
status
&
0xf0
)
==
MIDI_NOTE_OFF
?
0
:
event
->
data
[
1
];
/* DirectMusic doesn't have noteoff velocity */
BYTE
note
=
event
->
data
[
0
],
channel
=
event
->
status
&
0xf
;
DWORD
index
=
(
DWORD
)
channel
*
128
+
note
;
MUSIC_TIME
dmusic_time
;
struct
midi_seqtrack_item
*
note_state
=
parser
->
note_states
[
index
];
DMUS_IO_SEQ_ITEM
*
seq_item
;
struct
midi_seqtrack_item
*
item
;
/* Testing shows there are 2 cases to deal with here:
*
* 1. Got note on when the note is already on, generate a NOTE event with
* new velocity and duration 1.
* 2. Got note on when the note is off, generate a NOTE event that lasts
* until the next note off event, intervening note on event doesn't matter.
*/
if
(
new_velocity
)
{
TRACE
(
"Adding note event at time %lu, note %u, velocity %u
\n
"
,
parser
->
time
,
note
,
new_velocity
);
dmusic_time
=
(
ULONGLONG
)
parser
->
time
*
DMUS_PPQ
/
parser
->
division
;
item
=
calloc
(
1
,
sizeof
(
struct
midi_seqtrack_item
));
if
(
!
item
)
return
E_OUTOFMEMORY
;
seq_item
=
&
item
->
item
;
seq_item
->
mtTime
=
dmusic_time
;
seq_item
->
mtDuration
=
1
;
seq_item
->
dwPChannel
=
channel
;
seq_item
->
bStatus
=
MIDI_NOTE_ON
;
seq_item
->
bByte1
=
note
;
seq_item
->
bByte2
=
new_velocity
;
list_add_tail
(
&
parser
->
seqtrack_items
,
&
item
->
entry
);
parser
->
seqtrack_items_count
++
;
if
(
!
note_state
)
parser
->
note_states
[
index
]
=
item
;
}
else
if
(
note_state
)
{
note_state
->
item
.
mtDuration
=
(
ULONGLONG
)
parser
->
time
*
DMUS_PPQ
/
parser
->
division
-
note_state
->
item
.
mtTime
;
if
(
note_state
->
item
.
mtDuration
==
0
)
note_state
->
item
.
mtDuration
=
1
;
TRACE
(
"Note off at time %lu, note %u, duration %ld
\n
"
,
parser
->
time
,
note
,
note_state
->
item
.
mtDuration
);
parser
->
note_states
[
index
]
=
NULL
;
}
return
S_OK
;
}
static
int
midi_seqtrack_item_compare
(
const
void
*
a
,
const
void
*
b
)
{
const
DMUS_IO_SEQ_ITEM
*
item_a
=
a
,
*
item_b
=
b
;
return
item_a
->
mtTime
-
item_b
->
mtTime
;
}
static
HRESULT
midi_parser_parse
(
struct
midi_parser
*
parser
,
IDirectMusicSegment8
*
segment
)
{
WORD
i
=
0
;
HRESULT
hr
;
MUSIC_TIME
music_length
=
0
;
DMUS_IO_SEQ_ITEM
*
seq_items
=
NULL
;
struct
midi_seqtrack_item
*
item
;
TRACE
(
"(%p, %p): semi-stub
\n
"
,
parser
,
segment
);
...
...
@@ -266,35 +343,70 @@ static HRESULT midi_parser_parse(struct midi_parser *parser, IDirectMusicSegment
parser
->
time
+=
event
.
delta_time
;
if
(
event
.
status
==
0xff
&&
event
.
meta_type
==
MIDI_META_SET_TEMPO
)
hr
=
midi_parser_handle_set_tempo
(
parser
,
&
event
);
else
if
((
event
.
status
&
0xf0
)
==
MIDI_PROGRAM_CHANGE
)
hr
=
midi_parser_handle_program_change
(
parser
,
&
event
);
else
{
switch
(
event
.
status
&
0xf0
)
{
case
MIDI_NOTE_ON
:
case
MIDI_NOTE_OFF
:
hr
=
midi_parser_handle_note_on_off
(
parser
,
&
event
);
break
;
case
MIDI_PROGRAM_CHANGE
:
hr
=
midi_parser_handle_program_change
(
parser
,
&
event
);
break
;
default:
FIXME
(
"Unhandled MIDI event type %#02x at time +%lu
\n
"
,
event
.
status
,
parser
->
time
);
break
;
}
}
if
(
FAILED
(
hr
))
break
;
}
if
(
FAILED
(
hr
))
break
;
TRACE
(
"End of track %u
\n
"
,
i
);
if
(
parser
->
time
>
music_length
)
music_length
=
parser
->
time
;
parser
->
time
=
0
;
memset
(
parser
->
note_states
,
0
,
sizeof
(
parser
->
note_states
));
}
if
(
FAILED
(
hr
))
return
hr
;
TRACE
(
"End of file
\n
"
);
if
((
seq_items
=
calloc
(
parser
->
seqtrack_items_count
,
sizeof
(
DMUS_IO_SEQ_ITEM
)))
==
NULL
)
return
E_OUTOFMEMORY
;
i
=
0
;
LIST_FOR_EACH_ENTRY
(
item
,
&
parser
->
seqtrack_items
,
struct
midi_seqtrack_item
,
entry
)
seq_items
[
i
++
]
=
item
->
item
;
sequence_track_set_items
(
parser
->
seqtrack
,
seq_items
,
parser
->
seqtrack_items_count
);
qsort
(
seq_items
,
parser
->
seqtrack_items_count
,
sizeof
(
DMUS_IO_SEQ_ITEM
),
midi_seqtrack_item_compare
);
music_length
=
(
ULONGLONG
)
music_length
*
DMUS_PPQ
/
parser
->
division
+
1
;
if
(
SUCCEEDED
(
hr
))
hr
=
IDirectMusicSegment8_SetLength
(
segment
,
music_length
);
if
(
SUCCEEDED
(
hr
))
hr
=
IDirectMusicSegment8_InsertTrack
(
segment
,
parser
->
bandtrack
,
0xffff
);
if
(
SUCCEEDED
(
hr
))
hr
=
IDirectMusicSegment8_InsertTrack
(
segment
,
parser
->
chordtrack
,
0xffff
);
if
(
SUCCEEDED
(
hr
)
&&
parser
->
tempotrack
)
hr
=
IDirectMusicSegment8_InsertTrack
(
segment
,
parser
->
tempotrack
,
0xffff
);
if
(
SUCCEEDED
(
hr
))
hr
=
IDirectMusicSegment8_InsertTrack
(
segment
,
(
IDirectMusicTrack
*
)
parser
->
seqtrack
,
0xffff
);
return
hr
;
}
static
void
midi_parser_destroy
(
struct
midi_parser
*
parser
)
{
struct
midi_seqtrack_item
*
item
,
*
next_item
;
IStream_Release
(
parser
->
stream
);
if
(
parser
->
bandtrack
)
IDirectMusicTrack_Release
(
parser
->
bandtrack
);
if
(
parser
->
chordtrack
)
IDirectMusicTrack_Release
(
parser
->
chordtrack
);
if
(
parser
->
tempotrack
)
IDirectMusicTrack_Release
(
parser
->
tempotrack
);
if
(
parser
->
seqtrack
)
IDirectMusicTrack_Release
(
parser
->
seqtrack
);
LIST_FOR_EACH_ENTRY_SAFE
(
item
,
next_item
,
&
parser
->
seqtrack_items
,
struct
midi_seqtrack_item
,
entry
)
{
list_remove
(
&
item
->
entry
);
free
(
item
);
}
free
(
parser
);
}
...
...
@@ -334,6 +446,7 @@ static HRESULT midi_parser_new(IStream *stream, struct midi_parser **out_parser)
parser
=
calloc
(
1
,
sizeof
(
struct
midi_parser
));
if
(
!
parser
)
return
E_OUTOFMEMORY
;
list_init
(
&
parser
->
seqtrack_items
);
IStream_AddRef
(
stream
);
parser
->
stream
=
stream
;
parser
->
division
=
division
;
...
...
@@ -342,6 +455,10 @@ static HRESULT midi_parser_new(IStream *stream, struct midi_parser **out_parser)
if
(
SUCCEEDED
(
hr
))
hr
=
CoCreateInstance
(
&
CLSID_DirectMusicChordTrack
,
NULL
,
CLSCTX_INPROC_SERVER
,
&
IID_IDirectMusicTrack
,
(
void
**
)
&
parser
->
chordtrack
);
if
(
SUCCEEDED
(
hr
))
hr
=
CoCreateInstance
(
&
CLSID_DirectMusicSeqTrack
,
NULL
,
CLSCTX_INPROC_SERVER
,
&
IID_IDirectMusicTrack
,
(
void
**
)
&
parser
->
seqtrack
);
if
(
FAILED
(
hr
))
midi_parser_destroy
(
parser
);
else
*
out_parser
=
parser
;
return
hr
;
...
...
dlls/dmime/seqtrack.c
View file @
5ff94358
...
...
@@ -483,3 +483,11 @@ HRESULT create_dmseqtrack(REFIID lpcGUID, void **ppobj)
return
hr
;
}
void
sequence_track_set_items
(
IDirectMusicTrack8
*
track
,
DMUS_IO_SEQ_ITEM
*
items
,
unsigned
int
count
)
{
struct
sequence_track
*
This
=
impl_from_IDirectMusicTrack8
(
track
);
free
(
This
->
items
);
This
->
items
=
items
;
This
->
count
=
count
;
}
dlls/dmime/tests/dmime.c
View file @
5ff94358
...
...
@@ -1633,6 +1633,27 @@ static void test_midi(void)
0xc1
,
/* event type, program change, channel 1 */
0x30
,
/* event data, patch 48 */
};
static
const
char
midi_note_on
[]
=
{
0x04
,
/* delta time = 4 */
0x91
,
/* event type, note on, channel 1 */
0x3c
,
/* event data, middle C */
0x40
,
/* event data, velocity 64 */
};
static
const
char
midi_note_off
[]
=
{
0x04
,
/* delta time = 4 */
0x81
,
/* event type, note off, channel 1 */
0x3c
,
/* event data, middle C */
0x0
,
};
static
const
char
midi_note_off2
[]
=
{
0x60
,
/* delta time = 96 */
0x81
,
/* event type, note off, channel 1 */
0x3c
,
/* event data, middle C */
0x0
,
};
IDirectMusicSegment8
*
segment
=
NULL
;
IDirectMusicTrack
*
track
=
NULL
;
IDirectMusicLoader8
*
loader
;
...
...
@@ -1646,8 +1667,10 @@ static void test_midi(void)
WCHAR
test_mid
[
MAX_PATH
],
bogus_mid
[
MAX_PATH
];
HRESULT
hr
;
ULONG
ret
;
DWORD
track_length
;
MUSIC_TIME
next
;
DMUS_PMSG
*
msg
;
DMUS_NOTE_PMSG
*
note
;
DMUS_PATCH_PMSG
*
patch
;
DMUS_TEMPO_PARAM
tempo_param
;
#include <pshpack1.h>
...
...
@@ -1685,8 +1708,8 @@ static void test_midi(void)
expect_track
(
segment
,
BandTrack
,
-
1
,
0
);
expect_track
(
segment
,
ChordTrack
,
-
1
,
1
);
expect_track
(
segment
,
TempoTrack
,
-
1
,
2
);
todo_wine
expect_
track
(
segment
,
TimeSigTrack
,
-
1
,
3
);
todo_wine
expect_track
(
segment
,
SeqTrack
,
-
1
,
4
);
todo_wine
expect_
guid_track
(
segment
,
TimeSigTrack
,
-
1
,
0
);
expect_guid_track
(
segment
,
SeqTrack
,
-
1
,
0
);
/* no more tracks */
hr
=
IDirectMusicSegment8_GetTrack
(
segment
,
&
GUID_NULL
,
-
1
,
5
,
&
track
);
ok
(
hr
==
DMUS_E_NOT_FOUND
,
"unexpected extra track
\n
"
);
...
...
@@ -1726,7 +1749,7 @@ static void test_midi(void)
/* TempoTrack and TimeSigTrack seems to be optional. */
expect_track
(
segment
,
BandTrack
,
-
1
,
0
);
expect_track
(
segment
,
ChordTrack
,
-
1
,
1
);
todo_wine
expect_track
(
segment
,
SeqTrack
,
-
1
,
2
);
expect_track
(
segment
,
SeqTrack
,
-
1
,
2
);
IDirectMusicSegment_Release
(
segment
);
/* parse MIDI file with 1 track that has 1 event. */
...
...
@@ -1763,7 +1786,7 @@ static void test_midi(void)
expect_track
(
segment
,
BandTrack
,
-
1
,
0
);
expect_track
(
segment
,
ChordTrack
,
-
1
,
1
);
expect_track
(
segment
,
TempoTrack
,
-
1
,
2
);
todo_wine
expect_track
(
segment
,
SeqTrack
,
-
1
,
3
);
expect_track
(
segment
,
SeqTrack
,
-
1
,
3
);
hr
=
IDirectMusicSegment_GetParam
(
segment
,
&
GUID_TempoParam
,
-
1
,
DMUS_SEG_ALLTRACKS
,
0
,
&
next
,
&
tempo_param
);
ok
(
hr
==
S_OK
,
"got %#lx
\n
"
,
hr
);
...
...
@@ -1811,7 +1834,7 @@ static void test_midi(void)
expect_track
(
segment
,
BandTrack
,
-
1
,
0
);
expect_track
(
segment
,
ChordTrack
,
-
1
,
1
);
/* there is no tempo track. */
todo_wine
expect_track
(
segment
,
SeqTrack
,
-
1
,
2
);
expect_track
(
segment
,
SeqTrack
,
-
1
,
2
);
IDirectMusicSegment_Release
(
segment
);
/* parse MIDI file with program change event. */
...
...
@@ -1830,24 +1853,47 @@ static void test_midi(void)
header
.
length
=
GET_BE_DWORD
(
sizeof
(
header
)
-
8
);
hr
=
IStream_Write
(
stream
,
&
header
,
sizeof
(
header
),
NULL
);
ok
(
hr
==
S_OK
,
"got %#lx
\n
"
,
hr
);
track_header
.
length
=
RtlUlongByteSwap
(
sizeof
(
track_header
)
-
8
+
sizeof
(
midi_program_change
));
track_length
=
sizeof
(
midi_program_change
)
+
sizeof
(
midi_note_on
)
*
3
+
sizeof
(
midi_note_off
);
track_header
.
length
=
RtlUlongByteSwap
(
sizeof
(
track_header
)
-
8
+
track_length
);
hr
=
IStream_Write
(
stream
,
&
track_header
,
sizeof
(
track_header
),
NULL
);
ok
(
hr
==
S_OK
,
"got %#lx
\n
"
,
hr
);
hr
=
IStream_Write
(
stream
,
midi_program_change
,
sizeof
(
midi_program_change
),
NULL
);
ok
(
hr
==
S_OK
,
"got %#lx
\n
"
,
hr
);
/* Add note on/off events, like this:
* on, on, off, on
* So we can test what happens when we have two consecutive note on, and what happens with trailing note on. */
hr
=
IStream_Write
(
stream
,
midi_note_on
,
sizeof
(
midi_note_on
),
NULL
);
ok
(
hr
==
S_OK
,
"got %#lx
\n
"
,
hr
);
hr
=
IStream_Write
(
stream
,
midi_note_on
,
sizeof
(
midi_note_on
),
NULL
);
ok
(
hr
==
S_OK
,
"got %#lx
\n
"
,
hr
);
hr
=
IStream_Write
(
stream
,
midi_note_off
,
sizeof
(
midi_note_off
),
NULL
);
ok
(
hr
==
S_OK
,
"got %#lx
\n
"
,
hr
);
hr
=
IStream_Write
(
stream
,
midi_note_on
,
sizeof
(
midi_note_on
),
NULL
);
ok
(
hr
==
S_OK
,
"got %#lx
\n
"
,
hr
);
/* Add a second track, to test the duration of the trailing note. */
track_header
.
length
=
RtlUlongByteSwap
(
sizeof
(
track_header
)
-
8
+
sizeof
(
midi_note_on
)
+
sizeof
(
midi_note_off
));
hr
=
IStream_Write
(
stream
,
&
track_header
,
sizeof
(
track_header
),
NULL
);
ok
(
hr
==
S_OK
,
"got %#lx
\n
"
,
hr
);
hr
=
IStream_Write
(
stream
,
midi_note_on
,
sizeof
(
midi_note_on
),
NULL
);
ok
(
hr
==
S_OK
,
"got %#lx
\n
"
,
hr
);
hr
=
IStream_Write
(
stream
,
midi_note_off2
,
sizeof
(
midi_note_off2
),
NULL
);
ok
(
hr
==
S_OK
,
"got %#lx
\n
"
,
hr
);
hr
=
IStream_Seek
(
stream
,
zero
,
0
,
NULL
);
ok
(
hr
==
S_OK
,
"got %#lx
\n
"
,
hr
);
hr
=
IPersistStream_Load
(
persist
,
stream
);
ok
(
hr
==
S_OK
,
"got %#lx
\n
"
,
hr
);
hr
=
IStream_Seek
(
stream
,
zero
,
STREAM_SEEK_CUR
,
&
position
);
ok
(
hr
==
S_OK
,
"got %#lx
\n
"
,
hr
);
ok
(
position
.
QuadPart
==
sizeof
(
header
)
+
sizeof
(
track_header
)
+
sizeof
(
midi_program_change
),
ok
(
position
.
QuadPart
==
sizeof
(
header
)
+
sizeof
(
track_header
)
*
2
+
track_length
+
sizeof
(
midi_note_on
)
+
sizeof
(
midi_note_off
),
"got %lld
\n
"
,
position
.
QuadPart
);
IPersistStream_Release
(
persist
);
IStream_Release
(
stream
);
expect_track
(
segment
,
BandTrack
,
-
1
,
0
);
expect_track
(
segment
,
ChordTrack
,
-
1
,
1
);
todo_wine
expect_track
(
segment
,
SeqTrack
,
-
1
,
2
);
expect_track
(
segment
,
SeqTrack
,
-
1
,
2
);
hr
=
test_tool_create
(
message_types
,
ARRAY_SIZE
(
message_types
),
&
tool
);
ok
(
hr
==
S_OK
,
"got %#lx
\n
"
,
hr
);
...
...
@@ -1865,11 +1911,7 @@ static void test_midi(void)
ok
(
hr
==
S_OK
,
"got %#lx
\n
"
,
hr
);
IDirectMusicGraph_Release
(
graph
);
/* now play the segment, and check produced messages
* wine generates: DIRTY, PATCH, DIRTY.
* native generates: DIRTY, PATCH
*/
/* now play the segment, and check produced messages */
hr
=
IDirectMusicPerformance_Init
(
performance
,
NULL
,
0
,
0
);
ok
(
hr
==
S_OK
,
"got %#lx
\n
"
,
hr
);
hr
=
IDirectMusicPerformance_PlaySegment
(
performance
,
(
IDirectMusicSegment
*
)
segment
,
0x800
,
0
,
NULL
);
...
...
@@ -1892,6 +1934,55 @@ static void test_midi(void)
ok
(
hr
==
S_OK
,
"got %#lx
\n
"
,
hr
);
ret
=
test_tool_wait_message
(
tool
,
500
,
(
DMUS_PMSG
**
)
&
msg
);
ok
(
!
ret
,
"got %#lx
\n
"
,
ret
);
ok
(
msg
->
dwType
==
DMUS_PMSGT_NOTE
,
"got msg type %#lx, expected NOTE
\n
"
,
msg
->
dwType
);
ok
(
msg
->
mtTime
==
24
,
"got mtTime %lu, expected 24
\n
"
,
msg
->
mtTime
);
note
=
(
DMUS_NOTE_PMSG
*
)
msg
;
ok
(
note
->
bMidiValue
==
0x3c
,
"got note %#x, expected 0x3c
\n
"
,
note
->
bMidiValue
);
ok
(
note
->
bVelocity
==
0x40
,
"got velocity %#x, expected 0x40
\n
"
,
note
->
bVelocity
);
ok
(
note
->
mtDuration
==
600
,
"got mtDuration %lu, expected 600
\n
"
,
note
->
mtDuration
);
ok
(
note
->
dwPChannel
==
1
,
"got pchannel %lu, expected 1
\n
"
,
note
->
dwPChannel
);
hr
=
IDirectMusicPerformance_FreePMsg
(
performance
,
msg
);
ok
(
hr
==
S_OK
,
"got %#lx
\n
"
,
hr
);
ret
=
test_tool_wait_message
(
tool
,
500
,
(
DMUS_PMSG
**
)
&
msg
);
ok
(
!
ret
,
"got %#lx
\n
"
,
ret
);
ok
(
msg
->
dwType
==
DMUS_PMSGT_NOTE
,
"got msg type %#lx, expected NOTE
\n
"
,
msg
->
dwType
);
ok
(
msg
->
mtTime
==
49
,
"got mtTime %lu, expected 49
\n
"
,
msg
->
mtTime
);
note
=
(
DMUS_NOTE_PMSG
*
)
msg
;
ok
(
note
->
bMidiValue
==
0x3c
,
"got note %#x, expected 0x3c
\n
"
,
note
->
bMidiValue
);
ok
(
note
->
bVelocity
==
0x40
,
"got velocity %#x, expected 0x40
\n
"
,
note
->
bVelocity
);
ok
(
note
->
mtDuration
==
50
,
"got mtDuration %lu, expected 50
\n
"
,
note
->
mtDuration
);
ok
(
note
->
dwPChannel
==
1
,
"got pchannel %lu, expected 1
\n
"
,
note
->
dwPChannel
);
hr
=
IDirectMusicPerformance_FreePMsg
(
performance
,
msg
);
ok
(
hr
==
S_OK
,
"got %#lx
\n
"
,
hr
);
ret
=
test_tool_wait_message
(
tool
,
500
,
(
DMUS_PMSG
**
)
&
msg
);
ok
(
!
ret
,
"got %#lx
\n
"
,
ret
);
ok
(
msg
->
dwType
==
DMUS_PMSGT_NOTE
,
"got msg type %#lx, expected NOTE
\n
"
,
msg
->
dwType
);
ok
(
msg
->
mtTime
==
74
,
"got mtTime %lu, expected 74
\n
"
,
msg
->
mtTime
);
note
=
(
DMUS_NOTE_PMSG
*
)
msg
;
ok
(
note
->
bMidiValue
==
0x3c
,
"got note %#x, expected 0x3c
\n
"
,
note
->
bMidiValue
);
ok
(
note
->
bVelocity
==
0x40
,
"got velocity %#x, expected 0x40
\n
"
,
note
->
bVelocity
);
ok
(
note
->
mtDuration
==
1
,
"got mtDuration %lu, expected 1
\n
"
,
note
->
mtDuration
);
ok
(
note
->
dwPChannel
==
1
,
"got pchannel %lu, expected 1
\n
"
,
note
->
dwPChannel
);
hr
=
IDirectMusicPerformance_FreePMsg
(
performance
,
msg
);
ok
(
hr
==
S_OK
,
"got %#lx
\n
"
,
hr
);
ret
=
test_tool_wait_message
(
tool
,
500
,
(
DMUS_PMSG
**
)
&
msg
);
ok
(
!
ret
,
"got %#lx
\n
"
,
ret
);
ok
(
msg
->
dwType
==
DMUS_PMSGT_NOTE
,
"got msg type %#lx, expected NOTE
\n
"
,
msg
->
dwType
);
ok
(
msg
->
mtTime
==
124
,
"got mtTime %lu, expected 124
\n
"
,
msg
->
mtTime
);
note
=
(
DMUS_NOTE_PMSG
*
)
msg
;
ok
(
note
->
bMidiValue
==
0x3c
,
"got note %#x, expected 0x3c
\n
"
,
note
->
bMidiValue
);
ok
(
note
->
bVelocity
==
0x40
,
"got velocity %#x, expected 0x40
\n
"
,
note
->
bVelocity
);
ok
(
note
->
mtDuration
==
1
,
"got mtDuration %ld, expected 1
\n
"
,
note
->
mtDuration
);
ok
(
note
->
dwPChannel
==
1
,
"got pchannel %lu, expected 1
\n
"
,
note
->
dwPChannel
);
hr
=
IDirectMusicPerformance_FreePMsg
(
performance
,
msg
);
ok
(
hr
==
S_OK
,
"got %#lx
\n
"
,
hr
);
/* wine generates an extra DIRTY event. */
ret
=
test_tool_wait_message
(
tool
,
500
,
(
DMUS_PMSG
**
)
&
msg
);
todo_wine
ok
(
ret
==
WAIT_TIMEOUT
,
"unexpected message
\n
"
);
if
(
!
ret
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment