sbMediaListDuplicateFilter.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-2010 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 
28 
29 // Mozilla includes
30 #include <nsComponentManagerUtils.h>
31 #include <nsMemory.h>
32 #include <nsStringAPI.h>
33 
34 // Mozilla interfaces
35 #include <nsISimpleEnumerator.h>
36 
37 // Songbird includes
38 #include <sbPropertiesCID.h>
39 #include <sbStandardProperties.h>
40 
41 // Songbird interfaces
42 #include <sbIMediaItem.h>
43 #include <sbIMediaList.h>
44 
49 
50 static char const * const DUPLICATE_PROPERTIES[] = {
55 };
56 
57 sbMediaListDuplicateFilter::sbMediaListDuplicateFilter() :
58  mInitialized(PR_FALSE),
59  mSBPropKeysLength(NS_ARRAY_LENGTH(DUPLICATE_PROPERTIES)),
60  mSBPropKeys(NS_ARRAY_LENGTH(DUPLICATE_PROPERTIES)),
61  mDuplicateItems(0),
62  mTotalItems(0),
63  mRemoveDuplicates(PR_FALSE)
64 {
65  mKeys.Init();
66 }
67 
68 sbMediaListDuplicateFilter::~sbMediaListDuplicateFilter()
69 {
70  if (mMonitor) {
71  nsAutoMonitor::DestroyMonitor(mMonitor);
72  }
73 }
74 
75 NS_IMETHODIMP
76 sbMediaListDuplicateFilter::Initialize(nsISimpleEnumerator * aSource,
77  sbIMediaList * aDest,
78  PRBool aRemoveDuplicates)
79 {
80  NS_ENSURE_ARG_POINTER(aSource);
81  NS_ENSURE_ARG_POINTER(aDest);
82 
83  nsresult rv = NS_ERROR_UNEXPECTED;
84 
85  mMonitor = nsAutoMonitor::NewMonitor("sbMediaListDuplicateFilter::mMonitor");
86  NS_ENSURE_TRUE(mMonitor, NS_ERROR_OUT_OF_MEMORY);
87 
88  nsCOMPtr<sbIMutablePropertyArray> propArray =
89  do_CreateInstance(SB_MUTABLEPROPERTYARRAY_CONTRACTID, &rv);
90  NS_ENSURE_SUCCESS(rv, rv);
91 
92  // Can't use strict array when using it to get properties.
93  rv = propArray->SetStrict(PR_FALSE);
94  NS_ENSURE_SUCCESS(rv, rv);
95 
96  for (PRUint32 index = 0;
97  index < mSBPropKeysLength;
98  ++index) {
99  NS_ConvertASCIItoUTF16 prop(DUPLICATE_PROPERTIES[index]);
100  mSBPropKeys.AppendElement(prop);
101  propArray->AppendProperty(prop, EmptyString());
102  }
103 
104  mSBPropertyArray = do_QueryInterface(propArray, &rv);
105  NS_ENSURE_SUCCESS(rv, rv);
106 
107  mRemoveDuplicates = aRemoveDuplicates;
108  mSource = aSource;
109  mDest = aDest;
110 
111  return NS_OK;
112 }
113 
114 NS_IMETHODIMP
115 sbMediaListDuplicateFilter::GetDuplicateItems(PRUint32 * aDuplicateItems)
116 {
117  NS_ENSURE_ARG_POINTER(aDuplicateItems);
118  nsAutoMonitor mon(mMonitor);
119  *aDuplicateItems = mDuplicateItems;
120  return NS_OK;
121 }
122 
123 NS_IMETHODIMP
124 sbMediaListDuplicateFilter::GetTotalItems(PRUint32 * aTotalItems)
125 {
126  NS_ENSURE_ARG_POINTER(aTotalItems);
127  nsAutoMonitor mon(mMonitor);
128  *aTotalItems = mTotalItems;
129  return NS_OK;
130 }
131 
132 // nsISimpleEnumerator implementation
133 
134 NS_IMETHODIMP
135 sbMediaListDuplicateFilter::HasMoreElements(PRBool *aMore)
136 {
137  NS_ENSURE_ARG_POINTER(aMore);
138  if (!mCurrentItem) {
139  Advance();
140  }
141  *aMore = mCurrentItem != nsnull;
142  return NS_OK;
143 }
144 
145 NS_IMETHODIMP
146 sbMediaListDuplicateFilter::GetNext(nsISupports ** aItem)
147 {
148  NS_ENSURE_ARG_POINTER(aItem);
149 
150  nsresult rv;
151 
152  if (!mCurrentItem) {
153  Advance();
154  }
155  if (!mCurrentItem) {
156  return NS_ERROR_FAILURE;
157  }
158 
159  rv = CallQueryInterface(mCurrentItem, aItem);
160  NS_ENSURE_SUCCESS(rv, rv);
161 
162  mCurrentItem = nsnull;
163 
164  return NS_OK;
165 }
166 
167 // sbIMediaListEnumerationListener implementation
168 
169 NS_IMETHODIMP
170 sbMediaListDuplicateFilter::OnEnumerationBegin(sbIMediaList *aMediaList,
171  PRUint16 *_retval)
172 {
173  NS_ENSURE_ARG_POINTER(_retval);
175  return NS_OK;
176 }
177 
178 /* unsigned short onEnumeratedItem (in sbIMediaList aMediaList, in sbIMediaItem aMediaItem); */
179 NS_IMETHODIMP
180 sbMediaListDuplicateFilter::OnEnumeratedItem(sbIMediaList *aMediaList,
181  sbIMediaItem *aMediaItem,
182  PRUint16 *_retval)
183 {
184  NS_ENSURE_ARG_POINTER(aMediaItem);
185  NS_ENSURE_ARG_POINTER(_retval);
186 
187  nsresult rv = SaveItemKeys(aMediaItem);
188  NS_ENSURE_SUCCESS(rv, rv);
190  return NS_OK;
191 }
192 
193 /* void onEnumerationEnd (in sbIMediaList aMediaList, in nsresult aStatusCode); */
194 NS_IMETHODIMP
195 sbMediaListDuplicateFilter::OnEnumerationEnd(sbIMediaList *aMediaList,
196  nsresult aStatusCode)
197 {
198  return NS_OK;
199 }
200 
201 // Private implementation
202 
203 nsresult
204 sbMediaListDuplicateFilter::SaveItemKeys(sbIMediaItem * aItem)
205 {
206  nsresult rv;
207  nsString key;
208 
209  nsAutoMonitor mon(mMonitor);
210 
211  rv = aItem->GetProperties(mSBPropertyArray, getter_AddRefs(mItemProperties));
212  NS_ENSURE_SUCCESS(rv, rv);
213 
214  nsCOMPtr<sbIProperty> property;
215  for (PRUint32 index = 0;
216  index < mSBPropKeysLength;
217  ++index) {
218  rv = mItemProperties->GetPropertyAt(index, getter_AddRefs(property));
219  if (NS_SUCCEEDED(rv)) {
220  rv = property->GetValue(key);
221  if (NS_SUCCEEDED(rv) && !key.IsEmpty()) {
222  NS_ENSURE_TRUE(mKeys.PutEntry(key), NS_ERROR_OUT_OF_MEMORY);
223  }
224  }
225  }
226  return NS_OK;
227 }
228 
229 nsresult
230 sbMediaListDuplicateFilter::IsDuplicate(sbIMediaItem * aItem,
231  bool & aIsDuplicate)
232 {
233  aIsDuplicate = false;
234  nsresult rv;
235  nsString key;
236 
237  // No need to lock here because IsDuplicate is always
238  // called with the monitor already acquired.
239 
240  rv = aItem->GetProperties(mSBPropertyArray, getter_AddRefs(mItemProperties));
241  NS_ENSURE_SUCCESS(rv, rv);
242 
243  nsCOMPtr<sbIProperty> property;
244  for (PRUint32 index = 0;
245  index < mSBPropKeysLength;
246  ++index) {
247  rv = mItemProperties->GetPropertyAt(index, getter_AddRefs(property));
248  if (NS_SUCCEEDED(rv)) {
249  property->GetValue(key);
250  if (mKeys.GetEntry(key)) {
251  aIsDuplicate = true;
252  return NS_OK;
253  }
254  }
255  }
256  return NS_OK;
257 }
258 
259 nsresult
260 sbMediaListDuplicateFilter::Advance()
261 {
262  nsresult rv;
263 
264  nsAutoMonitor mon(mMonitor);
265 
266  if (!mInitialized) {
267  // Only enumerate if we need to check for duplicates.
268  if (mRemoveDuplicates) {
269  rv = mDest->EnumerateAllItems(this, sbIMediaList::ENUMERATIONTYPE_SNAPSHOT);
270  NS_ENSURE_SUCCESS(rv, rv);
271  }
272  // Always consider ourselves initialized past this point.
273  mInitialized = PR_TRUE;
274  }
275 
276  PRBool more;
277  rv = mSource->HasMoreElements(&more);
278  NS_ENSURE_SUCCESS(rv, rv);
279 
280  mCurrentItem = nsnull;
281  while (more && !mCurrentItem) {
282  nsCOMPtr<nsISupports> supports;
283  rv = mSource->GetNext(getter_AddRefs(supports));
284  NS_ENSURE_SUCCESS(rv, rv);
285  mCurrentItem = do_QueryInterface(supports);
286 
287  if (mCurrentItem) {
288  if (mRemoveDuplicates) {
289  bool isDuplicate = false;
290  rv = IsDuplicate(mCurrentItem, isDuplicate);
291  NS_ENSURE_SUCCESS(rv, rv);
292  if (isDuplicate) {
293  ++mDuplicateItems;
294  // Skipping duplicates then continue enumerating
295  mCurrentItem = nsnull;
296  }
297  }
298  ++mTotalItems;
299  }
300  }
301  return NS_OK;
302 }
return NS_OK
#define SB_PROPERTY_ORIGINURL
Interface used to enumerate the items in a media list.
#define SB_MUTABLEPROPERTYARRAY_CONTRACTID
static char const *const DUPLICATE_PROPERTIES[]
A brief description of the contents of this interface.
const unsigned short ENUMERATIONTYPE_SNAPSHOT
This flag means that the list being enumerated is a copy that may become out of date.
NS_IMPL_THREADSAFE_ISUPPORTS3(sbMediaListDuplicateFilter, nsISimpleEnumerator, sbIMediaListDuplicateFilter, sbIMediaListEnumerationListener)
#define SB_PROPERTY_GUID
Interface that defines a single item of media in the system.
#define SB_PROPERTY_CONTENTURL
#define SB_PROPERTY_ORIGINITEMGUID