Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(48)

Side by Side Diff: Source/modules/webaudio/AudioContext.cpp

Issue 1140723003: Implement suspend() and resume() for OfflineAudioContext (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Initial review + layout tests Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
92 } 92 }
93 93
94 AudioContext* audioContext = new AudioContext(&document); 94 AudioContext* audioContext = new AudioContext(&document);
95 audioContext->suspendIfNeeded(); 95 audioContext->suspendIfNeeded();
96 return audioContext; 96 return audioContext;
97 } 97 }
98 98
99 // Constructor for rendering to the audio hardware. 99 // Constructor for rendering to the audio hardware.
100 AudioContext::AudioContext(Document* document) 100 AudioContext::AudioContext(Document* document)
101 : ActiveDOMObject(document) 101 : ActiveDOMObject(document)
102 , m_didInitializeContextGraphMutex(false)
103 , m_isOfflineContext(false)
104 , m_destinationNode(nullptr)
102 , m_isStopScheduled(false) 105 , m_isStopScheduled(false)
103 , m_isCleared(false) 106 , m_isCleared(false)
104 , m_isInitialized(false) 107 , m_isInitialized(false)
105 , m_destinationNode(nullptr)
106 , m_isResolvingResumePromises(false) 108 , m_isResolvingResumePromises(false)
107 , m_connectionCount(0) 109 , m_connectionCount(0)
108 , m_didInitializeContextGraphMutex(false)
109 , m_deferredTaskHandler(DeferredTaskHandler::create()) 110 , m_deferredTaskHandler(DeferredTaskHandler::create())
110 , m_isOfflineContext(false)
111 , m_contextState(Suspended) 111 , m_contextState(Suspended)
112 { 112 {
113 m_didInitializeContextGraphMutex = true; 113 m_didInitializeContextGraphMutex = true;
114 m_destinationNode = DefaultAudioDestinationNode::create(this); 114 m_destinationNode = DefaultAudioDestinationNode::create(this);
115 115
116 initialize(); 116 initialize();
117 } 117 }
118 118
119 // Constructor for offline (non-realtime) rendering. 119 // Constructor for offline (non-realtime) rendering.
120 AudioContext::AudioContext(Document* document, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate) 120 AudioContext::AudioContext(Document* document, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate)
121 : ActiveDOMObject(document) 121 : ActiveDOMObject(document)
122 , m_didInitializeContextGraphMutex(false)
123 , m_isOfflineContext(true)
124 , m_destinationNode(nullptr)
122 , m_isStopScheduled(false) 125 , m_isStopScheduled(false)
123 , m_isCleared(false) 126 , m_isCleared(false)
124 , m_isInitialized(false) 127 , m_isInitialized(false)
125 , m_destinationNode(nullptr)
126 , m_isResolvingResumePromises(false) 128 , m_isResolvingResumePromises(false)
127 , m_connectionCount(0) 129 , m_connectionCount(0)
128 , m_didInitializeContextGraphMutex(false)
129 , m_deferredTaskHandler(DeferredTaskHandler::create()) 130 , m_deferredTaskHandler(DeferredTaskHandler::create())
130 , m_isOfflineContext(true)
131 , m_contextState(Suspended) 131 , m_contextState(Suspended)
132 { 132 {
133 m_didInitializeContextGraphMutex = true; 133 m_didInitializeContextGraphMutex = true;
134
134 // Create a new destination for offline rendering. 135 // Create a new destination for offline rendering.
135 m_renderTarget = AudioBuffer::create(numberOfChannels, numberOfFrames, sampl eRate); 136 m_renderTarget = AudioBuffer::create(numberOfChannels, numberOfFrames, sampl eRate);
136 if (m_renderTarget.get()) 137 if (m_renderTarget.get())
137 m_destinationNode = OfflineAudioDestinationNode::create(this, m_renderTa rget.get()); 138 m_destinationNode = OfflineAudioDestinationNode::create(this, m_renderTa rget.get());
138 139
139 initialize(); 140 initialize();
140 } 141 }
141 142
142 AudioContext::~AudioContext() 143 AudioContext::~AudioContext()
143 { 144 {
(...skipping 567 matching lines...) Expand 10 before | Expand all | Expand 10 after
711 } 712 }
712 713
713 if (newState == m_contextState) { 714 if (newState == m_contextState) {
714 // ASSERTs above failed; just return. 715 // ASSERTs above failed; just return.
715 return; 716 return;
716 } 717 }
717 718
718 m_contextState = newState; 719 m_contextState = newState;
719 720
720 // Notify context that state changed 721 // Notify context that state changed
721 if (executionContext()) 722 if (executionContext()) {
722 executionContext()->postTask(FROM_HERE, createSameThreadTask(&AudioConte xt::notifyStateChange, this)); 723 executionContext()->postTask(FROM_HERE,
724 createSameThreadTask(&AudioContext::notifyStateChange, this));
725 }
Raymond Toy 2015/05/28 16:37:35 This change isn't really necessary, is it?
hongchan 2015/06/09 20:49:59 No, I am reverting this in PS6.
723 } 726 }
724 727
725 void AudioContext::notifyStateChange() 728 void AudioContext::notifyStateChange()
726 { 729 {
727 dispatchEvent(Event::create(EventTypeNames::statechange)); 730 dispatchEvent(Event::create(EventTypeNames::statechange));
728 } 731 }
729 732
730 ScriptPromise AudioContext::suspendContext(ScriptState* scriptState) 733 ScriptPromise AudioContext::suspendContext(ScriptState* scriptState)
731 { 734 {
732 ASSERT(isMainThread()); 735 ASSERT(isMainThread());
736 ASSERT(!isOfflineContext());
737
733 AutoLocker locker(this); 738 AutoLocker locker(this);
734 739
735 if (isOfflineContext()) {
736 return ScriptPromise::rejectWithDOMException(
737 scriptState,
738 DOMException::create(
739 InvalidAccessError,
740 "cannot suspend an OfflineAudioContext"));
741 }
742
743 RefPtrWillBeRawPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver:: create(scriptState); 740 RefPtrWillBeRawPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver:: create(scriptState);
744 ScriptPromise promise = resolver->promise(); 741 ScriptPromise promise = resolver->promise();
745 742
746 if (m_contextState == Closed) { 743 if (m_contextState == Closed) {
747 resolver->reject( 744 resolver->reject(
748 DOMException::create(InvalidStateError, "Cannot suspend a context th at has been closed")); 745 DOMException::create(InvalidStateError, "Cannot suspend a context th at has been closed"));
749 } else { 746 } else {
750 // Stop rendering now. 747 // Stop rendering now.
751 if (m_destinationNode) 748 if (m_destinationNode)
752 stopRendering(); 749 stopRendering();
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
938 return EventTargetNames::AudioContext; 935 return EventTargetNames::AudioContext;
939 } 936 }
940 937
941 ExecutionContext* AudioContext::executionContext() const 938 ExecutionContext* AudioContext::executionContext() const
942 { 939 {
943 return m_isStopScheduled ? 0 : ActiveDOMObject::executionContext(); 940 return m_isStopScheduled ? 0 : ActiveDOMObject::executionContext();
944 } 941 }
945 942
946 void AudioContext::startRendering() 943 void AudioContext::startRendering()
947 { 944 {
948 // This is called for both online and offline contexts. 945 // This is only for the real-time context.
Raymond Toy 2015/05/28 16:37:35 Add assert for !isOfflineContext()?
hongchan 2015/06/09 20:49:59 Done.
949 ASSERT(isMainThread()); 946 ASSERT(isMainThread());
950 ASSERT(m_destinationNode); 947 ASSERT(m_destinationNode);
951 948
952 if (m_contextState == Suspended) { 949 if (m_contextState == Suspended) {
953 destination()->audioDestinationHandler().startRendering(); 950 destination()->audioDestinationHandler().startRendering();
954 setContextState(Running); 951 setContextState(Running);
955 } 952 }
956 } 953 }
957 954
958 void AudioContext::stopRendering() 955 void AudioContext::stopRendering()
959 { 956 {
960 ASSERT(isMainThread()); 957 ASSERT(isMainThread());
961 ASSERT(m_destinationNode); 958 ASSERT(m_destinationNode);
962 ASSERT(!isOfflineContext()); 959 ASSERT(!isOfflineContext());
963 960
964 if (m_contextState == Running) { 961 if (m_contextState == Running) {
965 destination()->audioDestinationHandler().stopRendering(); 962 destination()->audioDestinationHandler().stopRendering();
966 setContextState(Suspended); 963 setContextState(Suspended);
967 deferredTaskHandler().clearHandlersToBeDeleted(); 964 deferredTaskHandler().clearHandlersToBeDeleted();
968 } 965 }
969 } 966 }
970 967
968 bool AudioContext::shouldSuspendNow()
Raymond Toy 2015/05/28 16:37:35 Can't this be a method just on an OfflineAudioCont
hongchan 2015/06/09 20:49:58 The problem is OAC is a very thin wrapper for AC.
Raymond Toy 2015/06/09 22:34:59 Why not make context() be virtual? I don't know wh
969 {
970 ASSERT_WITH_MESSAGE(1, "shouldSuspendNow() only valid for offline audio cont ext");
971 return false;
972 }
973
971 void AudioContext::fireCompletionEvent() 974 void AudioContext::fireCompletionEvent()
Raymond Toy 2015/05/28 16:37:35 Could this be moved to the OfflineAudioContext cla
hongchan 2015/06/09 20:49:59 The same reason above.
972 { 975 {
973 ASSERT(isMainThread()); 976 ASSERT_WITH_MESSAGE(1, "fireCompletionEvent() only valid for offline audio c ontext");
974 if (!isMainThread())
975 return;
976
977 AudioBuffer* renderedBuffer = m_renderTarget.get();
978
979 // For an offline context, we set the state to closed here so that the oncom plete handler sees
980 // that the context has been closed.
981 setContextState(Closed);
982
983 ASSERT(renderedBuffer);
984 if (!renderedBuffer)
985 return;
986
987 // Avoid firing the event if the document has already gone away.
988 if (executionContext()) {
989 // Call the offline rendering completion event listener and resolve the promise too.
990 dispatchEvent(OfflineAudioCompletionEvent::create(renderedBuffer));
991 m_offlineResolver->resolve(renderedBuffer);
992 }
993 } 977 }
994 978
995 DEFINE_TRACE(AudioContext) 979 DEFINE_TRACE(AudioContext)
996 { 980 {
997 visitor->trace(m_closeResolver); 981 visitor->trace(m_closeResolver);
998 visitor->trace(m_offlineResolver);
999 visitor->trace(m_renderTarget); 982 visitor->trace(m_renderTarget);
1000 visitor->trace(m_destinationNode); 983 visitor->trace(m_destinationNode);
1001 visitor->trace(m_listener); 984 visitor->trace(m_listener);
1002 // trace() can be called in AudioContext constructor, and 985 // trace() can be called in AudioContext constructor, and
1003 // m_contextGraphMutex might be unavailable. 986 // m_contextGraphMutex might be unavailable.
1004 if (m_didInitializeContextGraphMutex) { 987 if (m_didInitializeContextGraphMutex) {
1005 AutoLocker lock(this); 988 AutoLocker lock(this);
1006 visitor->trace(m_activeSourceNodes); 989 visitor->trace(m_activeSourceNodes);
1007 } else { 990 } else {
1008 visitor->trace(m_activeSourceNodes); 991 visitor->trace(m_activeSourceNodes);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1045 // the destination node can GCed if JS has no references. stop() will also r esolve the Promise 1028 // the destination node can GCed if JS has no references. stop() will also r esolve the Promise
1046 // created here. 1029 // created here.
1047 stop(); 1030 stop();
1048 1031
1049 return promise; 1032 return promise;
1050 } 1033 }
1051 1034
1052 } // namespace blink 1035 } // namespace blink
1053 1036
1054 #endif // ENABLE(WEB_AUDIO) 1037 #endif // ENABLE(WEB_AUDIO)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698