sbTranscodeProgressListener.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-2009 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 */
28 
29 // Mozilla includes
30 #include <nsIWritablePropertyBag2.h>
31 
32 // Songbird includes
33 #include <sbIJobCancelable.h>
34 #include <sbIJobProgress.h>
35 #include <sbIDeviceEvent.h>
36 #include <sbIMediacoreEventListener.h>
37 #include <sbIMediacoreEvent.h>
38 #include <sbIMediacoreError.h>
39 #include <sbITranscodeError.h>
40 #include <sbStandardProperties.h>
41 #include <sbStatusPropertyValue.h>
42 #include <sbTranscodeUtils.h>
43 #include <sbVariantUtils.h>
44 // Local includes
45 #include "sbDeviceStatusHelper.h"
46 
50 
52 sbTranscodeProgressListener::New(sbBaseDevice * aDeviceBase,
53  sbDeviceStatusHelper * aDeviceStatusHelper,
54  sbIMediaItem *aItem,
55  PRMonitor * aCompleteNotifyMonitor,
56  StatusProperty const & aStatusProperty,
57  sbIJobCancelable * aCancel) {
58  return new sbTranscodeProgressListener(aDeviceBase,
59  aDeviceStatusHelper,
60  aItem,
61  aCompleteNotifyMonitor,
62  aStatusProperty,
63  aCancel);
64 }
65 
66 sbTranscodeProgressListener::sbTranscodeProgressListener(
67  sbBaseDevice * aDeviceBase,
68  sbDeviceStatusHelper * aDeviceStatusHelper,
69  sbIMediaItem *aItem,
70  PRMonitor * aCompleteNotifyMonitor,
71  StatusProperty const & aStatusProperty,
72  sbIJobCancelable * aCancel) :
73  mBaseDevice(aDeviceBase),
74  mStatus(aDeviceStatusHelper),
75  mItem(aItem),
76  mCompleteNotifyMonitor(aCompleteNotifyMonitor),
77  mIsComplete(0),
78  mTotal(0),
79  mStatusProperty(aStatusProperty),
80  mCancel(aCancel),
81  mAborted(PR_FALSE) {
82 
83  NS_ASSERTION(mBaseDevice,
84  "sbTranscodeProgressListener mBaseDevice can't be null");
85  NS_ASSERTION(mStatus,
86  "sbTranscodeProgressListener mStatus can't be null");
87  NS_ASSERTION(mItem,
88  "sbTranscodeProgressListener mItem can't be null");
89  NS_ASSERTION(mCompleteNotifyMonitor,
90  "sbTranscodeProgressListener mCompleteNotifyMonitor "
91  "can't be null");
92 
93  NS_IF_ADDREF(static_cast<sbIDevice*>(mBaseDevice));
94 }
95 
96 sbTranscodeProgressListener::~sbTranscodeProgressListener() {
97  sbIDevice * disambiguate = mBaseDevice;
98  NS_IF_RELEASE(disambiguate);
99 }
100 
101 nsresult
102 sbTranscodeProgressListener::Completed(sbIJobProgress * aJobProgress) {
103  nsresult rv;
104 
105  // Indicate that the transcode operation is complete. If a complete notify
106  // monitor was provided, operate under the monitor and send completion
107  // notification.
108  if (mCompleteNotifyMonitor) {
109  nsAutoMonitor monitor(mCompleteNotifyMonitor);
110  PR_AtomicSet(&mIsComplete, 1);
111  monitor.Notify();
112  } else {
113  PR_AtomicSet(&mIsComplete, 1);
114  }
115 
116  // Disconnect us now that we're done.
117  // This should be where we die as well, as this will be the last reference
118  rv = aJobProgress->RemoveJobProgressListener(this);
119  NS_ENSURE_SUCCESS(rv, rv);
120 
121  mCancel = nsnull;
122 
123  return NS_OK;
124 }
125 
126 nsresult
127 sbTranscodeProgressListener::SetProgress(sbIJobProgress * aJobProgress) {
128  nsresult rv;
129 
130  NS_ENSURE_ARG_POINTER(aJobProgress);
131 
132  if (!mTotal) {
133  rv = aJobProgress->GetTotal(&mTotal);
134  NS_ENSURE_SUCCESS(rv, rv);
135  }
136 
137  PRUint32 progress;
138  rv = aJobProgress->GetProgress(&progress);
139  NS_ENSURE_SUCCESS(rv, rv);
140 
141  double percentComplete = 0.0;
142  if (mTotal > 0) {
143  percentComplete = static_cast<double>(progress) /
144  static_cast<double>(mTotal);
145  }
146  mStatus->ItemProgress(percentComplete);
147 
149  double const complete = percentComplete * 100.0;
151  value.SetCurrent((PRUint32)complete);
152  SetStatusProperty(value);
153 
154  return NS_OK;
155 }
156 
157 NS_IMETHODIMP
158 sbTranscodeProgressListener::OnJobProgress(sbIJobProgress *aJobProgress)
159 {
160  NS_ENSURE_ARG_POINTER(aJobProgress);
161 
162  // Cancel job if it needs to be aborted. Continue processing OnJobProgress
163  // calls while the cancel operation is performed. Make sure cancel is only
164  // called once. Calling cancel can result in a reentrant call to
165  // OnJobProgress.
166  if (!mAborted &&
167  mCancel &&
168  mBaseDevice->IsRequestAborted()) {
169  mAborted = PR_TRUE;
170  nsCOMPtr<sbIJobCancelable> cancel = mCancel;
171  mCancel = nsnull;
172  cancel->Cancel();
173 
174  nsresult rv;
177  rv = SetStatusProperty(value);
178  NS_ENSURE_SUCCESS(rv, rv);
179 
180  rv = Completed(aJobProgress);
181  NS_ENSURE_SUCCESS(rv, rv);
182  return NS_OK;
183  }
184 
185  PRUint16 status;
186  nsresult rv = aJobProgress->GetStatus(&status);
187  NS_ENSURE_SUCCESS(rv, rv);
188  switch (status) {
192  SetStatusProperty(value);
193 
194  rv = Completed(aJobProgress);
195  NS_ENSURE_SUCCESS(rv, rv);
196  }
197  break;
198 
202  SetStatusProperty(value);
203 
204  rv = Completed(aJobProgress);
205  NS_ENSURE_SUCCESS(rv, rv);
206  }
207  break;
208 
210  rv = SetProgress(aJobProgress);
211  NS_ENSURE_SUCCESS(rv, rv);
212  }
213  break;
214 
215  default: {
216  NS_WARNING("Unexpected progress state in "
217  "sbTranscodeProgressListener::OnJobProgress");
218  }
219  break;
220  }
221 
222  return NS_OK;
223 }
224 
225 inline nsresult
226 sbTranscodeProgressListener::SetStatusProperty(
228 {
229  nsresult rv = mStatusProperty.SetValue(aValue.GetValue());
230  NS_ENSURE_SUCCESS(rv, rv);
231 
232  return NS_OK;
233 }
234 
235 NS_IMETHODIMP
236 sbTranscodeProgressListener::OnMediacoreEvent(sbIMediacoreEvent *aEvent)
237 {
238  NS_ENSURE_STATE(mItem);
239  NS_ENSURE_ARG_POINTER(aEvent);
240 
241  nsresult rv;
242  PRUint32 type;
243 
244  rv = aEvent->GetType(&type);
245  NS_ENSURE_SUCCESS(rv, rv);
246 
247  if (type == sbIMediacoreEvent::ERROR_EVENT) {
248  nsCOMPtr<sbIMediacoreError> error;
249  rv = aEvent->GetError(getter_AddRefs(error));
250  NS_ENSURE_SUCCESS(rv, rv);
251 
252  // Dispatch the device event
253  nsCOMPtr<nsIWritablePropertyBag2> bag =
254  do_CreateInstance("@songbirdnest.com/moz/xpcom/sbpropertybag;1", &rv);
255  NS_ENSURE_SUCCESS(rv, rv);
256 
257  nsString message;
258  rv = error->GetMessage(message);
259  if (NS_SUCCEEDED(rv)) {
260  rv = bag->SetPropertyAsAString(NS_LITERAL_STRING("message"),
261  message);
262  NS_ENSURE_SUCCESS(rv, rv);
263  }
264  rv = bag->SetPropertyAsInterface(NS_LITERAL_STRING("mediacore-error"),
265  NS_ISUPPORTS_CAST(sbIMediacoreError*, error));
266  NS_ENSURE_SUCCESS(rv, rv);
267 
268  nsString srcUri;
269  rv = mItem->GetProperty(NS_LITERAL_STRING(SB_PROPERTY_CONTENTURL), srcUri);
270  if (NS_SUCCEEDED(rv)) {
271  nsCOMPtr<sbITranscodeError> transcodeError;
272  rv = SB_NewTranscodeError(message, message, SBVoidString(),
273  srcUri,
274  nsnull,
275  getter_AddRefs(transcodeError));
276  NS_ENSURE_SUCCESS(rv, rv);
277  rv = transcodeError->SetDestItem(mItem);
278  NS_ENSURE_SUCCESS(rv, rv);
279  rv = bag->SetPropertyAsInterface(NS_LITERAL_STRING("transcode-error"),
280  NS_ISUPPORTS_CAST(sbITranscodeError*, transcodeError));
281  NS_ENSURE_SUCCESS(rv, rv);
282  }
283 
284  mBaseDevice->CreateAndDispatchEvent(
286  sbNewVariant(bag));
287  }
288 
289  return NS_OK;
290 }
291 
nsresult CreateAndDispatchEvent(PRUint32 aType, nsIVariant *aData, PRBool aAsync=PR_TRUE, sbIDeviceEventTarget *aTarget=nsnull)
return NS_OK
onPageChanged aValue
Definition: FeedWriter.js:1395
nsresult SB_NewTranscodeError(const nsAString &aMessageWithItem, const nsAString &aMessageWithoutItem, const nsAString &aDetails, const nsAString &aUri, sbIMediaItem *aMediaItem, sbITranscodeError **_retval)
Generic interface for exposing long running jobs to the UI.
NS_IMPL_THREADSAFE_ISUPPORTS2(sbTranscodeProgressListener, sbIJobProgressListener, sbIMediacoreEventListener) sbTranscodeProgressListener *sbTranscodeProgressListener
const unsigned long ERROR_EVENT
Indicates the event is an error and will have its error member set.
const unsigned short STATUS_SUCCEEDED
Constant indicating that the job has completed.
Songbird Variant Utility Definitions.
virtual PRBool IsRequestAborted()
const unsigned short STATUS_RUNNING
Constant indicating that the job is active.
Definition of the sbIMediacoreEvent interface.
const unsigned long EVENT_DEVICE_TRANSCODE_ERROR
GstMessage * message
void ItemProgress(double aProgress)
countRef value
Definition: FeedWriter.js:1423
Songbird Device Status Services Definitions.
Implemented to receive notifications from sbIJobProgress interfaces.
void SetCurrent(PRUint32 aCurrent)
Interface that defines a single item of media in the system.
#define SB_PROPERTY_CONTENTURL
const unsigned short STATUS_FAILED
Constant indicating that the job has completed with errors.