1 /* 2 * Implementation of IAudioData Interface 3 * 4 * Copyright 2012 Christian Costa 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #include "wine/debug.h" 22 23 #define COBJMACROS 24 25 #include "winbase.h" 26 #include "amstream_private.h" 27 28 WINE_DEFAULT_DEBUG_CHANNEL(amstream); 29 30 typedef struct { 31 IAudioData IAudioData_iface; 32 LONG ref; 33 DWORD size; 34 BYTE *data; 35 BOOL data_owned; 36 DWORD actual_data; 37 WAVEFORMATEX wave_format; 38 } AMAudioDataImpl; 39 40 static inline AMAudioDataImpl *impl_from_IAudioData(IAudioData *iface) 41 { 42 return CONTAINING_RECORD(iface, AMAudioDataImpl, IAudioData_iface); 43 } 44 45 /*** IUnknown methods ***/ 46 static HRESULT WINAPI IAudioDataImpl_QueryInterface(IAudioData *iface, REFIID riid, void **ret_iface) 47 { 48 TRACE("(%p)->(%s,%p)\n", iface, debugstr_guid(riid), ret_iface); 49 50 if (IsEqualGUID(riid, &IID_IUnknown) || 51 IsEqualGUID(riid, &IID_IAudioData)) 52 { 53 IAudioData_AddRef(iface); 54 *ret_iface = iface; 55 return S_OK; 56 } 57 58 ERR("(%p)->(%s,%p),not found\n", iface, debugstr_guid(riid), ret_iface); 59 return E_NOINTERFACE; 60 } 61 62 static ULONG WINAPI IAudioDataImpl_AddRef(IAudioData* iface) 63 { 64 AMAudioDataImpl *This = impl_from_IAudioData(iface); 65 ULONG ref = InterlockedIncrement(&This->ref); 66 67 TRACE("(%p)->(): new ref = %u\n", iface, This->ref); 68 69 return ref; 70 } 71 72 static ULONG WINAPI IAudioDataImpl_Release(IAudioData* iface) 73 { 74 AMAudioDataImpl *This = impl_from_IAudioData(iface); 75 ULONG ref = InterlockedDecrement(&This->ref); 76 77 TRACE("(%p)->(): new ref = %u\n", iface, This->ref); 78 79 if (!ref) 80 { 81 if (This->data_owned) 82 { 83 CoTaskMemFree(This->data); 84 } 85 86 HeapFree(GetProcessHeap(), 0, This); 87 } 88 89 return ref; 90 } 91 92 /*** IMemoryData methods ***/ 93 static HRESULT WINAPI IAudioDataImpl_SetBuffer(IAudioData* iface, DWORD size, BYTE *data, DWORD flags) 94 { 95 AMAudioDataImpl *This = impl_from_IAudioData(iface); 96 97 TRACE("(%p)->(%u,%p,%x)\n", iface, size, data, flags); 98 99 if (!size) 100 { 101 return E_INVALIDARG; 102 } 103 104 if (This->data_owned) 105 { 106 CoTaskMemFree(This->data); 107 This->data_owned = FALSE; 108 } 109 110 This->size = size; 111 This->data = data; 112 113 if (!This->data) 114 { 115 This->data = CoTaskMemAlloc(This->size); 116 This->data_owned = TRUE; 117 if (!This->data) 118 { 119 return E_OUTOFMEMORY; 120 } 121 } 122 123 return S_OK; 124 } 125 126 static HRESULT WINAPI IAudioDataImpl_GetInfo(IAudioData* iface, DWORD *length, BYTE **data, DWORD *actual_data) 127 { 128 AMAudioDataImpl *This = impl_from_IAudioData(iface); 129 130 TRACE("(%p)->(%p,%p,%p)\n", iface, length, data, actual_data); 131 132 if (!This->data) 133 { 134 return MS_E_NOTINIT; 135 } 136 137 if (length) 138 { 139 *length = This->size; 140 } 141 if (data) 142 { 143 *data = This->data; 144 } 145 if (actual_data) 146 { 147 *actual_data = This->actual_data; 148 } 149 150 return S_OK; 151 } 152 153 static HRESULT WINAPI IAudioDataImpl_SetActual(IAudioData* iface, DWORD data_valid) 154 { 155 AMAudioDataImpl *This = impl_from_IAudioData(iface); 156 157 TRACE("(%p)->(%u)\n", iface, data_valid); 158 159 if (data_valid > This->size) 160 { 161 return E_INVALIDARG; 162 } 163 164 This->actual_data = data_valid; 165 166 return S_OK; 167 } 168 169 /*** IAudioData methods ***/ 170 static HRESULT WINAPI IAudioDataImpl_GetFormat(IAudioData* iface, WAVEFORMATEX *wave_format_current) 171 { 172 AMAudioDataImpl *This = impl_from_IAudioData(iface); 173 174 TRACE("(%p)->(%p)\n", iface, wave_format_current); 175 176 if (!wave_format_current) 177 { 178 return E_POINTER; 179 } 180 181 *wave_format_current = This->wave_format; 182 183 return S_OK; 184 } 185 186 static HRESULT WINAPI IAudioDataImpl_SetFormat(IAudioData* iface, const WAVEFORMATEX *wave_format) 187 { 188 AMAudioDataImpl *This = impl_from_IAudioData(iface); 189 190 TRACE("(%p)->(%p)\n", iface, wave_format); 191 192 if (!wave_format) 193 { 194 return E_POINTER; 195 } 196 197 if (WAVE_FORMAT_PCM != wave_format->wFormatTag) 198 { 199 return E_INVALIDARG; 200 } 201 202 This->wave_format = *wave_format; 203 204 return S_OK; 205 } 206 207 static const struct IAudioDataVtbl AudioData_Vtbl = 208 { 209 /*** IUnknown methods ***/ 210 IAudioDataImpl_QueryInterface, 211 IAudioDataImpl_AddRef, 212 IAudioDataImpl_Release, 213 /*** IMemoryData methods ***/ 214 IAudioDataImpl_SetBuffer, 215 IAudioDataImpl_GetInfo, 216 IAudioDataImpl_SetActual, 217 /*** IAudioData methods ***/ 218 IAudioDataImpl_GetFormat, 219 IAudioDataImpl_SetFormat 220 }; 221 222 HRESULT AMAudioData_create(IUnknown *pUnkOuter, LPVOID *ppObj) 223 { 224 AMAudioDataImpl *object; 225 226 TRACE("(%p,%p)\n", pUnkOuter, ppObj); 227 228 if (pUnkOuter) 229 return CLASS_E_NOAGGREGATION; 230 231 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(AMAudioDataImpl)); 232 if (!object) 233 return E_OUTOFMEMORY; 234 235 object->IAudioData_iface.lpVtbl = &AudioData_Vtbl; 236 object->ref = 1; 237 238 object->wave_format.wFormatTag = WAVE_FORMAT_PCM; 239 object->wave_format.nChannels = 1; 240 object->wave_format.nSamplesPerSec = 11025; 241 object->wave_format.wBitsPerSample = 16; 242 object->wave_format.nBlockAlign = object->wave_format.wBitsPerSample * object->wave_format.nChannels / 8; 243 object->wave_format.nAvgBytesPerSec = object->wave_format.nBlockAlign * object->wave_format.nSamplesPerSec; 244 245 *ppObj = &object->IAudioData_iface; 246 247 return S_OK; 248 } 249