mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
The Linux kernel imposes a 15-byte limit on thread names[1]. This means information that does not fit in this limit, e.g., the pipeline ID of layout and script threads, is lost in a debugger and profiler (see the first column of the table below). This commit shortens the thread names used in Servo to maximize the amount of information conveyed. It also rectifies some inconsistencies in the names. | Before | After | |-------------------|-------------------| | `BluetoothThread` | `Bluetooth` | | `CanvasThread` | `Canvas` | | `display alert d` | `AlertDialog` | | `FontCacheThread` | `FontCache` | | `GLPlayerThread` | `GLPlayer` | | `HTML Parser` | `Parse:www.examp` | | `LayoutThread Pi` | `Layout(1,1)` | | `Memory profiler` | `MemoryProfiler` | | `Memory profiler` | `MemoryProfTimer` | | `OfflineAudioCon` | `OfflineACResolv` | | `PullTimelineMar` | `PullTimelineDat` | | `ScriptThread Pi` | `Script(1,1)` | | `WebWorker for h` | `WW:www.example.` | | `ServiceWorker f` | `SW:www.example.` | | `ServiceWorkerMa` | `SvcWorkerManage` | | `Time profiler t` | `TimeProfTimer` | | `Time profiler` | `TimeProfiler` | | `WebGL thread` | `WebGL` | | `Choose a device` | `DevicePicker` | | `Pick a file` | `FilePicker` | | `Pick files` | `FilePicker` | [1]: https://stackoverflow.com/questions/5026531/thread-name-longer-than-15-chars
205 lines
7.8 KiB
Rust
205 lines
7.8 KiB
Rust
/* 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 https://mozilla.org/MPL/2.0/. */
|
|
|
|
use crate::dom::audiobuffer::{AudioBuffer, MAX_SAMPLE_RATE, MIN_SAMPLE_RATE};
|
|
use crate::dom::audionode::MAX_CHANNEL_COUNT;
|
|
use crate::dom::baseaudiocontext::{BaseAudioContext, BaseAudioContextOptions};
|
|
use crate::dom::bindings::cell::DomRefCell;
|
|
use crate::dom::bindings::codegen::Bindings::BaseAudioContextBinding::BaseAudioContextBinding::BaseAudioContextMethods;
|
|
use crate::dom::bindings::codegen::Bindings::OfflineAudioContextBinding::OfflineAudioContextMethods;
|
|
use crate::dom::bindings::codegen::Bindings::OfflineAudioContextBinding::OfflineAudioContextOptions;
|
|
use crate::dom::bindings::error::{Error, Fallible};
|
|
use crate::dom::bindings::inheritance::Castable;
|
|
use crate::dom::bindings::num::Finite;
|
|
use crate::dom::bindings::refcounted::Trusted;
|
|
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
|
|
use crate::dom::bindings::root::DomRoot;
|
|
use crate::dom::event::{Event, EventBubbles, EventCancelable};
|
|
use crate::dom::offlineaudiocompletionevent::OfflineAudioCompletionEvent;
|
|
use crate::dom::promise::Promise;
|
|
use crate::dom::window::Window;
|
|
use crate::realms::InRealm;
|
|
use crate::task_source::TaskSource;
|
|
use dom_struct::dom_struct;
|
|
use msg::constellation_msg::PipelineId;
|
|
use servo_media::audio::context::OfflineAudioContextOptions as ServoMediaOfflineAudioContextOptions;
|
|
use std::cell::Cell;
|
|
use std::rc::Rc;
|
|
use std::sync::mpsc;
|
|
use std::sync::{Arc, Mutex};
|
|
use std::thread::Builder;
|
|
|
|
#[dom_struct]
|
|
pub struct OfflineAudioContext {
|
|
context: BaseAudioContext,
|
|
channel_count: u32,
|
|
length: u32,
|
|
rendering_started: Cell<bool>,
|
|
#[ignore_malloc_size_of = "promises are hard"]
|
|
pending_rendering_promise: DomRefCell<Option<Rc<Promise>>>,
|
|
}
|
|
|
|
#[allow(non_snake_case)]
|
|
impl OfflineAudioContext {
|
|
#[allow(unrooted_must_root)]
|
|
fn new_inherited(
|
|
channel_count: u32,
|
|
length: u32,
|
|
sample_rate: f32,
|
|
pipeline_id: PipelineId,
|
|
) -> OfflineAudioContext {
|
|
let options = ServoMediaOfflineAudioContextOptions {
|
|
channels: channel_count as u8,
|
|
length: length as usize,
|
|
sample_rate,
|
|
};
|
|
let context = BaseAudioContext::new_inherited(
|
|
BaseAudioContextOptions::OfflineAudioContext(options),
|
|
pipeline_id,
|
|
);
|
|
OfflineAudioContext {
|
|
context,
|
|
channel_count,
|
|
length,
|
|
rendering_started: Cell::new(false),
|
|
pending_rendering_promise: Default::default(),
|
|
}
|
|
}
|
|
|
|
#[allow(unrooted_must_root)]
|
|
fn new(
|
|
window: &Window,
|
|
channel_count: u32,
|
|
length: u32,
|
|
sample_rate: f32,
|
|
) -> Fallible<DomRoot<OfflineAudioContext>> {
|
|
if channel_count > MAX_CHANNEL_COUNT ||
|
|
channel_count <= 0 ||
|
|
length <= 0 ||
|
|
sample_rate < MIN_SAMPLE_RATE ||
|
|
sample_rate > MAX_SAMPLE_RATE
|
|
{
|
|
return Err(Error::NotSupported);
|
|
}
|
|
let pipeline_id = window.pipeline_id();
|
|
let context =
|
|
OfflineAudioContext::new_inherited(channel_count, length, sample_rate, pipeline_id);
|
|
Ok(reflect_dom_object(Box::new(context), window))
|
|
}
|
|
|
|
pub fn Constructor(
|
|
window: &Window,
|
|
options: &OfflineAudioContextOptions,
|
|
) -> Fallible<DomRoot<OfflineAudioContext>> {
|
|
OfflineAudioContext::new(
|
|
window,
|
|
options.numberOfChannels,
|
|
options.length,
|
|
*options.sampleRate,
|
|
)
|
|
}
|
|
|
|
pub fn Constructor_(
|
|
window: &Window,
|
|
number_of_channels: u32,
|
|
length: u32,
|
|
sample_rate: Finite<f32>,
|
|
) -> Fallible<DomRoot<OfflineAudioContext>> {
|
|
OfflineAudioContext::new(window, number_of_channels, length, *sample_rate)
|
|
}
|
|
}
|
|
|
|
impl OfflineAudioContextMethods for OfflineAudioContext {
|
|
// https://webaudio.github.io/web-audio-api/#dom-offlineaudiocontext-oncomplete
|
|
event_handler!(complete, GetOncomplete, SetOncomplete);
|
|
|
|
// https://webaudio.github.io/web-audio-api/#dom-offlineaudiocontext-length
|
|
fn Length(&self) -> u32 {
|
|
self.length
|
|
}
|
|
|
|
// https://webaudio.github.io/web-audio-api/#dom-offlineaudiocontext-startrendering
|
|
fn StartRendering(&self, comp: InRealm) -> Rc<Promise> {
|
|
let promise = Promise::new_in_current_realm(&self.global(), comp);
|
|
if self.rendering_started.get() {
|
|
promise.reject_error(Error::InvalidState);
|
|
return promise;
|
|
}
|
|
self.rendering_started.set(true);
|
|
|
|
*self.pending_rendering_promise.borrow_mut() = Some(promise.clone());
|
|
|
|
let processed_audio = Arc::new(Mutex::new(Vec::new()));
|
|
let processed_audio_ = processed_audio.clone();
|
|
let (sender, receiver) = mpsc::channel();
|
|
let sender = Mutex::new(sender);
|
|
self.context
|
|
.audio_context_impl()
|
|
.lock()
|
|
.unwrap()
|
|
.set_eos_callback(Box::new(move |buffer| {
|
|
processed_audio_
|
|
.lock()
|
|
.unwrap()
|
|
.extend_from_slice((*buffer).as_ref());
|
|
let _ = sender.lock().unwrap().send(());
|
|
}));
|
|
|
|
let this = Trusted::new(self);
|
|
let global = self.global();
|
|
let window = global.as_window();
|
|
let (task_source, canceller) = window
|
|
.task_manager()
|
|
.dom_manipulation_task_source_with_canceller();
|
|
Builder::new()
|
|
.name("OfflineACResolver".to_owned())
|
|
.spawn(move || {
|
|
let _ = receiver.recv();
|
|
let _ = task_source.queue_with_canceller(
|
|
task!(resolve: move || {
|
|
let this = this.root();
|
|
let processed_audio = processed_audio.lock().unwrap();
|
|
let mut processed_audio: Vec<_> = processed_audio
|
|
.chunks(this.length as usize)
|
|
.map(|channel| channel.to_vec())
|
|
.collect();
|
|
// it can end up being empty if the task failed
|
|
if processed_audio.len() != this.length as usize {
|
|
processed_audio.resize(this.length as usize, Vec::new())
|
|
}
|
|
let buffer = AudioBuffer::new(
|
|
&this.global().as_window(),
|
|
this.channel_count,
|
|
this.length,
|
|
*this.context.SampleRate(),
|
|
Some(processed_audio.as_slice()));
|
|
(*this.pending_rendering_promise.borrow_mut()).take().unwrap().resolve_native(&buffer);
|
|
let global = &this.global();
|
|
let window = global.as_window();
|
|
let event = OfflineAudioCompletionEvent::new(&window,
|
|
atom!("complete"),
|
|
EventBubbles::DoesNotBubble,
|
|
EventCancelable::NotCancelable,
|
|
&buffer);
|
|
event.upcast::<Event>().fire(this.upcast());
|
|
}),
|
|
&canceller,
|
|
);
|
|
})
|
|
.unwrap();
|
|
|
|
if self
|
|
.context
|
|
.audio_context_impl()
|
|
.lock()
|
|
.unwrap()
|
|
.resume()
|
|
.is_err()
|
|
{
|
|
promise.reject_error(Error::Type("Could not start offline rendering".to_owned()));
|
|
}
|
|
|
|
promise
|
|
}
|
|
}
|