| 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 |