void OpenALAudio::yield() { /* FIXME: This object causes a frame flip. Looks like a hack that could * use some fixing. */ VgaFrontLock vgaLock; StreamMap::iterator si; for (si = this->streams.begin(); si != this->streams.end();) { ALint state; StreamContext *sc; sc = si->second; if (sc->stream_data()) { ++si; continue; } alGetSourcei(sc->source, AL_SOURCE_STATE, &state); if (state == AL_STOPPED) { delete sc; this->streams.erase(si++); continue; } ++si; } }
Variant f_stream_context_get_options(const Resource& stream_or_context) { StreamContext* context = get_stream_context(stream_or_context); if (!context) { raise_warning("Invalid stream/context parameter"); return false; } return context->getOptions(); }
Variant f_stream_context_get_params(CResRef stream_or_context) { StreamContext* context = get_stream_context(stream_or_context); if (!context) { raise_warning("Invalid stream/context parameter"); return false; } return context->getParams(); }
bool f_stream_context_set_params(const Resource& stream_or_context, const Array& params) { StreamContext* context = get_stream_context(stream_or_context); if (!context || !StreamContext::validateParams(params)) { raise_warning("Invalid stream/context parameter"); return false; } context->mergeParams(params); return true; }
bool f_stream_context_set_params(CResRef stream_or_context, CArrRef params) { StreamContext* context = get_stream_context(stream_or_context); if (!context || !StreamContext::validateParams(params)) { raise_warning("Invalid stream/context parameter"); return false; } context->mergeParams(params); return true; }
// stop a short sound effect started by play_long_wav // // id - the serial no returned by play_long_wav // // return 1 - channel is found and stopped / channel not found // return 0 - cannot stop the channel // int OpenALAudio::stop_long_wav(int id) { StreamMap::iterator itr; StreamContext *sc; if (!this->wav_init_flag) return 1; MSG("stop_long_wav(%i)\n", id); itr = this->streams.find(id); if (itr == this->streams.end()) return 1; sc = itr->second; sc->stop(); this->streams.erase(itr); delete sc; return 1; }
/* * in - wav file stream to play. Claims ownership and will delete it. * vol - volume/panning * * return: 1 on success, 0 on failure */ int OpenALAudio::play_long_wav(InputStream *in, const DsVolume &vol) { const int BUFFER_COUNT = 4; StreamContext *sc = NULL; WavStream *ws = NULL; int id; assert(this->wav_init_flag); ws = new WavStream; if (!ws->open(in)) { delete in; goto err; } sc = new StreamContext; if (!sc->init(ws)) goto err; set_source_panning(sc->source, vol.ds_pan); set_source_volume(sc->source, vol.ds_vol + this->wav_volume); if (!check_al()) goto err; sc->stream_data(BUFFER_COUNT); id = unused_key(&this->streams); this->streams[id] = sc; return id; err: delete sc; delete ws; return 0; }
BOOL HandleWaveMessage(PMMDRV_MESSAGE_PARAMS pParams, DWORD *pdwResult) { // set the error code to be no error first SetLastError(MMSYSERR_NOERROR); UINT uMsg = pParams->uMsg; UINT uDeviceId = pParams->uDeviceId; DWORD dwParam1 = pParams->dwParam1; DWORD dwParam2 = pParams->dwParam2; DWORD dwUser = pParams->dwUser; StreamContext *pStreamContext = (StreamContext *)dwUser; DWORD dwRet; g_pHWContext->Lock(); _try { switch (uMsg) { case WODM_GETNUMDEVS: { dwRet = g_pHWContext->GetNumOutputDevices(); break; } case WIDM_GETNUMDEVS: { dwRet = g_pHWContext->GetNumInputDevices(); break; } case WODM_GETDEVCAPS: { DeviceContext *pDeviceContext; UINT NumDevs = g_pHWContext->GetNumOutputDevices(); if (pStreamContext) { pDeviceContext=pStreamContext->GetDeviceContext(); } else { pDeviceContext = g_pHWContext->GetOutputDeviceContext(uDeviceId); } dwRet = pDeviceContext->GetDevCaps((PVOID)dwParam1,dwParam2); break; } case WIDM_GETDEVCAPS: { DeviceContext *pDeviceContext; UINT NumDevs = g_pHWContext->GetNumInputDevices(); if (pStreamContext) { pDeviceContext=pStreamContext->GetDeviceContext(); } else { pDeviceContext = g_pHWContext->GetInputDeviceContext(uDeviceId); } dwRet = pDeviceContext->GetDevCaps((PVOID)dwParam1,dwParam2); break; } case WODM_GETEXTDEVCAPS: { DeviceContext *pDeviceContext; UINT NumDevs = g_pHWContext->GetNumOutputDevices(); if (pStreamContext) { pDeviceContext=pStreamContext->GetDeviceContext(); } else { pDeviceContext = g_pHWContext->GetOutputDeviceContext(uDeviceId); } dwRet = pDeviceContext->GetExtDevCaps((PVOID)dwParam1,dwParam2); break; } case WODM_OPEN: { DEBUGMSG(ZONE_WODM, (TEXT("WODM_OPEN\r\n"))); DeviceContext *pDeviceContext = g_pHWContext->GetOutputDeviceContext(uDeviceId); dwRet = pDeviceContext->OpenStream((LPWAVEOPENDESC)dwParam1, dwParam2, (StreamContext **)dwUser); break; } case WIDM_OPEN: { DEBUGMSG(ZONE_WIDM, (TEXT("WIDM_OPEN\r\n"))); DeviceContext *pDeviceContext = g_pHWContext->GetInputDeviceContext(uDeviceId); dwRet = pDeviceContext->OpenStream((LPWAVEOPENDESC)dwParam1, dwParam2, (StreamContext **)dwUser); break; } case WODM_CLOSE: case WIDM_CLOSE: { DEBUGMSG(ZONE_WIDM, (TEXT("WIDM_CLOSE/WODM_CLOSE\r\n"))); dwRet = pStreamContext->Close(); // Release stream context here, rather than inside StreamContext::Close, so that if someone // (like CMidiStream) has subclassed Close there's no chance that the object will get released // out from under them. if (dwRet==MMSYSERR_NOERROR) { pStreamContext->Release(); } break; } case WODM_RESTART: case WIDM_START: { dwRet = pStreamContext->Run(); break; } case WODM_PAUSE: case WIDM_STOP: { dwRet = pStreamContext->Stop(); break; } case WODM_GETPOS: case WIDM_GETPOS: { dwRet = pStreamContext->GetPos((PMMTIME)dwParam1); break; } case WODM_RESET: case WIDM_RESET: { dwRet = pStreamContext->Reset(); break; } case WODM_WRITE: case WIDM_ADDBUFFER: { DEBUGMSG(ZONE_WIDM, (TEXT("WODM_WRITE/WIDM_ADDBUFFER, Buffer=0x%x\r\n"),dwParam1)); dwRet = pStreamContext->QueueBuffer((LPWAVEHDR)dwParam1); break; } case WODM_GETVOLUME: { PULONG pdwGain = (PULONG)dwParam1; UINT NumDevs = g_pHWContext->GetNumOutputDevices(); if (pStreamContext) { *pdwGain = pStreamContext->GetGain(); } else { DeviceContext *pDeviceContext = g_pHWContext->GetOutputDeviceContext(uDeviceId); *pdwGain = pDeviceContext->GetGain(); } dwRet = MMSYSERR_NOERROR; break; } case WODM_SETVOLUME: { UINT NumDevs = g_pHWContext->GetNumOutputDevices(); LONG dwGain = dwParam1; if (pStreamContext) { dwRet = pStreamContext->SetGain(dwGain); } else { DeviceContext *pDeviceContext = g_pHWContext->GetOutputDeviceContext(uDeviceId); dwRet = pDeviceContext->SetGain(dwGain); } break; } case WODM_BREAKLOOP: { dwRet = pStreamContext->BreakLoop(); break; } case WODM_SETPLAYBACKRATE: { WaveStreamContext *pWaveStream = (WaveStreamContext *)dwUser; dwRet = pWaveStream->SetRate(dwParam1); break; } case WODM_GETPLAYBACKRATE: { WaveStreamContext *pWaveStream = (WaveStreamContext *)dwUser; dwRet = pWaveStream->GetRate((DWORD *)dwParam1); break; } case MM_WOM_SETSECONDARYGAINCLASS: { if (pStreamContext) { dwRet = pStreamContext->SetSecondaryGainClass(dwParam1); } else { dwRet = MMSYSERR_INVALPARAM; } break; } case MM_WOM_SETSECONDARYGAINLIMIT: { DeviceContext *pDeviceContext; if (pStreamContext) { pDeviceContext = pStreamContext->GetDeviceContext(); } else { pDeviceContext = g_pHWContext->GetOutputDeviceContext(uDeviceId); } dwRet = pDeviceContext->SetSecondaryGainLimit(dwParam1,dwParam2); break; } case MM_MOM_MIDIMESSAGE: { CMidiStream *pMidiStream = (CMidiStream *)dwUser; dwRet = pMidiStream->MidiMessage(dwParam1); break; } // unsupported messages case WODM_GETPITCH: case WODM_SETPITCH: case WODM_PREPARE: case WODM_UNPREPARE: case WIDM_PREPARE: case WIDM_UNPREPARE: default: dwRet = MMSYSERR_NOTSUPPORTED; } } _except (EXCEPTION_EXECUTE_HANDLER) { dwRet = MMSYSERR_INVALPARAM; } g_pHWContext->Unlock(); // Pass the return code back via pBufOut if (pdwResult) { *pdwResult = dwRet; } return TRUE; }
File* HttpStreamWrapper::open(const String& filename, const String& mode, int options, const Variant& context) { if (RuntimeOption::ServerHttpSafeMode) { return nullptr; } if (strncmp(filename.data(), "http://", sizeof("http://") - 1) && strncmp(filename.data(), "https://", sizeof("https://") - 1)) { return nullptr; } std::unique_ptr<UrlFile> file; StreamContext *ctx = !context.isResource() ? nullptr : context.toResource().getTyped<StreamContext>(); Array headers; String method = s_GET; String post_data = null_string; int max_redirs = 20; int timeout = -1; bool ignore_errors = false; if (ctx && !ctx->getOptions().isNull() && !ctx->getOptions()[s_http].isNull()) { Array opts = ctx->getOptions()[s_http].toArray(); if (opts.exists(s_method)) { method = opts[s_method].toString(); } if (opts.exists(s_header)) { Array lines; if (opts[s_header].isString()) { lines = StringUtil::Explode( opts[s_header].toString(), "\r\n").toArray(); } else if (opts[s_header].isArray()) { lines = opts[s_header]; } for (ArrayIter it(lines); it; ++it) { Array parts = StringUtil::Explode( it.second().toString(), ":").toArray(); headers.set(parts.rvalAt(0), parts.rvalAt(1)); } } if (opts.exists(s_user_agent) && !headers.exists(s_User_Agent)) { headers.set(s_User_Agent, opts[s_user_agent]); } if (opts.exists(s_max_redirects)) { max_redirs = opts[s_max_redirects].toInt64(); } if (opts.exists(s_timeout)) { timeout = opts[s_timeout].toInt64(); } if (opts.exists(s_ignore_errors)) { ignore_errors = opts[s_ignore_errors].toBoolean(); } post_data = opts[s_content].toString(); } if (!headers.exists(s_User_Agent)) { auto default_user_agent = ThreadInfo::s_threadInfo.getNoCheck() ->m_reqInjectionData.getUserAgent(); if (!default_user_agent.empty()) { headers.set(s_User_Agent, default_user_agent); } } file = std::unique_ptr<UrlFile>(newres<UrlFile>(method.data(), headers, post_data, max_redirs, timeout, ignore_errors)); bool ret = file->open(filename, mode); if (!ret) { raise_warning("Failed to open %s (%s)", filename.data(), file->getLastError().c_str()); return nullptr; } return file.release(); }
//------------------------------------------------------------------------------ // process_MiscellaneousMessage, all messages not handled by the other message // handlers // BOOL CAudioManager::process_AudioStreamMessage( PMMDRV_MESSAGE_PARAMS pParams, DWORD *pdwResult ) { DEBUGMSG(ZONE_FUNCTION, (L"WAV:+process_AudioStreamMessage(uMsg=%d)\r\n", pParams->uMsg) ); // set the error code to be no error first SetLastError(MMSYSERR_NOERROR); CStreamManager *pStreamManager; WaveStreamContext *pWaveStream; PDWORD pdwGain; UINT uMsg = pParams->uMsg; UINT uDeviceId = pParams->uDeviceId; DWORD dwParam1 = pParams->dwParam1; DWORD dwParam2 = pParams->dwParam2; DWORD dwUser = pParams->dwUser; StreamContext *pStreamContext = (StreamContext *)dwUser; DWORD dwRet=MMSYSERR_NOTSUPPORTED; switch (uMsg) { case WODM_SETVOLUME: DEBUGMSG(ZONE_WODM, (L"WAV:WODM_SETVOLUME\r\n")); dwRet = (pStreamContext) ? pStreamContext->SetGain(dwParam1) : put_OutputGain(dwParam1); break; case WODM_RESTART: case WIDM_START: DEBUGMSG(ZONE_WODM|ZONE_WIDM, (L"WAV:WODM_RESTART/WIDM_START\r\n")); dwRet = pStreamContext->Run(); break; case WODM_PAUSE: case WIDM_STOP: DEBUGMSG(ZONE_WODM|ZONE_WIDM, (L"WAV:WODM_PAUSE/WIDM_STOP\r\n")); dwRet = pStreamContext->Stop(); break; case WODM_GETPOS: case WIDM_GETPOS: DEBUGMSG(ZONE_WODM|ZONE_WIDM, (L"WAV:WODM_GETPOS/WIDM_GETPOS\r\n")); dwRet = pStreamContext->GetPos((PMMTIME)dwParam1); break; case WODM_RESET: case WIDM_RESET: DEBUGMSG(ZONE_WODM|ZONE_WIDM, (L"WAV:WODM_RESET/WIDM_RESET\r\n")); dwRet = pStreamContext->Reset(); break; case WODM_WRITE: case WIDM_ADDBUFFER: DEBUGMSG(ZONE_WODM|ZONE_WIDM, (L"WAV:WODM_WRITE/WIDM_ADDBUFFER\r\n") ); if(m_bSuspend==TRUE) dwRet=MMSYSERR_NOERROR; else dwRet = pStreamContext->QueueBuffer((LPWAVEHDR)dwParam1); break; case WODM_GETVOLUME: DEBUGMSG(ZONE_WODM, (L"WAV:WODM_GETVOLUME\r\n")); pdwGain = (PDWORD)dwParam1; *pdwGain = (pStreamContext) ? pStreamContext->GetGain() : get_OutputGain(); dwRet = MMSYSERR_NOERROR; break; case WODM_BREAKLOOP: DEBUGMSG(ZONE_WODM, (L"WAV:WODM_BREAKLOOP\r\n")); dwRet = pStreamContext->BreakLoop(); break; case WODM_SETPLAYBACKRATE: DEBUGMSG(ZONE_WODM, (L"WAV:WODM_SETPLAYBACKRATE\r\n")); pWaveStream = (WaveStreamContext *)dwUser; dwRet = pWaveStream->SetRate(dwParam1); break; case WODM_GETPLAYBACKRATE: DEBUGMSG(ZONE_WODM, (L"WAV:WODM_GETPLAYBACKRATE\r\n")); pWaveStream = (WaveStreamContext *)dwUser; dwRet = pWaveStream->GetRate((DWORD *)dwParam1); break; case MM_WOM_FORCEQUALITY: DEBUGMSG(ZONE_WODM, (L"WAV:MM_WOM_FORCEQUALITY\r\n")); if (pStreamContext) { dwRet = pStreamContext->ForceQuality((BOOL)dwParam1); } else { dwRet = get_HardwareAudioBridge()->enable_WideBand( (BOOL)dwParam1 ); } break; case WODM_BT_SCO_AUDIO_CONTROL: DEBUGMSG(ZONE_WODM, (L"WAV:WODM_BT_SCO_AUDIO_CONTROL\r\n")); get_HardwareAudioBridge()->notify_BTHeadsetAttached( pParams->dwParam2 ); dwRet = MMSYSERR_NOERROR; break; case WODM_CLOSE: case WIDM_CLOSE: DEBUGMSG(ZONE_WODM|ZONE_WIDM, (L"WAV:WIDM_CLOSE/WODM_CLOSE\r\n")); // Release stream context here, rather than inside // StreamContext::Close, so that if someone // has subclassed Close there's no chance that the object // will get released out from under them. // dwRet = pStreamContext->Close(); if (dwRet == MMSYSERR_NOERROR) { pStreamContext->Release(); } break; case WODM_OPEN: DEBUGMSG(ZONE_WODM, (L"WAV:WODM_OPEN\r\n")); pStreamManager = get_OutputStreamManager(uDeviceId); dwRet = pStreamManager->open_Stream((LPWAVEOPENDESC)dwParam1, dwParam2, (StreamContext **)dwUser ); break; case WIDM_OPEN: DEBUGMSG(ZONE_WODM, (L"WAV:WIDM_OPEN\r\n")); pStreamManager = get_InputStreamManager(uDeviceId); dwRet = pStreamManager->open_Stream((LPWAVEOPENDESC)dwParam1, dwParam2, (StreamContext **)dwUser ); break; case WODM_GETDEVCAPS: DEBUGMSG(ZONE_WODM, (L"WAV:WODM_GETDEVCAPS\r\n")); pStreamManager = (pStreamContext) ? pStreamContext->GetStreamManager() : get_OutputStreamManager(uDeviceId); dwRet = pStreamManager->get_DevCaps((PVOID)dwParam1, dwParam2); break; case WIDM_GETDEVCAPS: DEBUGMSG(ZONE_WIDM, (L"WAV:WIDM_GETDEVCAPS\r\n")); pStreamManager = (pStreamContext) ? pStreamContext->GetStreamManager() : get_InputStreamManager(uDeviceId); dwRet = pStreamManager->get_DevCaps((PVOID)dwParam1, dwParam2); break; case WODM_GETEXTDEVCAPS: DEBUGMSG(ZONE_WODM, (L"WAV:WODM_GETEXTDEVCAPS\r\n")); pStreamManager = (pStreamContext) ? pStreamContext->GetStreamManager() : get_OutputStreamManager(uDeviceId); dwRet = pStreamManager->get_ExtDevCaps((PVOID)dwParam1, dwParam2); break; case WIDM_GETNUMDEVS: DEBUGMSG(ZONE_WODM, (L"WAV:WIDM_GETNUMDEVS\r\n")); dwRet = get_InputDeviceCount(); break; case WODM_GETNUMDEVS: DEBUGMSG(ZONE_WIDM, (L"WAV:WODM_GETNUMDEVS\r\n")); dwRet = get_OutputDeviceCount(); break; case WODM_GETPROP: { // DEBUGMSG(ZONE_WODM, (TEXT("WODM_GETPROP\r\n"))); PWAVEPROPINFO pPropInfo = (PWAVEPROPINFO) dwParam1; if (pStreamContext) { dwRet = pStreamContext->GetProperty(pPropInfo); } else { pStreamManager = get_OutputStreamManager(uDeviceId); dwRet = pStreamManager->GetProperty(pPropInfo); } break; } case WIDM_GETPROP: { // DEBUGMSG(ZONE_WODM, (TEXT("WIDM_GETPROP\r\n"))); PWAVEPROPINFO pPropInfo = (PWAVEPROPINFO) dwParam1; if (pStreamContext) { dwRet = pStreamContext->GetProperty(pPropInfo); } else { pStreamManager = get_InputStreamManager(uDeviceId); dwRet = pStreamManager->GetProperty(pPropInfo); } break; } case WODM_SETPROP: { // DEBUGMSG(ZONE_WODM, (TEXT("WODM_SETPROP\r\n"))); PWAVEPROPINFO pPropInfo = (PWAVEPROPINFO) dwParam1; if (pStreamContext) { dwRet = pStreamContext->SetProperty(pPropInfo); } else { pStreamManager = get_OutputStreamManager(uDeviceId); dwRet = pStreamManager->SetProperty(pPropInfo); } break; } case WIDM_SETPROP: { // DEBUGMSG(ZONE_WODM, (TEXT("WIDM_SETPROP\r\n"))); PWAVEPROPINFO pPropInfo = (PWAVEPROPINFO) dwParam1; if (pStreamContext) { dwRet = pStreamContext->SetProperty(pPropInfo); } else { pStreamManager = get_InputStreamManager(uDeviceId); dwRet = pStreamManager->SetProperty(pPropInfo); } break; } case WODM_GETPITCH: case WODM_SETPITCH: case WODM_PREPARE: case WODM_UNPREPARE: case WIDM_PREPARE: case WIDM_UNPREPARE: default: dwRet = MMSYSERR_NOTSUPPORTED; } if (pdwResult) { *pdwResult = dwRet; } DEBUGMSG(ZONE_FUNCTION, (L"WAV:-process_AudioStreamMessage(bResult=%d)\r\n", TRUE) ); return TRUE; }
File* HttpStreamWrapper::open(const String& filename, const String& mode, int options, CVarRef context) { if (RuntimeOption::ServerHttpSafeMode) { return nullptr; } if (strncmp(filename.data(), "http://", sizeof("http://") - 1) && strncmp(filename.data(), "https://", sizeof("https://") - 1)) { return nullptr; } std::unique_ptr<UrlFile> file; StreamContext *ctx = !context.isResource() ? nullptr : context.toResource().getTyped<StreamContext>(); if (!ctx || ctx->getOptions().isNull() || ctx->getOptions()[s_http].isNull()) { file = std::unique_ptr<UrlFile>(NEWOBJ(UrlFile)()); } else { Array opts = ctx->getOptions()[s_http].toArray(); String method = s_GET; if (opts.exists(s_method)) { method = opts[s_method].toString(); } Array headers; if (opts.exists(s_header)) { Array lines; if (opts[s_header].isString()) { lines = StringUtil::Explode( opts[s_header].toString(), "\r\n").toArray(); } else if (opts[s_header].isArray()) { lines = opts[s_header]; } for (ArrayIter it(lines); it; ++it) { Array parts = StringUtil::Explode( it.second().toString(), ": ").toArray(); headers.set(parts.rvalAt(0), parts.rvalAt(1)); } } if (opts.exists(s_user_agent) && !headers.exists(s_User_Agent)) { headers.set(s_User_Agent, opts[s_user_agent]); } int max_redirs = 20; if (opts.exists(s_max_redirects)) { max_redirs = opts[s_max_redirects].toInt64(); } int timeout = -1; if (opts.exists(s_timeout)) { timeout = opts[s_timeout].toInt64(); } file = std::unique_ptr<UrlFile>(NEWOBJ(UrlFile)(method.data(), headers, opts[s_content].toString(), max_redirs, timeout)); } bool ret = file->open(filename, mode); if (!ret) { raise_warning("Failed to open %s (%s)", filename.data(), file->getLastError().c_str()); return nullptr; } return file.release(); }