sbIPDPref.cpp
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set sw=2 :miv */
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://www.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 //------------------------------------------------------------------------------
28 //------------------------------------------------------------------------------
29 //
30 // iPod device preference services.
31 //
32 //------------------------------------------------------------------------------
33 //------------------------------------------------------------------------------
34 
40 //------------------------------------------------------------------------------
41 //
42 // iPod device preference imported services.
43 //
44 //------------------------------------------------------------------------------
45 
46 // Local imports.
47 #include "sbIPDDevice.h"
48 #include "sbIPDLog.h"
49 
50 // Songbird imports.
51 #include <sbAutoRWLock.h>
52 #include <sbIDeviceEvent.h>
53 #include <sbIDeviceLibraryMediaSyncSettings.h>
54 
55 // Mozilla imports.
56 #include <nsArrayUtils.h>
57 #include <prprf.h>
58 
59 
60 //------------------------------------------------------------------------------
61 //
62 // iPod device preference services.
63 //
64 //------------------------------------------------------------------------------
65 
70 nsresult
71 sbIPDDevice::PrefInitialize()
72 {
73  // Set up to auto-finalize on error.
74  SB_IPD_DEVICE_AUTO_INVOKE(AutoFinalize, PrefFinalize()) autoFinalize(this);
75 
76  // Create the preference lock.
77  mPrefLock = nsAutoLock::NewLock("sbIPDDevice::mPrefLock");
78  NS_ENSURE_TRUE(mPrefLock, NS_ERROR_OUT_OF_MEMORY);
79 
80  // Forget auto-finalize.
81  autoFinalize.forget();
82 
83  return NS_OK;
84 }
85 
86 
91 void
92 sbIPDDevice::PrefFinalize()
93 {
94  // Dispose of pref lock.
95  if (mPrefLock)
96  nsAutoLock::DestroyLock(mPrefLock);
97  mPrefLock = nsnull;
98 }
99 
100 
105 nsresult
106 sbIPDDevice::PrefConnect()
107 {
108  nsresult rv;
109 
110  // Set up to auto-disconnect on error.
111  SB_IPD_DEVICE_AUTO_INVOKE(AutoDisconnect, PrefDisconnect())
112  autoDisconnect(this);
113 
114  // Connect the iPod preferences file services.
115  rv = PrefConnectIPodPrefs();
116  NS_ENSURE_SUCCESS(rv, rv);
117 
118  // Mark the preference services as connected. After this, "pref lock" fields
119  // may be used.
120  {
121  nsAutoLock autoPrefLock(mPrefLock);
122  mPrefConnected = PR_TRUE;
123  }
124 
125  // Forget auto-disconnect.
126  autoDisconnect.forget();
127 
128  return NS_OK;
129 }
130 
131 
136 void
137 sbIPDDevice::PrefDisconnect()
138 {
139  // Mark the preference services as not connected. After this, "pref lock"
140  // fields may not be used.
141  {
142  nsAutoLock autoPrefLock(mPrefLock);
143  mPrefConnected = PR_FALSE;
144  }
145 
146  // Disconnect the iPod preferences file services.
147  PrefDisconnectIPodPrefs();
148 }
149 
150 
151 //------------------------------------------------------------------------------
152 //
153 // iPod device preference sbIDeviceLibrary services.
154 //
155 //------------------------------------------------------------------------------
156 
163 nsresult
164 sbIPDDevice::GetMgmtType(PRUint32* aMgmtType)
165 {
166  // Validate arguments.
167  NS_ASSERTION(aMgmtType, "aMgmtType is null");
168 
169  // Operate under the preference lock.
170  nsAutoLock autoPrefLock(mPrefLock);
171  NS_ENSURE_TRUE(mPrefConnected, NS_ERROR_NOT_AVAILABLE);
172 
173  // Read the management type.
174  if (mIPodPrefs->music_mgmt_type == 0x00) {
176  } else {
177  if (mIPodPrefs->music_update_type == 0x01)
179  else if (mIPodPrefs->music_update_type == 0x02)
181  else {
182  NS_WARNING("Unexpected management type preference.");
183  return NS_ERROR_UNEXPECTED;
184  }
185  }
186 
187  return NS_OK;
188 }
189 
190 
197 nsresult
198 sbIPDDevice::SetMgmtType(PRUint32 aMgmtType)
199 {
200  nsresult rv;
201 
202  // Operate under the preference lock.
203  {
204  nsAutoLock autoPrefLock(mPrefLock);
205  NS_ENSURE_TRUE(mPrefConnected, NS_ERROR_NOT_AVAILABLE);
206 
207  // Set the management type.
208  switch (aMgmtType) {
210  mIPodPrefs->music_mgmt_type = 0x00;
211  break;
212 
214  mIPodPrefs->music_mgmt_type = 0x01;
215  mIPodPrefs->music_update_type = 0x01;
216  break;
217 
219  mIPodPrefs->music_mgmt_type = 0x01;
220  mIPodPrefs->music_update_type = 0x02;
221  break;
222 
223  default :
224  NS_WARNING("Invalid management type.");
225  return NS_ERROR_INVALID_ARG;
226  }
227 
228  // Mark the preferences as dirty.
229  mIPodPrefsDirty = PR_TRUE;
230  }
231 
232  // Write the preferences. Do this outside of the preference lock to avoid
233  // potential deadlock warnings.
235  rv = PushRequest(REQUEST_WRITE_PREFS);
236  NS_ENSURE_SUCCESS(rv, rv);
237 
238  return NS_OK;
239 }
240 
241 
248 nsresult
249 sbIPDDevice::GetIsSetUp(PRBool* aIsSetUp)
250 {
251  // Validate arguments.
252  NS_ASSERTION(aIsSetUp, "aIsSetUp is null");
253 
254  // Operate under the preference lock.
255  nsAutoLock autoPrefLock(mPrefLock);
256  NS_ENSURE_TRUE(mPrefConnected, NS_ERROR_NOT_AVAILABLE);
257 
258  // Read the ipod set up flag
259  *aIsSetUp = (mIPodPrefs->ipod_set_up ? PR_TRUE : PR_FALSE);
260 
261  return NS_OK;
262 }
263 
264 
271 nsresult
272 sbIPDDevice::SetIsSetUp(PRBool aIsSetUp)
273 {
274  nsresult rv;
275 
276  // Operate under the preference lock.
277  {
278  nsAutoLock autoPrefLock(mPrefLock);
279  NS_ENSURE_TRUE(mPrefConnected, NS_ERROR_NOT_AVAILABLE);
280 
281  // Set the ipod set up flag
282  mIPodPrefs->ipod_set_up = (aIsSetUp ? 0x01 : 0x00);
283 
284  // Mark the preferences as dirty.
285  mIPodPrefsDirty = PR_TRUE;
286  }
287 
288  // Write the preferences. Do this outside of the preference lock to avoid
289  // potential deadlock warnings.
291  rv = PushRequest(REQUEST_WRITE_PREFS);
292  NS_ENSURE_SUCCESS(rv, rv);
293 
294  return NS_OK;
295 }
296 
297 
304 nsresult
305 sbIPDDevice::GetSyncPlaylistList(nsIArray** aPlaylistList)
306 {
307  // Validate arguments.
308  NS_ASSERTION(aPlaylistList, "aPlaylistList is null");
309 
310  // Function variables.
311  nsresult rv;
312 
313  // Operate under the preference lock.
314  nsAutoLock autoPrefLock(mPrefLock);
315  NS_ENSURE_TRUE(mPrefConnected, NS_ERROR_NOT_AVAILABLE);
316 
317  // Get a mutable array.
318  nsCOMPtr<nsIMutableArray> playlistList =
319  do_CreateInstance("@songbirdnest.com/moz/xpcom/threadsafe-array;1", &rv);
320  NS_ENSURE_SUCCESS(rv, rv);
321 
322  // Build a Songbird sync playlist list from the iPod sync playlist list.
323  PRUint32 playlistCount = mSyncPlaylistList.Length();
324  for (PRUint32 i = 0; i < playlistCount; i++) {
325  // Get the next media list from the next playlist ID. Skip sync playlist if
326  // it's not mapped to a Songbird media list.
327  nsCOMPtr<sbIMediaItem> mediaItem;
328  rv = IDMapGet(mSyncPlaylistList[i], getter_AddRefs(mediaItem));
329  if (NS_FAILED(rv))
330  continue;
331 
332  // Add it to the Songbird playlist list.
333  rv = playlistList->AppendElement(mediaItem, PR_FALSE);
334  NS_ENSURE_SUCCESS(rv, rv);
335  }
336 
337  // Return results.
338  NS_ADDREF(*aPlaylistList = playlistList);
339 
340  return NS_OK;
341 }
342 
343 
351 nsresult
352 sbIPDDevice::SetSyncPlaylistList(nsIArray* aPlaylistList)
353 {
354  // Validate arguments.
355  NS_ASSERTION(aPlaylistList, "aPlaylistList is null");
356 
357  // Function variables.
358  PRBool success;
359  nsresult rv;
360 
361  // Operate under the preference lock.
362  {
363  nsAutoLock autoPrefLock(mPrefLock);
364  NS_ENSURE_TRUE(mPrefConnected, NS_ERROR_NOT_AVAILABLE);
365 
366  // Get the number of sync playlists.
367  PRUint32 playlistCount;
368  rv = aPlaylistList->GetLength(&playlistCount);
369  NS_ENSURE_SUCCESS(rv, rv);
370 
371  // Reset iPod sync playlist list.
372  mSyncPlaylistList.Clear();
373  success = mSyncPlaylistList.SetCapacity(playlistCount);
374  NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
375 
376  // Build an iPod sync playlist list from the Songbird sync playlist list.
377  for (PRUint32 i = 0; i < playlistCount; i++) {
378  // Get the next Songbird sync playlist media list item.
379  nsCOMPtr<sbIMediaItem> mediaItem = do_QueryElementAt(aPlaylistList,
380  i,
381  &rv);
382  NS_ENSURE_SUCCESS(rv, rv);
383 
384  // Add the sync playlist media item to the iPod sync playlist list.
385  guint64 playlistID;
386  guint64* pPlaylistID;
387  rv = GetSyncPlaylist(mediaItem, &playlistID);
388  NS_ENSURE_SUCCESS(rv, rv);
389  pPlaylistID = mSyncPlaylistList.AppendElement(playlistID);
390  NS_ENSURE_TRUE(pPlaylistID, NS_ERROR_OUT_OF_MEMORY);
391  }
392 
393  // Mark the preferences as dirty.
394  mSyncPlaylistListDirty = PR_TRUE;
395  }
396 
397  // Write the sync playlist list file. Do this outside of the preference lock
398  // to avoid potential deadlock warnings.
400  rv = PushRequest(REQUEST_WRITE_PREFS);
401  NS_ENSURE_SUCCESS(rv, rv);
402 
403  return NS_OK;
404 }
405 
406 
414 nsresult
415 sbIPDDevice::AddToSyncPlaylistList(sbIMediaList* aPlaylist)
416 {
417  // Validate parameters.
418  NS_ASSERTION(aPlaylist, "aPlaylist is null");
419 
420  // Function variables.
421  nsresult rv;
422 
423  // Operate under the preference lock.
424  {
425  nsAutoLock autoPrefLock(mPrefLock);
426  NS_ENSURE_TRUE(mPrefConnected, NS_ERROR_NOT_AVAILABLE);
427 
428  // Get the iPod playlist ID mapped to the sync playlist media list.
429  guint64 playlistID;
430  rv = GetSyncPlaylist(aPlaylist, &playlistID);
431  NS_ENSURE_SUCCESS(rv, rv);
432 
433  // Do nothing more if playlist is already in list.
434  if (mSyncPlaylistList.Contains(playlistID))
435  return NS_OK;
436 
437  // Add to sync playlist list.
438  guint64* appendSyncPlaylist;
439  appendSyncPlaylist = mSyncPlaylistList.AppendElement(playlistID);
440  NS_ENSURE_TRUE(appendSyncPlaylist, NS_ERROR_OUT_OF_MEMORY);
441 
442  // Mark the preferences as dirty.
443  mSyncPlaylistListDirty = PR_TRUE;
444  }
445 
446  // Write the sync playlist list file. Do this outside of the preference lock
447  // to avoid potential deadlock warnings.
449  rv = PushRequest(REQUEST_WRITE_PREFS);
450  NS_ENSURE_SUCCESS(rv, rv);
451 
452  return NS_OK;
453 }
454 
455 
464 nsresult
465 sbIPDDevice::GetSyncPlaylist(sbIMediaItem* aPlaylist,
466  guint64* aIPodID)
467 {
468  // Validate arguments.
469  NS_ASSERTION(aPlaylist, "aPlaylist is null");
470 
471  // Function variables.
472  nsresult rv;
473 
474  // If the playlist item is mapped to an iPod playlist ID, return that playlist
475  // ID.
476  nsAutoString sbID;
477  nsTArray<guint64> iPodIDList;
478  rv = GetSBID(aPlaylist, sbID);
479  NS_ENSURE_SUCCESS(rv, rv);
480  rv = IDMapGet(sbID, iPodIDList);
481  if (NS_SUCCEEDED(rv) && !iPodIDList.IsEmpty()) {
482  *aIPodID = iPodIDList[0];
483  return NS_OK;
484  }
485 
486  // If no iPod mapping exists for the media list item, create one and add
487  // the mapped playlist ID to the iPod sync playlist list.
488  guint64 iPodID = (((guint64) g_random_int()) << 32) |
489  ((guint64) g_random_int());
490  rv = IDMapAdd(sbID, iPodID);
491  NS_ENSURE_SUCCESS(rv, rv);
492  *aIPodID = iPodID;
493 
494  return NS_OK;
495 }
496 
497 
498 //------------------------------------------------------------------------------
499 //
500 // iPod device iPod preferences file services.
501 //
502 // These services provide access to the iPod preferences files stored on the
503 // iPod. These are the files that iTunes writes when saving iPod preference
504 // settings.
505 //
506 //------------------------------------------------------------------------------
507 
515 nsresult
516 sbIPDDevice::PrefConnectIPodPrefs()
517 {
518  GError* gError = NULL;
519  PRBool success;
520  nsresult rv;
521 
522  // Set up to auto-disconnect on error.
523  SB_IPD_DEVICE_AUTO_INVOKE(AutoDisconnect, PrefDisconnectIPodPrefs())
524  autoDisconnect(this);
525 
526  // Parse the iPod preferences.
527  mIPodPrefs = itdb_prefs_parse(mITDB->device, &gError);
528  if (gError) {
529  if (gError->message)
530  FIELD_LOG(("%s", gError->message));
531  g_error_free(gError);
532  gError = NULL;
533  }
534  NS_ENSURE_TRUE(mIPodPrefs, NS_ERROR_FAILURE);
535 
536  // Read the sync playlist list and arrange for auto-cleanup.
537  guint64* syncPlaylistList;
538  int syncPlaylistCount;
539  success = itdb_update_playlists_read(mITDB->device,
540  &syncPlaylistList,
541  &syncPlaylistCount,
542  &gError);
543  if (gError) {
544  if (gError->message)
545  FIELD_LOG(("%s", gError->message));
546  g_error_free(gError);
547  gError = NULL;
548  }
549  NS_ENSURE_TRUE(success, NS_ERROR_FAILURE);
550  sbAutoGMemPtr autoSyncPlaylistList(syncPlaylistList);
551 
552  // Save the sync playlist list.
553  mSyncPlaylistList.Clear();
554  guint64* appendSyncPlaylistList =
555  mSyncPlaylistList.AppendElements(syncPlaylistList,
556  syncPlaylistCount);
557  NS_ENSURE_TRUE(appendSyncPlaylistList, NS_ERROR_OUT_OF_MEMORY);
558 
559  // If a valid iPod preferences file was not available, set one up.
560  if (!(mIPodPrefs->valid_file)) {
561  // Write the preferences file.
562  mIPodPrefsDirty = PR_TRUE;
564  rv = PushRequest(REQUEST_WRITE_PREFS);
565  NS_ENSURE_SUCCESS(rv, rv);
566  }
567 
568  // Initialize the sync partner preference.
569  rv = PrefInitializeSyncPartner();
570  NS_ENSURE_SUCCESS(rv, rv);
571 
572  // Forget auto-disconnect.
573  autoDisconnect.forget();
574 
575  return NS_OK;
576 }
577 
578 
586 void
587 sbIPDDevice::PrefDisconnectIPodPrefs()
588 {
589  // Dispose of the iPod preferences data record.
590  if (mIPodPrefs)
591  g_free(mIPodPrefs);
592  mIPodPrefs = NULL;
593 
594  // Clear the sync playlist list.
595  mSyncPlaylistList.Clear();
596 }
597 
598 
603 nsresult
604 sbIPDDevice::PrefInitializeSyncPartner()
605 {
606  nsresult rv;
607 
608  // Get the Songbird sync partner ID from the iPod sync partner ID. Try
609  // getting a Songbird sync partner ID mapped to the iPod sync partner ID. If
610  // none mapped, use the iPod sync partner ID as the Songbird sync partner ID
611  // but don't create a mapping between them.
612  nsAutoString sbSyncPartnerID;
613  guint64 iPodSyncPartnerID = mIPodPrefs->music_lib_link_id;
614  rv = IDMapGet(iPodSyncPartnerID, sbSyncPartnerID);
615  if (rv == NS_ERROR_NOT_AVAILABLE) {
616  char sbSyncPartnerIDLiteral[64];
617  PR_snprintf(sbSyncPartnerIDLiteral,
618  sizeof(sbSyncPartnerIDLiteral),
619  "%08x%08x",
620  (PRUint32) ((iPodSyncPartnerID >> 32) & 0xFFFFFFFF),
621  (PRUint32) (iPodSyncPartnerID & 0xFFFFFFFF));
622  sbSyncPartnerID.AssignLiteral(sbSyncPartnerIDLiteral);
623  } else {
624  NS_ENSURE_SUCCESS(rv, rv);
625  }
626 
627  // Set the internal sync partner ID preference.
629  NS_LITERAL_STRING("SyncPartner"),
630  sbIPDVariant(sbSyncPartnerID).get(),
631  nsnull);
632  NS_ENSURE_SUCCESS(rv, rv);
633 
634  return NS_OK;
635 }
636 
nsresult CreateAndDispatchEvent(PRUint32 aType, nsIVariant *aData, PRBool aAsync=PR_TRUE, sbIDeviceEventTarget *aTarget=nsnull)
nsresult SetPreferenceInternalNoNotify(const nsAString &aPrefName, nsIVariant *aPrefValue, PRBool *aPrefChanged)
return NS_OK
A brief description of the contents of this interface.
nsresult PushRequest(const PRUint32 aType, sbIMediaItem *aItem=nsnull, sbIMediaList *aList=nsnull, PRUint32 aIndex=PR_UINT32_MAX, PRUint32 aOtherIndex=PR_UINT32_MAX, nsISupports *aData=nsnull)
Songbird iPod Device Definitions.
#define FIELD_LOG(args)
Definition: sbIPDLog.h:126
this _document this
Definition: FeedWriter.js:1085
Songbird iPod Device Logging Definitions.
return
Definition: FeedWriter.js:850
#define SB_IPD_DEVICE_AUTO_INVOKE(aName, aMethod)
Definition: sbIPDDevice.h:1179
if(DEBUG_DATAREMOTES)
const unsigned long EVENT_DEVICE_PREFS_CHANGED
Interface that defines a single item of media in the system.
_getSelectedPageStyle s i