@@ -77,6 +77,81 @@ static void load_resource(const WCHAR *name, WCHAR *filename)
77
77
CloseHandle (file );
78
78
}
79
79
80
+ static void stream_begin_chunk (IStream * stream , const char type [5 ], ULARGE_INTEGER * offset )
81
+ {
82
+ static const LARGE_INTEGER zero = {0 };
83
+ HRESULT hr ;
84
+ hr = IStream_Write (stream , type , 4 , NULL );
85
+ ok (hr == S_OK , "got %#lx\n" , hr );
86
+ hr = IStream_Seek (stream , zero , STREAM_SEEK_CUR , offset );
87
+ ok (hr == S_OK , "got %#lx\n" , hr );
88
+ hr = IStream_Write (stream , "\0\0\0\0" , 4 , NULL );
89
+ ok (hr == S_OK , "got %#lx\n" , hr );
90
+ }
91
+
92
+ static void stream_end_chunk (IStream * stream , ULARGE_INTEGER * offset )
93
+ {
94
+ static const LARGE_INTEGER zero = {0 };
95
+ ULARGE_INTEGER position ;
96
+ HRESULT hr ;
97
+ UINT size ;
98
+ hr = IStream_Seek (stream , zero , STREAM_SEEK_CUR , & position );
99
+ ok (hr == S_OK , "got %#lx\n" , hr );
100
+ hr = IStream_Seek (stream , * (LARGE_INTEGER * )offset , STREAM_SEEK_SET , NULL );
101
+ ok (hr == S_OK , "got %#lx\n" , hr );
102
+ size = position .QuadPart - offset -> QuadPart - 4 ;
103
+ hr = IStream_Write (stream , & size , 4 , NULL );
104
+ ok (hr == S_OK , "got %#lx\n" , hr );
105
+ hr = IStream_Seek (stream , * (LARGE_INTEGER * )& position , STREAM_SEEK_SET , NULL );
106
+ ok (hr == S_OK , "got %#lx\n" , hr );
107
+ hr = IStream_Write (stream , & zero , (position .QuadPart & 1 ), NULL );
108
+ ok (hr == S_OK , "got %#lx\n" , hr );
109
+ }
110
+
111
+ #define CHUNK_BEGIN (stream , type ) \
112
+ do { \
113
+ ULARGE_INTEGER __off; \
114
+ IStream *__stream = (stream); \
115
+ stream_begin_chunk(stream, type, &__off); \
116
+ do
117
+
118
+ #define CHUNK_RIFF (stream , form ) \
119
+ do { \
120
+ ULARGE_INTEGER __off; \
121
+ IStream *__stream = (stream); \
122
+ stream_begin_chunk(stream, "RIFF", &__off); \
123
+ IStream_Write(stream, form, 4, NULL); \
124
+ do
125
+
126
+ #define CHUNK_LIST (stream , form ) \
127
+ do { \
128
+ ULARGE_INTEGER __off; \
129
+ IStream *__stream = (stream); \
130
+ stream_begin_chunk(stream, "LIST", &__off); \
131
+ IStream_Write(stream, form, 4, NULL); \
132
+ do
133
+
134
+ #define CHUNK_END \
135
+ while (0); \
136
+ stream_end_chunk(__stream, &__off); \
137
+ } while (0)
138
+
139
+ #define CHUNK_DATA (stream , type , data ) \
140
+ CHUNK_BEGIN(stream, type) \
141
+ { \
142
+ IStream_Write((stream), &(data), sizeof(data), NULL); \
143
+ } \
144
+ CHUNK_END
145
+
146
+ #define CHUNK_ARRAY (stream , type , items ) \
147
+ CHUNK_BEGIN(stream, type) \
148
+ { \
149
+ UINT __size = sizeof(*(items)); \
150
+ IStream_Write((stream), &__size, 4, NULL); \
151
+ IStream_Write((stream), &(items), sizeof(items), NULL); \
152
+ } \
153
+ CHUNK_END
154
+
80
155
struct test_tool
81
156
{
82
157
IDirectMusicTool IDirectMusicTool_iface ;
@@ -2411,6 +2486,191 @@ static void test_wave_pmsg(void)
2411
2486
IDirectMusicTool_Release (tool );
2412
2487
}
2413
2488
2489
+ #define check_dmus_note_pmsg (a , b , c , d , e , f ) check_dmus_note_pmsg_(__LINE__, a, b, c, d, e, f)
2490
+ static void check_dmus_note_pmsg_ (int line , DMUS_NOTE_PMSG * msg , MUSIC_TIME time , UINT chan ,
2491
+ UINT duration , UINT key , UINT vel )
2492
+ {
2493
+ ok_ (__FILE__ , line )(msg -> dwSize == sizeof (* msg ), "got dwSize %lu\n" , msg -> dwSize );
2494
+ ok_ (__FILE__ , line )(!!msg -> rtTime , "got rtTime %I64u\n" , msg -> rtTime );
2495
+ ok_ (__FILE__ , line )(abs (msg -> mtTime - time ) < 10 , "got mtTime %lu\n" , msg -> mtTime );
2496
+ ok_ (__FILE__ , line )(msg -> dwPChannel == chan , "got dwPChannel %lu\n" , msg -> dwPChannel );
2497
+ ok_ (__FILE__ , line )(!!msg -> dwVirtualTrackID , "got dwVirtualTrackID %lu\n" , msg -> dwVirtualTrackID );
2498
+ ok_ (__FILE__ , line )(msg -> dwType == DMUS_PMSGT_NOTE , "got %#lx\n" , msg -> dwType );
2499
+ ok_ (__FILE__ , line )(!msg -> dwVoiceID , "got dwVoiceID %lu\n" , msg -> dwVoiceID );
2500
+ ok_ (__FILE__ , line )(msg -> dwGroupID == 1 , "got dwGroupID %lu\n" , msg -> dwGroupID );
2501
+ ok_ (__FILE__ , line )(!msg -> punkUser , "got punkUser %p\n" , msg -> punkUser );
2502
+ ok_ (__FILE__ , line )(msg -> mtDuration == duration , "got mtDuration %lu\n" , msg -> mtDuration );
2503
+ ok_ (__FILE__ , line )(msg -> wMusicValue == key , "got wMusicValue %u\n" , msg -> wMusicValue );
2504
+ ok_ (__FILE__ , line )(!msg -> wMeasure , "got wMeasure %u\n" , msg -> wMeasure );
2505
+ /* FIXME: ok_(__FILE__, line)(!msg->nOffset, "got nOffset %u\n", msg->nOffset); */
2506
+ /* FIXME: ok_(__FILE__, line)(!msg->bBeat, "got bBeat %u\n", msg->bBeat); */
2507
+ /* FIXME: ok_(__FILE__, line)(!msg->bGrid, "got bGrid %u\n", msg->bGrid); */
2508
+ ok_ (__FILE__ , line )(msg -> bVelocity == vel , "got bVelocity %u\n" , msg -> bVelocity );
2509
+ ok_ (__FILE__ , line )(msg -> bFlags == 1 , "got bFlags %#x\n" , msg -> bFlags );
2510
+ ok_ (__FILE__ , line )(!msg -> bTimeRange , "got bTimeRange %u\n" , msg -> bTimeRange );
2511
+ ok_ (__FILE__ , line )(!msg -> bDurRange , "got bDurRange %u\n" , msg -> bDurRange );
2512
+ ok_ (__FILE__ , line )(!msg -> bVelRange , "got bVelRange %u\n" , msg -> bVelRange );
2513
+ ok_ (__FILE__ , line )(!msg -> bPlayModeFlags , "got bPlayModeFlags %#x\n" , msg -> bPlayModeFlags );
2514
+ ok_ (__FILE__ , line )(!msg -> bSubChordLevel , "got bSubChordLevel %u\n" , msg -> bSubChordLevel );
2515
+ ok_ (__FILE__ , line )(msg -> bMidiValue == key , "got bMidiValue %u\n" , msg -> bMidiValue );
2516
+ ok_ (__FILE__ , line )(!msg -> cTranspose , "got cTranspose %u\n" , msg -> cTranspose );
2517
+ }
2518
+
2519
+ static void test_sequence_track (void )
2520
+ {
2521
+ static const DWORD message_types [] =
2522
+ {
2523
+ DMUS_PMSGT_MIDI ,
2524
+ DMUS_PMSGT_NOTE ,
2525
+ DMUS_PMSGT_CURVE ,
2526
+ DMUS_PMSGT_DIRTY ,
2527
+ };
2528
+ static const LARGE_INTEGER zero = {0 };
2529
+ IDirectMusicPerformance * performance ;
2530
+ IDirectMusicSegment * segment ;
2531
+ IDirectMusicGraph * graph ;
2532
+ IDirectMusicTrack * track ;
2533
+ IPersistStream * persist ;
2534
+ IDirectMusicTool * tool ;
2535
+ DMUS_NOTE_PMSG * note ;
2536
+ IStream * stream ;
2537
+ DMUS_PMSG * msg ;
2538
+ HRESULT hr ;
2539
+ DWORD ret ;
2540
+
2541
+ hr = test_tool_create (message_types , ARRAY_SIZE (message_types ), & tool );
2542
+ ok (hr == S_OK , "got %#lx\n" , hr );
2543
+
2544
+ hr = CoCreateInstance (& CLSID_DirectMusicPerformance , NULL , CLSCTX_INPROC_SERVER ,
2545
+ & IID_IDirectMusicPerformance , (void * * )& performance );
2546
+ ok (hr == S_OK , "got %#lx\n" , hr );
2547
+
2548
+ hr = CoCreateInstance (& CLSID_DirectMusicGraph , NULL , CLSCTX_INPROC_SERVER ,
2549
+ & IID_IDirectMusicGraph , (void * * )& graph );
2550
+ ok (hr == S_OK , "got %#lx\n" , hr );
2551
+ hr = IDirectMusicGraph_InsertTool (graph , (IDirectMusicTool * )tool , NULL , 0 , -1 );
2552
+ ok (hr == S_OK , "got %#lx\n" , hr );
2553
+ hr = IDirectMusicPerformance_SetGraph (performance , graph );
2554
+ ok (hr == S_OK , "got %#lx\n" , hr );
2555
+ IDirectMusicGraph_Release (graph );
2556
+
2557
+
2558
+ /* create a segment and load a simple RIFF stream */
2559
+
2560
+ hr = CoCreateInstance (& CLSID_DirectMusicSegment , NULL , CLSCTX_INPROC_SERVER ,
2561
+ & IID_IDirectMusicSegment , (void * * )& segment );
2562
+ ok (hr == S_OK , "got %#lx\n" , hr );
2563
+
2564
+ hr = IDirectMusicSegment_QueryInterface (segment , & IID_IPersistStream , (void * * )& persist );
2565
+ ok (hr == S_OK , "got %#lx\n" , hr );
2566
+ hr = CreateStreamOnHGlobal (0 , TRUE, & stream );
2567
+ ok (hr == S_OK , "got %#lx\n" , hr );
2568
+
2569
+ CHUNK_RIFF (stream , "DMSG" )
2570
+ {
2571
+ /* set a non-zero segment length, or nothing will be played */
2572
+ DMUS_IO_SEGMENT_HEADER head = {.mtLength = 2000 };
2573
+ CHUNK_DATA (stream , "segh" , head );
2574
+ CHUNK_DATA (stream , "guid" , CLSID_DirectMusicSegment );
2575
+ }
2576
+ CHUNK_END ;
2577
+
2578
+ hr = IStream_Seek (stream , zero , 0 , NULL );
2579
+ ok (hr == S_OK , "got %#lx\n" , hr );
2580
+ hr = IPersistStream_Load (persist , stream );
2581
+ ok (hr == S_OK , "got %#lx\n" , hr );
2582
+ IPersistStream_Release (persist );
2583
+ IStream_Release (stream );
2584
+
2585
+
2586
+ /* add a sequence track to our segment */
2587
+
2588
+ hr = CoCreateInstance (& CLSID_DirectMusicSeqTrack , NULL , CLSCTX_INPROC_SERVER ,
2589
+ & IID_IDirectMusicTrack , (void * * )& track );
2590
+ ok (hr == S_OK , "got %#lx\n" , hr );
2591
+
2592
+ hr = IDirectMusicSegment_QueryInterface (track , & IID_IPersistStream , (void * * )& persist );
2593
+ ok (hr == S_OK , "got %#lx\n" , hr );
2594
+ hr = CreateStreamOnHGlobal (0 , TRUE, & stream );
2595
+ ok (hr == S_OK , "got %#lx\n" , hr );
2596
+
2597
+ CHUNK_BEGIN (stream , "seqt" )
2598
+ {
2599
+ DMUS_IO_SEQ_ITEM items [] =
2600
+ {
2601
+ {.mtTime = 0 , .mtDuration = 500 , .dwPChannel = 0 , .bStatus = 0x90 , .bByte1 = 60 , .bByte2 = 120 },
2602
+ {.mtTime = 1000 , .mtDuration = 200 , .dwPChannel = 1 , .bStatus = 0x90 , .bByte1 = 50 , .bByte2 = 100 },
2603
+ };
2604
+ CHUNK_ARRAY (stream , "evtl" , items );
2605
+ }
2606
+ CHUNK_END ;
2607
+
2608
+ hr = IStream_Seek (stream , zero , 0 , NULL );
2609
+ ok (hr == S_OK , "got %#lx\n" , hr );
2610
+ hr = IPersistStream_Load (persist , stream );
2611
+ ok (hr == S_OK , "got %#lx\n" , hr );
2612
+ IPersistStream_Release (persist );
2613
+ IStream_Release (stream );
2614
+
2615
+ hr = IDirectMusicSegment_InsertTrack (segment , (IDirectMusicTrack * )track , 1 );
2616
+ ok (hr == S_OK , "got %#lx\n" , hr );
2617
+ IDirectMusicTrack_Release (track );
2618
+
2619
+
2620
+ /* now play the segment, and check produced messages */
2621
+
2622
+ hr = IDirectMusicPerformance_Init (performance , NULL , 0 , 0 );
2623
+ ok (hr == S_OK , "got %#lx\n" , hr );
2624
+
2625
+ hr = IDirectMusicPerformance_PlaySegment (performance , segment , 0x800 , 0 , NULL );
2626
+ ok (hr == S_OK , "got %#lx\n" , hr );
2627
+
2628
+ ret = test_tool_wait_message (tool , 500 , & msg );
2629
+ todo_wine ok (!ret , "got %#lx\n" , ret );
2630
+ if (!ret )
2631
+ {
2632
+ ok (msg -> dwType == DMUS_PMSGT_DIRTY , "got %#lx\n" , msg -> dwType );
2633
+ hr = IDirectMusicPerformance_FreePMsg (performance , msg );
2634
+ ok (hr == S_OK , "got %#lx\n" , hr );
2635
+ }
2636
+
2637
+ ret = test_tool_wait_message (tool , 500 , (DMUS_PMSG * * )& note );
2638
+ todo_wine ok (!ret , "got %#lx\n" , ret );
2639
+ if (!ret )
2640
+ {
2641
+ check_dmus_note_pmsg (note , 0 , 0 , 500 , 60 , 120 );
2642
+ hr = IDirectMusicPerformance_FreePMsg (performance , (DMUS_PMSG * )note );
2643
+ ok (hr == S_OK , "got %#lx\n" , hr );
2644
+ }
2645
+
2646
+ ret = test_tool_wait_message (tool , 500 , (DMUS_PMSG * * )& note );
2647
+ todo_wine ok (!ret , "got %#lx\n" , ret );
2648
+ if (!ret )
2649
+ {
2650
+ check_dmus_note_pmsg (note , 1000 , 1 , 200 , 50 , 100 );
2651
+ hr = IDirectMusicPerformance_FreePMsg (performance , (DMUS_PMSG * )note );
2652
+ ok (hr == S_OK , "got %#lx\n" , hr );
2653
+ }
2654
+
2655
+ ret = test_tool_wait_message (tool , 500 , & msg );
2656
+ todo_wine ok (!ret , "got %#lx\n" , ret );
2657
+ if (!ret )
2658
+ {
2659
+ ok (msg -> dwType == DMUS_PMSGT_DIRTY , "got %#lx\n" , msg -> dwType );
2660
+ hr = IDirectMusicPerformance_FreePMsg (performance , msg );
2661
+ ok (hr == S_OK , "got %#lx\n" , hr );
2662
+ }
2663
+
2664
+ IDirectMusicSegment_Release (segment );
2665
+
2666
+
2667
+ hr = IDirectMusicPerformance_CloseDown (performance );
2668
+ ok (hr == S_OK , "got %#lx\n" , hr );
2669
+
2670
+ IDirectMusicPerformance_Release (performance );
2671
+ IDirectMusicTool_Release (tool );
2672
+ }
2673
+
2414
2674
START_TEST (dmime )
2415
2675
{
2416
2676
CoInitialize (NULL );
@@ -2440,6 +2700,7 @@ START_TEST(dmime)
2440
2700
test_performance_pmsg ();
2441
2701
test_notification_pmsg ();
2442
2702
test_wave_pmsg ();
2703
+ test_sequence_track ();
2443
2704
2444
2705
CoUninitialize ();
2445
2706
}
0 commit comments