Commit 7bbd4be5 authored by Rémi Bernon's avatar Rémi Bernon Committed by Alexandre Julliard
parent 15c4c02e
...@@ -18,6 +18,7 @@ C_SRCS = \ ...@@ -18,6 +18,7 @@ C_SRCS = \
sysextrack.c \ sysextrack.c \
tempotrack.c \ tempotrack.c \
timesigtrack.c \ timesigtrack.c \
wave.c \
wavetrack.c wavetrack.c
IDL_SRCS = dmime.idl IDL_SRCS = dmime.idl
......
...@@ -77,6 +77,9 @@ extern HRESULT segment_state_create(IDirectMusicSegment *segment, MUSIC_TIME sta ...@@ -77,6 +77,9 @@ extern HRESULT segment_state_create(IDirectMusicSegment *segment, MUSIC_TIME sta
extern HRESULT segment_state_play(IDirectMusicSegmentState *iface, IDirectMusicPerformance *performance); extern HRESULT segment_state_play(IDirectMusicSegmentState *iface, IDirectMusicPerformance *performance);
extern HRESULT segment_state_end_play(IDirectMusicSegmentState *iface); extern HRESULT segment_state_end_play(IDirectMusicSegmentState *iface);
extern HRESULT wave_track_create_from_chunk(IStream *stream, struct chunk_entry *parent,
IDirectMusicTrack8 **ret_iface);
/***************************************************************************** /*****************************************************************************
* Auxiliary definitions * Auxiliary definitions
*/ */
......
...@@ -741,13 +741,17 @@ static inline void dump_segment_header(DMUS_IO_SEGMENT_HEADER *h, DWORD size) ...@@ -741,13 +741,17 @@ static inline void dump_segment_header(DMUS_IO_SEGMENT_HEADER *h, DWORD size)
} }
} }
static HRESULT parse_segment_form(struct segment *This, IStream *stream, const struct chunk_entry *riff) static HRESULT parse_dmsg_chunk(struct segment *This, IStream *stream, const struct chunk_entry *riff)
{ {
struct chunk_entry chunk = {.parent = riff}; struct chunk_entry chunk = {.parent = riff};
HRESULT hr; HRESULT hr;
TRACE("Parsing segment form in %p: %s\n", stream, debugstr_chunk(riff)); TRACE("Parsing segment form in %p: %s\n", stream, debugstr_chunk(riff));
if (FAILED(hr = dmobj_parsedescriptor(stream, riff, &This->dmobj.desc, DMUS_OBJ_NAME | DMUS_OBJ_CATEGORY))
|| FAILED(hr = stream_reset_chunk_data(stream, riff)))
return hr;
while ((hr = stream_next_chunk(stream, &chunk)) == S_OK) { while ((hr = stream_next_chunk(stream, &chunk)) == S_OK) {
switch (chunk.id) { switch (chunk.id) {
case DMUS_FOURCC_SEGMENT_CHUNK: case DMUS_FOURCC_SEGMENT_CHUNK:
...@@ -786,89 +790,58 @@ static inline struct segment *impl_from_IPersistStream(IPersistStream *iface) ...@@ -786,89 +790,58 @@ static inline struct segment *impl_from_IPersistStream(IPersistStream *iface)
return CONTAINING_RECORD(iface, struct segment, dmobj.IPersistStream_iface); return CONTAINING_RECORD(iface, struct segment, dmobj.IPersistStream_iface);
} }
static HRESULT parse_wave_form(struct segment *This, IStream *stream, const struct chunk_entry *riff) static HRESULT WINAPI segment_persist_stream_Load(IPersistStream *iface, IStream *stream)
{ {
struct segment *This = impl_from_IPersistStream(iface);
struct chunk_entry chunk = {0};
HRESULT hr; HRESULT hr;
struct chunk_entry chunk = {.parent = riff};
TRACE("Parsing segment wave in %p: %s\n", stream, debugstr_chunk(riff)); TRACE("(%p, %p): Loading\n", This, stream);
while ((hr = stream_next_chunk(stream, &chunk)) == S_OK) { if (!stream) return E_POINTER;
switch (chunk.id) {
case mmioFOURCC('f','m','t',' '): {
if (FAILED(hr = stream_chunk_get_data(stream, &chunk, &This->wave_format,
sizeof(This->wave_format))) )
return hr;
TRACE("Wave Format tag %d\n", This->wave_format.wf.wFormatTag);
break;
}
case mmioFOURCC('d','a','t','a'): {
TRACE("Wave Data size %lu\n", chunk.size);
if (This->wave_data)
ERR("Multiple data streams detected\n");
This->wave_data = malloc(chunk.size);
This->data_size = chunk.size;
if (!This->wave_data)
return E_OUTOFMEMORY;
if (FAILED(hr = stream_chunk_get_data(stream, &chunk, This->wave_data, chunk.size)))
return hr;
break;
}
case FOURCC_LIST: {
FIXME("Skipping LIST tag\n");
break;
}
case mmioFOURCC('I','S','F','T'): {
FIXME("Skipping ISFT tag\n");
break;
}
case mmioFOURCC('f','a','c','t'): {
FIXME("Skipping fact tag\n");
break;
}
}
}
return SUCCEEDED(hr) ? S_OK : hr; if ((hr = stream_get_chunk(stream, &chunk)) == S_OK)
} {
switch (MAKE_IDTYPE(chunk.id, chunk.type))
{
case MAKE_IDTYPE(FOURCC_RIFF, DMUS_FOURCC_SEGMENT_FORM):
hr = parse_dmsg_chunk(This, stream, &chunk);
break;
static HRESULT WINAPI segment_persist_stream_Load(IPersistStream *iface, IStream *stream) case mmioFOURCC('M','T','h','d'):
{ FIXME("MIDI file loading not supported\n");
struct segment *This = impl_from_IPersistStream(iface); break;
struct chunk_entry riff = {0};
HRESULT hr;
TRACE("(%p, %p): Loading\n", This, stream); case MAKE_IDTYPE(FOURCC_RIFF, mmioFOURCC('W','A','V','E')):
{
IDirectMusicTrack8 *track;
HRESULT hr;
if (!stream) TRACE("Loading segment %p from wave file\n", This);
return E_POINTER;
if (stream_get_chunk(stream, &riff) != S_OK || This->header.mtLength = 1;
(riff.id != FOURCC_RIFF && riff.id != mmioFOURCC('M','T','h','d'))) if (FAILED(hr = wave_track_create_from_chunk(stream, &chunk, &track))) break;
return DMUS_E_UNSUPPORTED_STREAM; hr = segment_append_track(This, (IDirectMusicTrack *)track, 1, 0);
stream_reset_chunk_start(stream, &riff); break;
}
if (riff.id == mmioFOURCC('M','T','h','d')) { default:
FIXME("MIDI file loading not supported\n"); WARN("Invalid segment chunk %s %s\n", debugstr_fourcc(chunk.id), debugstr_fourcc(chunk.type));
return S_OK; hr = DMUS_E_UNSUPPORTED_STREAM;
break;
}
} }
hr = IDirectMusicObject_ParseDescriptor(&This->dmobj.IDirectMusicObject_iface, stream,
&This->dmobj.desc);
if (FAILED(hr)) if (FAILED(hr))
return hr; {
stream_reset_chunk_data(stream, &riff); WARN("Failed to load segment from stream %p, hr %#lx\n", stream, hr);
return DMUS_E_UNSUPPORTED_STREAM;
if (riff.type == DMUS_FOURCC_SEGMENT_FORM)
hr = parse_segment_form(This, stream, &riff);
else if(riff.type == mmioFOURCC('W','A','V','E'))
hr = parse_wave_form(This, stream, &riff);
else {
FIXME("Unknown type %s\n", debugstr_chunk(&riff));
hr = S_OK;
} }
return hr; This->dmobj.desc.guidClass = CLSID_DirectMusicSegment;
This->dmobj.desc.dwValidData |= DMUS_OBJ_CLASS;
return S_OK;
} }
static const IPersistStreamVtbl segment_persist_stream_vtbl = static const IPersistStreamVtbl segment_persist_stream_vtbl =
......
...@@ -3279,7 +3279,7 @@ static void test_wave_pmsg(void) ...@@ -3279,7 +3279,7 @@ static void test_wave_pmsg(void)
length = 0xdeadbeef; length = 0xdeadbeef;
hr = IDirectMusicSegment_GetLength(segment, &length); hr = IDirectMusicSegment_GetLength(segment, &length);
ok(hr == S_OK, "got %#lx\n", hr); ok(hr == S_OK, "got %#lx\n", hr);
todo_wine ok(length == 1, "got %lu\n", length); ok(length == 1, "got %lu\n", length);
/* without Download, no DMUS_PMSGT_WAVE is sent */ /* without Download, no DMUS_PMSGT_WAVE is sent */
......
...@@ -17,13 +17,14 @@ ...@@ -17,13 +17,14 @@
*/ */
#include "dmime_private.h" #include "dmime_private.h"
#include "dmusic_wave.h"
WINE_DEFAULT_DEBUG_CHANNEL(dmime); WINE_DEFAULT_DEBUG_CHANNEL(dmime);
struct wave_item { struct wave_item {
struct list entry; struct list entry;
DMUS_IO_WAVE_ITEM_HEADER header; DMUS_IO_WAVE_ITEM_HEADER header;
IDirectMusicObject *object; IUnknown *object;
}; };
struct wave_part { struct wave_part {
...@@ -100,8 +101,7 @@ static ULONG WINAPI wave_track_Release(IDirectMusicTrack8 *iface) ...@@ -100,8 +101,7 @@ static ULONG WINAPI wave_track_Release(IDirectMusicTrack8 *iface)
list_remove(&part->entry); list_remove(&part->entry);
LIST_FOR_EACH_ENTRY_SAFE(item, item2, &part->items, struct wave_item, entry) { LIST_FOR_EACH_ENTRY_SAFE(item, item2, &part->items, struct wave_item, entry) {
list_remove(&item->entry); list_remove(&item->entry);
if (item->object) if (item->object) IUnknown_Release(item->object);
IDirectMusicObject_Release(item->object);
free(item); free(item);
} }
free(part); free(part);
...@@ -355,7 +355,7 @@ static HRESULT parse_wave_item(struct wave_part *part, IStream *stream, struct c ...@@ -355,7 +355,7 @@ static HRESULT parse_wave_item(struct wave_part *part, IStream *stream, struct c
hr = DMUS_E_UNSUPPORTED_STREAM; hr = DMUS_E_UNSUPPORTED_STREAM;
goto error; goto error;
} }
if (FAILED(hr = dmobj_parsereference(stream, &chunk, &item->object))) if (FAILED(hr = dmobj_parsereference(stream, &chunk, (IDirectMusicObject **)&item->object)))
goto error; goto error;
list_add_tail(&part->items, &item->entry); list_add_tail(&part->items, &item->entry);
...@@ -484,3 +484,38 @@ HRESULT create_dmwavetrack(REFIID lpcGUID, void **ppobj) ...@@ -484,3 +484,38 @@ HRESULT create_dmwavetrack(REFIID lpcGUID, void **ppobj)
return hr; return hr;
} }
HRESULT wave_track_create_from_chunk(IStream *stream, struct chunk_entry *parent,
IDirectMusicTrack8 **ret_iface)
{
IDirectMusicTrack8 *iface;
struct wave_track *This;
struct wave_item *item;
struct wave_part *part;
HRESULT hr;
if (FAILED(hr = create_dmwavetrack(&IID_IDirectMusicTrack8, (void **)&iface))) return hr;
This = impl_from_IDirectMusicTrack8(iface);
if (!(part = calloc(1, sizeof(*part))))
{
IDirectMusicTrack8_Release(iface);
return E_OUTOFMEMORY;
}
list_init(&part->items);
list_add_tail(&This->parts, &part->entry);
if (!(item = calloc(1, sizeof(*item)))
|| FAILED(hr = wave_create_from_chunk(stream, parent, &item->object)))
{
IDirectMusicTrack8_Release(iface);
free(item);
return hr;
}
if (FAILED(hr = wave_get_duration(item->object, &item->header.rtDuration)))
WARN("Failed to get wave duration, hr %#lx\n", hr);
list_add_tail(&part->items, &item->entry);
*ret_iface = iface;
return S_OK;
}
...@@ -32,3 +32,4 @@ struct chunk_entry; ...@@ -32,3 +32,4 @@ struct chunk_entry;
extern HRESULT wave_create_from_soundfont(struct soundfont *soundfont, UINT index, IUnknown **out); extern HRESULT wave_create_from_soundfont(struct soundfont *soundfont, UINT index, IUnknown **out);
extern HRESULT wave_create_from_chunk(IStream *stream, struct chunk_entry *parent, IUnknown **out); extern HRESULT wave_create_from_chunk(IStream *stream, struct chunk_entry *parent, IUnknown **out);
extern HRESULT wave_download_to_port(IUnknown *iface, IDirectMusicPortDownload *port, DWORD *id); extern HRESULT wave_download_to_port(IUnknown *iface, IDirectMusicPortDownload *port, DWORD *id);
extern HRESULT wave_get_duration(IUnknown *iface, REFERENCE_TIME *duration);
...@@ -338,3 +338,10 @@ HRESULT wave_download_to_port(IUnknown *iface, IDirectMusicPortDownload *port, D ...@@ -338,3 +338,10 @@ HRESULT wave_download_to_port(IUnknown *iface, IDirectMusicPortDownload *port, D
IDirectMusicDownload_Release(download); IDirectMusicDownload_Release(download);
return hr; return hr;
} }
HRESULT wave_get_duration(IUnknown *iface, REFERENCE_TIME *duration)
{
struct wave *This = impl_from_IUnknown(iface);
*duration = (REFERENCE_TIME)This->data_size * 10000000 / This->format->nAvgBytesPerSec;
return S_OK;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment