OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2010, Google Inc. All rights reserved. | 2 * Copyright (C) 2010, Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
119 | 119 |
120 AudioNodeOutput* AudioNode::output(unsigned i) | 120 AudioNodeOutput* AudioNode::output(unsigned i) |
121 { | 121 { |
122 if (i < m_outputs.size()) | 122 if (i < m_outputs.size()) |
123 return m_outputs[i].get(); | 123 return m_outputs[i].get(); |
124 return 0; | 124 return 0; |
125 } | 125 } |
126 | 126 |
127 void AudioNode::connect(AudioNode* destination, unsigned outputIndex, unsigned i
nputIndex, ExceptionState& es) | 127 void AudioNode::connect(AudioNode* destination, unsigned outputIndex, unsigned i
nputIndex, ExceptionState& es) |
128 { | 128 { |
129 ASSERT(isMainThread()); | 129 ASSERT(isMainThread()); |
130 AudioContext::AutoLocker locker(context()); | 130 AudioContext::AutoLocker locker(context()); |
131 | 131 |
132 if (!destination) { | 132 if (!destination) { |
133 es.throwDOMException(SyntaxError); | 133 es.throwDOMException(SyntaxError); |
134 return; | 134 return; |
135 } | 135 } |
136 | 136 |
137 // Sanity check input and output indices. | 137 // Sanity check input and output indices. |
138 if (outputIndex >= numberOfOutputs()) { | 138 if (outputIndex >= numberOfOutputs()) { |
139 es.throwDOMException(IndexSizeError); | 139 es.throwDOMException(IndexSizeError); |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
335 } | 335 } |
336 | 336 |
337 bool AudioNode::propagatesSilence() const | 337 bool AudioNode::propagatesSilence() const |
338 { | 338 { |
339 return m_lastNonSilentTime + latencyTime() + tailTime() < context()->current
Time(); | 339 return m_lastNonSilentTime + latencyTime() + tailTime() < context()->current
Time(); |
340 } | 340 } |
341 | 341 |
342 void AudioNode::pullInputs(size_t framesToProcess) | 342 void AudioNode::pullInputs(size_t framesToProcess) |
343 { | 343 { |
344 ASSERT(context()->isAudioThread()); | 344 ASSERT(context()->isAudioThread()); |
345 | 345 |
346 // Process all of the AudioNodes connected to our inputs. | 346 // Process all of the AudioNodes connected to our inputs. |
347 for (unsigned i = 0; i < m_inputs.size(); ++i) | 347 for (unsigned i = 0; i < m_inputs.size(); ++i) |
348 input(i)->pull(0, framesToProcess); | 348 input(i)->pull(0, framesToProcess); |
349 } | 349 } |
350 | 350 |
351 bool AudioNode::inputsAreSilent() | 351 bool AudioNode::inputsAreSilent() |
352 { | 352 { |
353 for (unsigned i = 0; i < m_inputs.size(); ++i) { | 353 for (unsigned i = 0; i < m_inputs.size(); ++i) { |
354 if (!input(i)->bus()->isSilent()) | 354 if (!input(i)->bus()->isSilent()) |
355 return false; | 355 return false; |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
430 if (refType == RefTypeConnection) | 430 if (refType == RefTypeConnection) |
431 enableOutputsIfNecessary(); | 431 enableOutputsIfNecessary(); |
432 } | 432 } |
433 | 433 |
434 void AudioNode::deref(RefType refType) | 434 void AudioNode::deref(RefType refType) |
435 { | 435 { |
436 // The actually work for deref happens completely within the audio context's
graph lock. | 436 // The actually work for deref happens completely within the audio context's
graph lock. |
437 // In the case of the audio thread, we must use a tryLock to avoid glitches. | 437 // In the case of the audio thread, we must use a tryLock to avoid glitches. |
438 bool hasLock = false; | 438 bool hasLock = false; |
439 bool mustReleaseLock = false; | 439 bool mustReleaseLock = false; |
440 | 440 |
441 if (context()->isAudioThread()) { | 441 if (context()->isAudioThread()) { |
442 // Real-time audio thread must not contend lock (to avoid glitches). | 442 // Real-time audio thread must not contend lock (to avoid glitches). |
443 hasLock = context()->tryLock(mustReleaseLock); | 443 hasLock = context()->tryLock(mustReleaseLock); |
444 } else { | 444 } else { |
445 context()->lock(mustReleaseLock); | 445 context()->lock(mustReleaseLock); |
446 hasLock = true; | 446 hasLock = true; |
447 } | 447 } |
448 | 448 |
449 if (hasLock) { | 449 if (hasLock) { |
450 // This is where the real deref work happens. | 450 // This is where the real deref work happens. |
451 finishDeref(refType); | 451 finishDeref(refType); |
452 | 452 |
453 if (mustReleaseLock) | 453 if (mustReleaseLock) |
454 context()->unlock(); | 454 context()->unlock(); |
455 } else { | 455 } else { |
456 // We were unable to get the lock, so put this in a list to finish up la
ter. | 456 // We were unable to get the lock, so put this in a list to finish up la
ter. |
457 ASSERT(context()->isAudioThread()); | 457 ASSERT(context()->isAudioThread()); |
458 ASSERT(refType == RefTypeConnection); | 458 ASSERT(refType == RefTypeConnection); |
459 context()->addDeferredFinishDeref(this); | 459 context()->addDeferredFinishDeref(this); |
460 } | 460 } |
461 | 461 |
462 // Once AudioContext::uninitialize() is called there's no more chances for d
eleteMarkedNodes() to get called, so we call here. | 462 // Once AudioContext::uninitialize() is called there's no more chances for d
eleteMarkedNodes() to get called, so we call here. |
463 // We can't call in AudioContext::~AudioContext() since it will never be cal
led as long as any AudioNode is alive | 463 // We can't call in AudioContext::~AudioContext() since it will never be cal
led as long as any AudioNode is alive |
464 // because AudioNodes keep a reference to the context. | 464 // because AudioNodes keep a reference to the context. |
465 if (context()->isAudioThreadFinished()) | 465 if (context()->isAudioThreadFinished()) |
466 context()->deleteMarkedNodes(); | 466 context()->deleteMarkedNodes(); |
467 } | 467 } |
468 | 468 |
469 void AudioNode::finishDeref(RefType refType) | 469 void AudioNode::finishDeref(RefType refType) |
470 { | 470 { |
471 ASSERT(context()->isGraphOwner()); | 471 ASSERT(context()->isGraphOwner()); |
472 | 472 |
473 switch (refType) { | 473 switch (refType) { |
474 case RefTypeNormal: | 474 case RefTypeNormal: |
475 ASSERT(m_normalRefCount > 0); | 475 ASSERT(m_normalRefCount > 0); |
476 atomicDecrement(&m_normalRefCount); | 476 atomicDecrement(&m_normalRefCount); |
477 break; | 477 break; |
478 case RefTypeConnection: | 478 case RefTypeConnection: |
479 ASSERT(m_connectionRefCount > 0); | 479 ASSERT(m_connectionRefCount > 0); |
480 atomicDecrement(&m_connectionRefCount); | 480 atomicDecrement(&m_connectionRefCount); |
481 break; | 481 break; |
482 default: | 482 default: |
483 ASSERT_NOT_REACHED(); | 483 ASSERT_NOT_REACHED(); |
484 } | 484 } |
485 | 485 |
486 #if DEBUG_AUDIONODE_REFERENCES | 486 #if DEBUG_AUDIONODE_REFERENCES |
487 fprintf(stderr, "%p: %d: AudioNode::deref(%d) %d %d\n", this, nodeType(), re
fType, m_normalRefCount, m_connectionRefCount); | 487 fprintf(stderr, "%p: %d: AudioNode::deref(%d) %d %d\n", this, nodeType(), re
fType, m_normalRefCount, m_connectionRefCount); |
488 #endif | 488 #endif |
489 | 489 |
490 if (!m_connectionRefCount) { | 490 if (!m_connectionRefCount) { |
491 if (!m_normalRefCount) { | 491 if (!m_normalRefCount) { |
492 if (!m_isMarkedForDeletion) { | 492 if (!m_isMarkedForDeletion) { |
493 // All references are gone - we need to go away. | 493 // All references are gone - we need to go away. |
494 for (unsigned i = 0; i < m_outputs.size(); ++i) | 494 for (unsigned i = 0; i < m_outputs.size(); ++i) |
495 output(i)->disconnectAll(); // This will deref() nodes we're
connected to. | 495 output(i)->disconnectAll(); // This will deref() nodes we're
connected to. |
(...skipping 23 matching lines...) Expand all Loading... |
519 fprintf(stderr, "%d: %d\n", i, s_nodeCount[i]); | 519 fprintf(stderr, "%d: %d\n", i, s_nodeCount[i]); |
520 | 520 |
521 fprintf(stderr, "===========================\n\n\n"); | 521 fprintf(stderr, "===========================\n\n\n"); |
522 } | 522 } |
523 | 523 |
524 #endif // DEBUG_AUDIONODE_REFERENCES | 524 #endif // DEBUG_AUDIONODE_REFERENCES |
525 | 525 |
526 } // namespace WebCore | 526 } // namespace WebCore |
527 | 527 |
528 #endif // ENABLE(WEB_AUDIO) | 528 #endif // ENABLE(WEB_AUDIO) |
OLD | NEW |