Esempio n. 1
0
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;
   }
}
Esempio n. 2
0
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();
}
Esempio n. 3
0
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();
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
// 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;
}
Esempio n. 7
0
/*
 * 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;
}
Esempio n. 8
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;
}
Esempio n. 9
0
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();
}
Esempio n. 10
0
//------------------------------------------------------------------------------
// 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;
}
Esempio n. 11
0
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();
}