sbMainThreadMetadataProcessor.cpp
Go to the documentation of this file.
1 /* vim: set sw=2 :miv */
2 /*
3 //
4 // BEGIN SONGBIRD GPL
5 //
6 // This file is part of the Songbird web player.
7 //
8 // Copyright(c) 2005-2008 POTI, Inc.
9 // http://songbirdnest.com
10 //
11 // This file may be licensed under the terms of of the
12 // GNU General Public License Version 2 (the "GPL").
13 //
14 // Software distributed under the License is distributed
15 // on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
16 // express or implied. See the GPL for the specific language
17 // governing rights and limitations.
18 //
19 // You should have received a copy of the GPL along with this
20 // program. If not, go to http://www.gnu.org/licenses/gpl.html
21 // or write to the Free Software Foundation, Inc.,
22 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 //
24 // END SONGBIRD GPL
25 //
26 */
27 
33 // INCLUDES ===================================================================
34 #include <nspr.h>
35 #include <nscore.h>
36 #include <nsThreadUtils.h>
37 #include <nsComponentManagerUtils.h>
38 
40 #include "sbFileMetadataService.h"
41 #include "sbMetadataJobItem.h"
42 
43 #include "prlog.h"
44 
45 // DEFINES ====================================================================
46 
47 // TODO tweak me
48 #define TIMER_PERIOD 33
49 #define NUM_ACTIVE_HANDLERS 15
50 
51 #ifdef PR_LOGGING
52 extern PRLogModuleInfo* gMetadataLog;
53 #define TRACE(args) PR_LOG(gMetadataLog, PR_LOG_DEBUG, args)
54 #define LOG(args) PR_LOG(gMetadataLog, PR_LOG_WARN, args)
55 #else
56 #define TRACE(args) /* nothing */
57 #define LOG(args) /* nothing */
58 #endif
59 
60 // GLOBALS ====================================================================
61 // CLASSES ====================================================================
62 
64 
66  sbFileMetadataService* aManager) :
67  mJobManager(aManager),
68  mTimer(nsnull),
69  mRunning(PR_FALSE)
70 {
71  MOZ_COUNT_CTOR(sbMainThreadMetadataProcessor);
72  TRACE(("sbMainThreadMetadataProcessor[0x%.8x] - ctor", this));
73  NS_ASSERTION(NS_IsMainThread(), "sbMainThreadMetadataProcessor called off the main thread");
74 }
75 
77 {
78  MOZ_COUNT_DTOR(sbMainThreadMetadataProcessor);
79  TRACE(("sbMainThreadMetadataProcessor[0x%.8x] - dtor", this));
80  Stop();
81  mTimer = nsnull;
82  mJobManager= nsnull;
83 }
84 
86 {
87  NS_ENSURE_STATE(mJobManager);
88  NS_ASSERTION(NS_IsMainThread(), "sbMainThreadMetadataProcessor called off the main thread!");
89  TRACE(("sbMainThreadMetadataProcessor[0x%.8x] - Start", this));
90  nsresult rv;
91 
92  if (!mTimer) {
93  mTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
94  NS_ENSURE_SUCCESS(rv, rv);
95 
97  }
98 
99  if (!mRunning) {
100  rv = mTimer->InitWithCallback(this,
101  TIMER_PERIOD,
102  nsITimer::TYPE_REPEATING_SLACK);
103  NS_ENSURE_SUCCESS(rv, rv);
104 
105  mRunning = PR_TRUE;
106 
107  // Run the timer method right away so we don't waste any time
108  // before starting the handlers (would otherwise wait
109  // TIMER_PERIOD before even starting)
110  Notify(nsnull);
111  }
112 
113  return NS_OK;
114 }
115 
117 {
118  NS_ASSERTION(NS_IsMainThread(), "sbMainThreadMetadataProcessor called off the main thread");
119  TRACE(("sbMainThreadMetadataProcessor[0x%.8x] - Stop", this));
120  nsresult rv;
121 
122  if (mTimer) {
123  mTimer->Cancel();
124  }
125 
126  mRunning = PR_FALSE;
127 
128  // Kill any active handlers
129  for (PRUint32 i=0; i < NUM_ACTIVE_HANDLERS; i++) {
130  if (mCurrentJobItems[i] != nsnull) {
131  nsRefPtr<sbMetadataJobItem> item = mCurrentJobItems[i];
132 
133  nsCOMPtr<sbIMetadataHandler> handler;
134  rv = item->GetHandler(getter_AddRefs(handler));
135  NS_ENSURE_SUCCESS(rv, rv);
136 
137  mCurrentJobItems[i] = nsnull;
138  handler->Close();
139 
140  // Give back the processed job item
141  mJobManager->PutProcessedJobItem(item);
142  }
143  }
144 
145  return NS_OK;
146 }
147 
148 
152 NS_IMETHODIMP sbMainThreadMetadataProcessor::Notify(nsITimer* aTimer)
153 {
154  TRACE(("sbMainThreadMetadataProcessor[0x%.8x] - Notify", this));
155  nsresult rv;
156 
157  PRBool finished = PR_TRUE;
158 
159  // Check on the state of our active job items.
160  // Handle completed items and replace with new items.
161  for (PRUint32 i=0; i < NUM_ACTIVE_HANDLERS; i++) {
162  nsRefPtr<sbMetadataJobItem> item = mCurrentJobItems[i];
163 
164  // If this is an active item, check to see if it has completed
165  // URGH, sbIMetadataHandler needs a callback!
166  if (item) {
167  // Check to see if it has completed
168  nsCOMPtr<sbIMetadataHandler> handler;
169  rv = item->GetHandler(getter_AddRefs(handler));
170  NS_ENSURE_SUCCESS(rv, rv);
171  PRBool handlerCompleted;
172  rv = handler->GetCompleted(&handlerCompleted);
173  NS_ENSURE_SUCCESS(rv, rv);
174 
175  if (handlerCompleted) {
176  // NULL the array entry
177  mCurrentJobItems[i] = nsnull;
178 
179  // Indicate that we processed this item
180  item->SetProcessed(PR_TRUE);
181 
182  // Give back the processed job item
183  mJobManager->PutProcessedJobItem(item);
184  item = nsnull;
185  } else {
186  // Still processing. We aren't ready to shut the timer down.
187  finished = PR_FALSE;
188  }
189  }
190 
191  // If this is an empty slot, get a new job item
192  if (!item) {
193  // Get the next job item
194  rv = mJobManager->GetQueuedJobItem(PR_TRUE, getter_AddRefs(item));
195  // If there are no more job items available, we may need to shut down soon
196  if (rv == NS_ERROR_NOT_AVAILABLE) {
197  continue;
198  }
199  NS_ENSURE_SUCCESS(rv, rv);
200 
201  // And stuff it in our working array to check next loop
202  mCurrentJobItems[i] = item;
203 
204  // Still processing. We aren't ready to shut the timer down.
205  finished = PR_FALSE;
206  }
207 
208  // If item processing hasn't started, start a new handler
209  if (item) {
210  PRBool processingStarted;
211  rv = item->GetProcessingStarted(&processingStarted);
212  NS_ENSURE_SUCCESS(rv, rv);
213  if (!processingStarted) {
214  // Get the job owning the job item.
215  nsRefPtr<sbMetadataJob> job;
216  rv = item->GetOwningJob(getter_AddRefs(job));
217  NS_ENSURE_SUCCESS(rv, rv);
218 
219  // Don't start processing until the job item is not blocked.
220  PRBool jobItemIsBlocked;
221  rv = mJobManager->GetJobItemIsBlocked(item, &jobItemIsBlocked);
222  NS_ENSURE_SUCCESS(rv, rv);
223  if (jobItemIsBlocked) {
224  // Set the job as blocked.
225  rv = job->SetBlocked(PR_TRUE);
226  NS_ENSURE_SUCCESS(rv, rv);
227 
228  // Still processing. We aren't ready to shut the timer down.
229  finished = PR_FALSE;
230  continue;
231  }
232 
233  // Set the job as not blocked.
234  rv = job->SetBlocked(PR_FALSE);
235  NS_ENSURE_SUCCESS(rv, rv);
236 
237  // Start the metadata handler for this job item.
238 
239  nsCOMPtr<sbIMetadataHandler> handler;
240  rv = item->GetHandler(getter_AddRefs(handler));
241  NS_ENSURE_SUCCESS(rv, rv);
242 
243  sbMetadataJob::JobType jobType;
244  rv = item->GetJobType(&jobType);
245  NS_ENSURE_SUCCESS(rv, rv);
246 
247  // We don't care if it is async... we're polling no matter what.
248  PRBool async = PR_FALSE;
249  if (jobType == sbMetadataJob::TYPE_WRITE) {
250  rv = handler->Write(&async);
251  }
252  else {
253  rv = handler->Read(&async);
254  }
255 
256  // If failed, give back to the job
257  if (NS_FAILED(rv)) {
258  // must push back immediately
259  mJobManager->PutProcessedJobItem(item);
260  mCurrentJobItems[i] = nsnull;
261  }
262  else {
263  // Still processing. We aren't ready to shut the timer down.
264  rv = item->SetProcessingStarted(PR_TRUE);
265  NS_ENSURE_SUCCESS(rv, rv);
266  finished = PR_FALSE;
267  }
268  }
269  }
270  } // end mCurrentJobItems for loop
271 
272  // If there are not more active job items, then we can
273  // safely shut down
274  if (finished) {
275  Stop();
276  }
277 
278  return NS_OK;
279 }
280 
NS_IMPL_THREADSAFE_ISUPPORTS1(sbMainThreadMetadataProcessor, nsITimerCallback)
return NS_OK
nsRefPtr< sbFileMetadataService > mJobManager
#define TRACE(args)
#define NUM_ACTIVE_HANDLERS
#define TIMER_PERIOD
nsTArray< nsRefPtr< sbMetadataJobItem > > mCurrentJobItems
var finished
Manages reading and writing metadata to and from sbIMediaItem objects and media files.
Runs sbIMetadataHandlers with a timer on the main thread.
A metadata job task.
_getSelectedPageStyle s i
NS_DECL_ISUPPORTS NS_DECL_NSITIMERCALLBACK sbMainThreadMetadataProcessor(sbFileMetadataService *aManager)
GstMessage gpointer data sbGStreamerMessageHandler * handler
nsITimerCallback
Coordinates reading and writing of media file metadata.