sbRemoteNotificationManager.cpp
Go to the documentation of this file.
1 /*
2 //
3 // BEGIN SONGBIRD GPL
4 //
5 // This file is part of the Songbird web player.
6 //
7 // Copyright(c) 2005-2008 POTI, Inc.
8 // http://songbirdnest.com
9 //
10 // This file may be licensed under the terms of of the
11 // GNU General Public License Version 2 (the "GPL").
12 //
13 // Software distributed under the License is distributed
14 // on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
15 // express or implied. See the GPL for the specific language
16 // governing rights and limitations.
17 //
18 // You should have received a copy of the GPL along with this
19 // program. If not, go to http://www.gnu.org/licenses/gpl.html
20 // or write to the Free Software Foundation, Inc.,
21 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 //
23 // END SONGBIRD GPL
24 //
25  */
26 
28 
29 #include <nsIStringBundle.h>
30 #include <nsAutoPtr.h>
31 #include <nsServiceManagerUtils.h>
32 #include <nsComponentManagerUtils.h>
33 
34 #include <sbIDataRemote.h>
35 #include <sbILibrary.h>
36 #include <sbILibraryManager.h>
37 
38 #define SB_DATAREMOTE_FACEPLATE_STATUS \
39  NS_LITERAL_STRING("faceplate.status.override.text")
40 #define TIMER_RESOLUTION 500
41 #define MAX_NOTIFICATION_TIME 1 * PR_USEC_PER_SEC
42 
43 #define BUNDLE_URL "chrome://songbird/locale/songbird.properties"
44 
49 #ifdef PR_LOGGING
50 static PRLogModuleInfo* gRemoteNotificationManagerLog = nsnull;
51 #endif /* PR_LOGGING */
52 
53 #define TRACE(args) PR_LOG(gRemoteNotificationManagerLog, PR_LOG_DEBUG, args)
54 #define LOG(args) PR_LOG(gRemoteNotificationManagerLog, PR_LOG_WARN, args)
55 
57 
59  mCurrentActionType(eNone),
60  mCancelPending(PR_FALSE)
61 {
62 #ifdef PR_LOGGING
63  if (!gRemoteNotificationManagerLog) {
64  gRemoteNotificationManagerLog = PR_NewLogModule("sbRemoteNotificationManager");
65  }
66 #endif
67  TRACE(("sbRemoteNotificationManager[0x%.8x] - Constructed", this));
68 }
69 
71 {
72  TRACE(("sbRemoteNotificationManager[0x%.8x] - Destructed", this));
73 }
74 
75 nsresult
77 {
78  TRACE(("sbRemoteNotificationManager[0x%.8x] - Init", this));
79  nsresult rv;
80 
81  PRBool success = mPriorityList.SetLength(eEditedPlaylist + 1);
82  NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
83 
84  mDataRemote =
85  do_CreateInstance("@songbirdnest.com/Songbird/DataRemote;1", &rv);
86  NS_ENSURE_SUCCESS(rv, rv);
87 
88  rv = mDataRemote->Init(SB_DATAREMOTE_FACEPLATE_STATUS, EmptyString());
89  NS_ENSURE_SUCCESS(rv, rv);
90 
91  nsCOMPtr<nsIStringBundleService> stringBundleService =
92  do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
93  NS_ENSURE_SUCCESS(rv, rv);
94 
95  rv = stringBundleService->CreateBundle(BUNDLE_URL, getter_AddRefs(mBundle));
96  NS_ENSURE_SUCCESS(rv, rv);
97 
98  nsCOMPtr<sbILibraryManager> libManager =
99  do_GetService("@songbirdnest.com/Songbird/library/Manager;1", &rv);
100  NS_ENSURE_SUCCESS(rv, rv);
101 
102  rv = libManager->GetMainLibrary(getter_AddRefs(mMainLibrary));
103  NS_ENSURE_SUCCESS(rv, rv);
104 
105  return NS_OK;
106 }
107 
108 nsresult
110 {
111  if (!mTimer) {
112  return NS_OK;
113  }
114 
115  mCancelPending = PR_TRUE;
116 
117  return NS_OK;
118 }
119 
120 nsresult
122 {
123  TRACE(("sbRemoteNotificationManager[0x%.8x] - Action (%d, 0x%.8x)",
124  this, aType, aLibrary));
125 
126  nsresult rv;
127 
128  if (aType < eDownload || aType > eEditedPlaylist) {
129  return NS_ERROR_INVALID_ARG;
130  }
131 
132  nsString libraryName;
133  if (aLibrary) {
134  // Only include library-specific notifications from the main library
135  PRBool isMainLibrary;
136  rv = mMainLibrary->Equals(aLibrary, &isMainLibrary);
137  NS_ENSURE_SUCCESS(rv, rv);
138 
139  if (!isMainLibrary) {
140  return NS_OK;
141  }
142 
143  rv = aLibrary->GetName(libraryName);
144  NS_ENSURE_SUCCESS(rv, rv);
145  }
146 
147  // Update this action
148  mPriorityList[aType].mLibraryName = libraryName;
149  mPriorityList[aType].mDisplayUntilTime = PR_Now() + MAX_NOTIFICATION_TIME;
150 
151  // If this action has a higher priorty than the currently displaying action,
152  // make this the new current action and update the status immediately
153  if (aType < mCurrentActionType) {
154  mCurrentActionType = aType;
155  rv = UpdateStatus();
156  NS_ENSURE_SUCCESS(rv, rv);
157  }
158 
159  // Start up the timer that is used to cycle through the message list
160  if (!mTimer) {
161  mTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
162  NS_ENSURE_SUCCESS(rv, rv);
163 
164  // kung fu death grip, matched in Notify. without this the manager goes
165  // away before the timer and deadlocks - bug 7970
166  NS_ADDREF_THIS();
167  rv = mTimer->InitWithCallback(this,
169  nsITimer::TYPE_REPEATING_SLACK);
170  NS_ENSURE_SUCCESS(rv, rv);
171  }
172 
173  return NS_OK;
174 }
175 
176 NS_IMETHODIMP
177 sbRemoteNotificationManager::Notify(nsITimer* aTimer)
178 {
179  TRACE(("sbRemoteNotificationManager[0x%.8x] - Notify", this));
180 
181  NS_ENSURE_ARG_POINTER(aTimer);
182 
183  nsresult rv;
184 
185  if (mCancelPending) {
186  nsRefPtr<sbRemoteNotificationManager> kungFuDeathGrip(this);
187  nsresult rv, rv2;
188  // clear the status bar text
189  mCurrentActionType = eNone;
190  rv = UpdateStatus();
191 
192  // and clear the timer (regardless of if the status bar was cleared)
193  // keep the return value so we always return the worst one
194  rv2 = mTimer->Cancel();
195  mTimer = nsnull;
196 
197  // kung fu death grip, matched in Notify. without this the manager goes
198  // away before the timer and deadlocks - bug7970
199  NS_RELEASE_THIS();
200 
201  NS_ENSURE_SUCCESS(rv, rv);
202  return rv2;
203  }
204 
205  PRTime now = PR_Now();
206 
207  // If we're currently showing a message, check to see if it has been up
208  // long enough
209  if (mCurrentActionType > eNone) {
210  if (now > mPriorityList[mCurrentActionType].mDisplayUntilTime) {
211  mPriorityList[mCurrentActionType].mDisplayUntilTime = 0;
212  }
213  else {
214  // The current message still has time left, do nothing
215  return NS_OK;
216  }
217  }
218 
219  // Is there another message waiting to be displayed? If so, bump the
220  // display until time, update status message and return
221  for (ActionType i = eDownload; i <= eEditedPlaylist; i = ActionType(i + 1)) {
222  if (mPriorityList[i].mDisplayUntilTime > 0) {
223  mCurrentActionType = i;
224  mPriorityList[i].mDisplayUntilTime = now + MAX_NOTIFICATION_TIME;
225  rv = UpdateStatus();
226  NS_ENSURE_SUCCESS(rv, rv);
227 
228  return NS_OK;
229  }
230  }
231 
232  // If we get here, there are no messages to display, so cancel the timer.
233  return Cancel();
234 }
235 
236 nsresult
237 sbRemoteNotificationManager::UpdateStatus()
238 {
239  TRACE(("sbRemoteNotificationManager[0x%.8x] - UpdateStatus", this));
240 
241  nsresult rv;
242  nsString key;
243  nsString message;
244 
245  switch(mCurrentActionType) {
246  case eDownload:
247  key.AssignLiteral("rapi.notification.download");
248  break;
249  case eUpdatedWithItems:
250  key.AssignLiteral("rapi.notification.updateditems");
251  break;
253  key.AssignLiteral("rapi.notification.updatedplaylists");
254  break;
255  case eEditedItems:
256  key.AssignLiteral("rapi.notification.editeditems");
257  break;
258  case eEditedPlaylist:
259  key.AssignLiteral("rapi.notification.editedplaylists");
260  break;
261  default:
262  // Use a blank message
263  break;
264  }
265 
266  if (!key.IsEmpty()) {
267  nsString libraryName = mPriorityList[mCurrentActionType].mLibraryName;
268  const PRUnichar* strings[1] = { libraryName.get() };
269  rv = mBundle->FormatStringFromName(key.BeginReading(),
270  strings,
271  1,
272  getter_Copies(message));
273  if (NS_FAILED(rv)) {
274  message = key;
275  }
276  }
277 
278  rv = mDataRemote->SetStringValue(message);
279  NS_ENSURE_SUCCESS(rv, rv);
280 
281  return NS_OK;
282 }
283 
return NS_OK
NS_IMPL_ISUPPORTS1(sbDeviceCapabilitiesUtils, sbIDeviceCapabilitiesUtils) sbDeviceCapabilitiesUtils
#define TIMER_RESOLUTION
#define TRACE(args)
var strings
Definition: Info.js:46
#define BUNDLE_URL
#define SB_DATAREMOTE_FACEPLATE_STATUS
nsresult Action(ActionType aType, sbILibrary *aLibrary)
GstMessage * message
Media library abstraction.
Definition: sbILibrary.idl:82
function now()
#define MAX_NOTIFICATION_TIME
_getSelectedPageStyle s i
nsITimerCallback