Commit 7bbd4be5 authored by Rémi Bernon's avatar Rémi Bernon Committed by Alexandre Julliard
parent 15c4c02e
......@@ -18,6 +18,7 @@ C_SRCS = \
sysextrack.c \
tempotrack.c \
timesigtrack.c \
wave.c \
wavetrack.c
IDL_SRCS = dmime.idl
......
......@@ -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_end_play(IDirectMusicSegmentState *iface);
extern HRESULT wave_track_create_from_chunk(IStream *stream, struct chunk_entry *parent,
IDirectMusicTrack8 **ret_iface);
/*****************************************************************************
* Auxiliary definitions
*/
......
......@@ -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};
HRESULT hr;
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) {
switch (chunk.id) {
case DMUS_FOURCC_SEGMENT_CHUNK:
......@@ -786,89 +790,58 @@ static inline struct segment *impl_from_IPersistStream(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;
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) {
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;
}
}
}
if (!stream) return E_POINTER;
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)
{
struct segment *This = impl_from_IPersistStream(iface);
struct chunk_entry riff = {0};
HRESULT hr;
case mmioFOURCC('M','T','h','d'):
FIXME("MIDI file loading not supported\n");
break;
TRACE("(%p, %p): Loading\n", This, stream);
case MAKE_IDTYPE(FOURCC_RIFF, mmioFOURCC('W','A','V','E')):
{
IDirectMusicTrack8 *track;
HRESULT hr;
if (!stream)
return E_POINTER;
TRACE("Loading segment %p from wave file\n", This);
if (stream_get_chunk(stream, &riff) != S_OK ||
(riff.id != FOURCC_RIFF && riff.id != mmioFOURCC('M','T','h','d')))
return DMUS_E_UNSUPPORTED_STREAM;
stream_reset_chunk_start(stream, &riff);
This->header.mtLength = 1;
if (FAILED(hr = wave_track_create_from_chunk(stream, &chunk, &track))) break;
hr = segment_append_track(This, (IDirectMusicTrack *)track, 1, 0);
break;
}
if (riff.id == mmioFOURCC('M','T','h','d')) {
FIXME("MIDI file loading not supported\n");
return S_OK;
default:
WARN("Invalid segment chunk %s %s\n", debugstr_fourcc(chunk.id), debugstr_fourcc(chunk.type));
hr = DMUS_E_UNSUPPORTED_STREAM;
break;
}
}
hr = IDirectMusicObject_ParseDescriptor(&This->dmobj.IDirectMusicObject_iface, stream,
&This->dmobj.desc);
if (FAILED(hr))
return hr;
stream_reset_chunk_data(stream, &riff);
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;
{
WARN("Failed to load segment from stream %p, hr %#lx\n", stream, hr);
return DMUS_E_UNSUPPORTED_STREAM;
}
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 =
......
......@@ -3279,7 +3279,7 @@ static void test_wave_pmsg(void)
length = 0xdeadbeef;
hr = IDirectMusicSegment_GetLength(segment, &length);
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 */
......
......@@ -17,13 +17,14 @@
*/
#include "dmime_private.h"
#include "dmusic_wave.h"
WINE_DEFAULT_DEBUG_CHANNEL(dmime);
struct wave_item {
struct list entry;
DMUS_IO_WAVE_ITEM_HEADER header;
IDirectMusicObject *object;
IUnknown *object;
};
struct wave_part {
......@@ -100,8 +101,7 @@ static ULONG WINAPI wave_track_Release(IDirectMusicTrack8 *iface)
list_remove(&part->entry);
LIST_FOR_EACH_ENTRY_SAFE(item, item2, &part->items, struct wave_item, entry) {
list_remove(&item->entry);
if (item->object)
IDirectMusicObject_Release(item->object);
if (item->object) IUnknown_Release(item->object);
free(item);
}
free(part);
......@@ -355,7 +355,7 @@ static HRESULT parse_wave_item(struct wave_part *part, IStream *stream, struct c
hr = DMUS_E_UNSUPPORTED_STREAM;
goto error;
}
if (FAILED(hr = dmobj_parsereference(stream, &chunk, &item->object)))
if (FAILED(hr = dmobj_parsereference(stream, &chunk, (IDirectMusicObject **)&item->object)))
goto error;
list_add_tail(&part->items, &item->entry);
......@@ -484,3 +484,38 @@ HRESULT create_dmwavetrack(REFIID lpcGUID, void **ppobj)
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;
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_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
IDirectMusicDownload_Release(download);
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