Initial commit of the Modello Multimedia app
[profile/ivi/Modello_Multimediaplayer.git] / js / remotecontent.js
1 /* global ko */
2
3 /**
4  * @module MultimediaPlayerApplication
5  */
6
7 /**
8  * Class representing remote media content for MultiMedia Player.
9  *
10  * @class RemoteContent
11  * @constructor
12  */
13 var RemoteContent = function() {
14         "use strict";
15         var self = this;
16         this.mediaServer = tizen.mediaserver;
17         this.mediaSources = ko.observableArray([]);
18         this.selectedMediaSource = ko.observable(null);
19
20         this.mediaContainers = ko.observableArray([]);
21         this.selectedMediaContainer = ko.observable(null);
22
23         this.mediaContainerItems = ko.observableArray([]);
24         this.selectedMediaContainerItem = ko.observable(null);
25
26         this.currentBrowseOperation = "";
27         this.alphabetFilter = ko.observable("");
28         this.onMediaSourceLost = null;
29
30         this.mediaSourcesComputed = ko.computed(function() {
31                 if (self.alphabetFilter() !== "") {
32                         return ko.utils.arrayFilter(self.mediaSources(), function(mediaSource) {
33                                 return mediaSource.friendlyName.toString().toLowerCase().trim().indexOf(self.alphabetFilter().toString().toLowerCase().trim()) === 0;
34                         });
35                 }
36                 return self.mediaSources();
37         });
38         this.mediaContainersComputed = ko.computed(function() {
39                 if (self.alphabetFilter() !== "") {
40                         return ko.utils.arrayFilter(self.mediaContainers(), function(mediaContainer) {
41                                 return mediaContainer.title.toString().toLowerCase().trim().indexOf(self.alphabetFilter().toString().toLowerCase().trim()) === 0;
42                         });
43                 }
44                 return self.mediaContainers();
45         });
46         this.mediaContainerItemsComputed = ko.computed(function() {
47                 if (self.alphabetFilter() !== "") {
48                         return ko.utils.arrayFilter(self.mediaContainerItems(), function(mediaItem) {
49                                 return mediaItem.title.toString().toLowerCase().trim().indexOf(self.alphabetFilter().toString().toLowerCase().trim()) === 0;
50                         });
51                 }
52                 return self.mediaContainerItems();
53         });
54 };
55
56 /**
57  * Scans network for available DLNA server and adds it to media sources.
58  *
59  * @method scanMediaServerNetwork
60  */
61 RemoteContent.prototype.scanMediaServerNetwork = function() {
62         "use strict";
63         var self = this;
64         if (!!self.mediaServer) {
65                 self.clearDisappearedMediaSources();
66                 self.mediaServer.scanNetwork(function(source) {
67                         self.addMediaSource(source);
68                 }, function(err) {
69                         console.log("An error has occured while scanning network: " + err.message);
70                         console.log(err);
71                 });
72         }
73 };
74
75 /**
76  * Adds given media source to the list.
77  *
78  * @method addMediaSource
79  * @param source {Object} media source
80  */
81 RemoteContent.prototype.addMediaSource = function(source) {
82         "use strict";
83         var self = this;
84         console.log(source);
85         if (!!source) {
86                 if (!source.friendlyName) {
87                         return;
88                 }
89                 source.timestamp = new Date().getTime();
90                 var sourceExists = false;
91                 for ( var i = 0; i < self.mediaSources().length; ++i) {
92                         var src = self.mediaSources()[i];
93                         if (src.id === source.id) {
94                                 self.mediaSources()[i] = source;
95                                 sourceExists = true;
96                                 break;
97                         }
98                 }
99                 if (!sourceExists) {
100                         self.mediaSources.push(source);
101                 }
102
103                 self.mediaSources.sort(function(left, right) {
104                         var leftFriendlyName = "Unknown";
105                         if (!!left.friendlyName && left.friendlyName !== "") {
106                                 leftFriendlyName = left.friendlyName;
107                         }
108                         leftFriendlyName = leftFriendlyName.toString().trim().toLowerCase();
109                         var rightFriendlyName = "Unknown";
110                         if (!!right.friendlyName && right.friendlyName !== "") {
111                                 rightFriendlyName = right.friendlyName;
112                         }
113                         rightFriendlyName = rightFriendlyName.toString().trim().toLowerCase();
114                         return leftFriendlyName === rightFriendlyName ? 0 : (leftFriendlyName < rightFriendlyName) ? -1 : 1;
115                 });
116         }
117 };
118
119 /**
120  * Sets given media source as selected and adds new media container based on the media source and sets it as selected.
121  *
122  * @method selectMediaSource
123  * @param mediaSource {Object} media source
124  */
125 RemoteContent.prototype.selectMediaSource = function(mediaSource) {
126         "use strict";
127         var self = this;
128         console.log(mediaSource);
129         self.selectedMediaSource(null);
130         if (!!mediaSource) {
131                 self.selectedMediaSource(mediaSource);
132                 self.resetMediaContainers();
133                 self.resetMediaContainerItems();
134                 var mediaSourceContainerProps = {
135                         DisplayName : mediaSource.root.title,
136                         Path : mediaSource.root.id,
137                         Type : mediaSource.root.type
138                 };
139                 /*global mediacontent*/
140                 var mediaContainer = new mediacontent.MediaContainer(mediaSourceContainerProps);
141                 self.mediaContainers.push(mediaContainer);
142                 self.selectMediaContainer(mediaContainer);
143         }
144 };
145
146 /**
147  * Sets given media container as selected.
148  *
149  * @method selectMediaContainer
150  * @param mediaSourceContainer {Object} media source container
151  */
152 RemoteContent.prototype.selectMediaContainer = function(mediaSourceContainer) {
153         "use strict";
154         var self = this;
155         console.log(mediaSourceContainer);
156         if (!!mediaSourceContainer) {
157                 self.resetMediaContainerItems();
158
159                 for ( var i = self.mediaContainers().length - 1; i >= 0; --i) {
160                         if (self.mediaContainers()[i] !== mediaSourceContainer) {
161                                 self.mediaContainers.pop();
162                         } else {
163                                 break;
164                         }
165                 }
166                 console.log(self.mediaContainers());
167                 self.selectedMediaContainer(mediaSourceContainer);
168                 self.browseMediaSourceContainer(self.selectedMediaSource(), mediaSourceContainer);
169         }
170 };
171
172 /**
173  * Sets given media container item as selected.
174  *
175  * @method selectMediaContainerItem
176  * @param mediaContainerItem {Object} media source container
177  */
178 RemoteContent.prototype.selectMediaContainerItem = function(mediaContainerItem) {
179         "use strict";
180         var self = this;
181         console.log(mediaContainerItem);
182         if (!!mediaContainerItem) {
183                 self.selectedMediaContainerItem(mediaContainerItem);
184                 if (mediaContainerItem.type === "CONTAINER") {
185                         self.mediaContainers.push(mediaContainerItem);
186                         self.selectMediaContainer(mediaContainerItem);
187                 }
188         }
189 };
190
191 /**
192  * Sets selected media source to null and empties media sources.
193  *
194  * @method resetMediaSource
195  */
196 RemoteContent.prototype.resetMediaSource = function() {
197         "use strict";
198         var self = this;
199         self.selectedMediaSource(null);
200         self.mediaSources.removeAll();
201         self.mediaSources([]);
202 };
203
204 /**
205  * Removes expired media sources and invokes onMediaSourceLost listener.
206  *
207  * @method clearDisappearedMediaSources
208  */
209 RemoteContent.prototype.clearDisappearedMediaSources = function() {
210         "use strict";
211         var self = this;
212         if (self.mediaSources().length) {
213                 for ( var i = self.mediaSources().length - 1; i >= 0; --i) {
214                         if (new Date().getTime() - self.mediaSources()[i].timestamp > 10000) {
215                                 var mediaSourceId = self.mediaSources()[i].id;
216                                 self.mediaSources.remove(self.mediaSources()[i]);
217                                 if (!!self.onMediaSourceLost) {
218                                         self.onMediaSourceLost(mediaSourceId);
219                                 }
220                         }
221                 }
222         }
223 };
224
225 /**
226  * Sets the listener to receive notifications when media source is lost.
227  *
228  * @method setMediaSourceLostListener
229  * @param onMediaSourceLost {Function(mediaSourceId)} Event listener to be set.
230  */
231 RemoteContent.prototype.setMediaSourceLostListener = function(onMediaSourceLost) {
232         "use strict";
233         var self = this;
234         if (!!onMediaSourceLost) {
235                 self.onMediaSourceLost = onMediaSourceLost;
236         }
237 };
238
239 /**
240  * Sets selected media container to null and empties media containers.
241  *
242  * @method resetMediaContainers
243  */
244 RemoteContent.prototype.resetMediaContainers = function() {
245         "use strict";
246         var self = this;
247         self.selectedMediaContainer(null);
248         self.mediaContainers.removeAll();
249         self.mediaContainers([]);
250 };
251
252 /**
253  * Sets selected media container item to null and empties media container items.
254  *
255  * @method resetMediaContainerItems
256  */
257 RemoteContent.prototype.resetMediaContainerItems = function() {
258         "use strict";
259         var self = this;
260         self.selectedMediaContainerItem(null);
261         self.mediaContainerItems.removeAll();
262         self.mediaContainerItems([]);
263 };
264
265 /**
266  * Gets media source by its id.
267  *
268  * @method getMediaSourceById
269  * @param id (String) media source id
270  */
271 RemoteContent.prototype.getMediaSourceById = function(id) {
272         "use strict";
273         var self = this;
274         var mediaSource = ko.utils.arrayFirst(self.mediaSources(), function(ms) {
275                 return ms.id === id;
276         });
277         return mediaSource;
278 };
279
280 /**
281  * Gets media container by its id.
282  *
283  * @method getMediaContainerById
284  * @param id {String} media container id
285  */
286 RemoteContent.prototype.getMediaContainerById = function(id) {
287         "use strict";
288         var self = this;
289         var mediaContainer = ko.utils.arrayFirst(self.mediaContainers(), function(mc) {
290                 return mc.id === id;
291         });
292         return mediaContainer;
293 };
294
295 /**
296  * Browses given media source container.
297  *
298  * @method browseMediaSourceContainer
299  * @param source {Object} media source
300  * @param container {Object} media container
301  */
302 RemoteContent.prototype.browseMediaSourceContainer = function(source, container) {
303         "use strict";
304         var self = this;
305         var browseCount = 100;
306         var browseOffset = 0;
307         var localOp = "Browse_" + source.id + "_" + container.id;
308
309         function browseErrorCB(str) {
310                 console.log("Error browsing " + container.id + " : " + str);
311         }
312
313         function browseContainerCB(jsonArray) {
314                 console.log(jsonArray);
315                 if (self.currentBrowseOperation !== localOp) {
316                         return;
317                 }
318                 for ( var i = 0; i < jsonArray.length; ++i) {
319                         self.mediaContainerItems.push(mediacontent.mediaObjectForProps(jsonArray[i]));
320                 }
321
322                 if (jsonArray.length === browseCount) {
323                         browseOffset += browseCount;
324                         source.browse(container.id, "+DisplayName", browseCount, browseOffset, browseContainerCB, browseErrorCB);
325                 } else {
326                         self.currentBrowseOperation = "";
327                 }
328         }
329
330         if (self.currentBrowseOperation === localOp) {
331                 return;
332         }
333
334         self.currentBrowseOperation = localOp;
335
336         source.browse(container.id, "+DisplayName", browseCount, browseOffset, browseContainerCB, browseErrorCB);
337 };
338
339 /**
340  * Gets audio media items from selected container.
341  *
342  * @method getAudioFromSelectedContainer
343  */
344 RemoteContent.prototype.getAudioFromSelectedContainer = function() {
345         "use strict";
346         var self = this;
347         if (!!self.mediaContainerItemsComputed() && self.mediaContainerItemsComputed().length) {
348                 return ko.utils.arrayFilter(self.mediaContainerItemsComputed(), function(mediaItem) {
349                         return mediaItem.type === "AUDIO";
350                 });
351         }
352         return [];
353 };
354
355 /**
356  * Gets video media items from selected container.
357  *
358  * @method getVideoFromSelectedContainer
359  */
360 RemoteContent.prototype.getVideoFromSelectedContainer = function() {
361         "use strict";
362         var self = this;
363         if (!!self.mediaContainerItemsComputed() && self.mediaContainerItemsComputed().length) {
364                 return ko.utils.arrayFilter(self.mediaContainerItemsComputed(), function(mediaItem) {
365                         return mediaItem.type === "VIDEO";
366                 });
367         }
368         return [];
369 };