/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim:expandtab:shiftwidth=4:tabstop=4:
*/ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
static ca_context* ca_context_get_default() { // This allows us to avoid race conditions with freeing the context by handing // that responsibility to Glib, and still use one context at a time static GPrivate ctx_private =
G_PRIVATE_INIT((GDestroyNotify)ca_context_destroy);
ca_context_create(&ctx); if (!ctx) { return nullptr;
}
#if !defined(XP_OPENBSD) && ((defined MOZ_ALSA) || (defined MOZ_SNDIO))
{ // On most platforms, libcanberra is configured to prefer pulse. // If the pulse daemon is not running then every time a sound is played // libcanberra will dlopen libpulse.so and try to create a new context, // which will fail. // We don't really want this to happen every time a sound is played (this // will stall the main thread, for instance, when opening a context menu), // so try to use ALSA or sndio if cubeb is already using that. // There is no point in doing this on OpenBSD, as system libcanberra // already prefers sndio there, which should always work.
nsAutoString backend;
mozilla::CubebUtils::GetCurrentBackend(backend);
// Only check for each backend if we have support compiled in. # ifdef MOZ_ALSA if (backend == u"alsa"_ns) {
ca_context_set_driver(ctx, "alsa");
} # endif # ifdef MOZ_SNDIO if (backend == u"sndio"_ns) {
ca_context_set_driver(ctx, "sndio");
} # endif
} #endif
g_private_set(&ctx_private, ctx);
NS_IMETHODIMP
nsSound::Init() { // This function is designed so that no library is compulsory, and // one library missing doesn't cause the other(s) to not be used. if (mInited) return NS_OK;
mInited = true;
if (!libcanberra) {
libcanberra = PR_LoadLibrary("libcanberra.so.0"); if (libcanberra) {
ca_context_create = (ca_context_create_fn)PR_FindFunctionSymbol(
libcanberra, "ca_context_create"); if (!ca_context_create) { #ifdef MOZ_TSAN // With TSan, we cannot unload libcanberra once we have loaded it // because TSan does not support unloading libraries that are matched // from its suppression list. Hence we just keep the library loaded in // TSan builds.
libcanberra = nullptr; return NS_OK; #endif
PR_UnloadLibrary(libcanberra);
libcanberra = nullptr;
} else { // at this point we know we have a good libcanberra library
ca_context_destroy = (ca_context_destroy_fn)PR_FindFunctionSymbol(
libcanberra, "ca_context_destroy");
ca_context_set_driver = (ca_context_set_driver_fn)PR_FindFunctionSymbol(
libcanberra, "ca_context_set_driver");
ca_context_play = (ca_context_play_fn)PR_FindFunctionSymbol(
libcanberra, "ca_context_play");
ca_context_change_props =
(ca_context_change_props_fn)PR_FindFunctionSymbol(
libcanberra, "ca_context_change_props");
ca_proplist_create = (ca_proplist_create_fn)PR_FindFunctionSymbol(
libcanberra, "ca_proplist_create");
ca_proplist_destroy = (ca_proplist_destroy_fn)PR_FindFunctionSymbol(
libcanberra, "ca_proplist_destroy");
ca_proplist_sets = (ca_proplist_sets_fn)PR_FindFunctionSymbol(
libcanberra, "ca_proplist_sets");
ca_context_play_full = (ca_context_play_full_fn)PR_FindFunctionSymbol(
libcanberra, "ca_context_play_full");
}
}
}
if (!sInstance) { if (gfxPlatform::IsHeadless()) {
sInstance = new mozilla::widget::HeadlessSound();
} else {
sInstance = new nsSound();
}
ClearOnShutdown(&sInstance);
}
RefPtr<nsISound> service = sInstance.get(); return service.forget();
}
NS_IMETHODIMP nsSound::OnStreamComplete(nsIStreamLoader* aLoader,
nsISupports* context, nsresult aStatus,
uint32_t dataLen, const uint8_t* data) { // print a load error on bad status, and return if (NS_FAILED(aStatus)) { #ifdef DEBUG if (aLoader) {
nsCOMPtr<nsIRequest> request;
aLoader->GetRequest(getter_AddRefs(request)); if (request) {
nsCOMPtr<nsIURI> uri;
nsCOMPtr<nsIChannel> channel = do_QueryInterface(request); if (channel) {
channel->GetURI(getter_AddRefs(uri)); if (uri) {
printf("Failed to load %s\n", uri->GetSpecOrDefault().get());
}
}
}
} #endif return aStatus;
}
// XXX: Should we do this on another thread?
uint32_t length = dataLen; while (length > 0) {
int32_t amount = PR_Write(fd.get(), data, length); if (amount < 0) { return NS_ERROR_FAILURE;
}
length -= amount;
data += amount;
}
ca_context* ctx = ca_context_get_default(); if (!ctx) { return NS_ERROR_OUT_OF_MEMORY;
}
ca_proplist* p;
ca_proplist_create(&p); if (!p) { return NS_ERROR_OUT_OF_MEMORY;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.