23 more patches ported to 1.3.5
[webos-internals:modifications.git] / messaging / messaging-sms-tone-per-contact.patch
1 diff --git a/usr/palm/applications/com.palm.app.contacts/app/controllers/filepicker-behaviors.js b/usr/palm/applications/com.palm.app.contacts/app/controllers/filepicker-behaviors.js
2 index 276995f..695a2c1 100644
3 --- a/usr/palm/applications/com.palm.app.contacts/app/controllers/filepicker-behaviors.js
4 +++ b/usr/palm/applications/com.palm.app.contacts/app/controllers/filepicker-behaviors.js
5 @@ -57,6 +57,55 @@ var FilepickerBehaviors = {
6  
7         },
8         
9 +       attachMsgtonePicker: function(event){
10 +               if(this.person.messagingRingtoneLoc){
11 +                       this.controller.popupSubmenu( {
12 +                               onChoose:function(c){
13 +                                       if(c == "CHANGE"){
14 +                                               this.pushMsgtonePicker();
15 +                                       } else if(c == "DELETE"){
16 +                                               this.clearMsgtone();
17 +                                       }
18 +                               }.bind(this),
19 +                               placeNear:event.target,
20 +                               items:[
21 +                                       {label:$L("Change Msgtone"), command:'CHANGE'},
22 +                                       {label:$L("Delete Msgtone"), command:'DELETE'}
23 +                               ]
24 +                       })                      
25 +               } else {
26 +                       this.pushMsgtonePicker();
27 +               }
28 +               
29 +       },
30 +       
31 +       clearMsgtone:function(){
32 +               this.person.messagingRingtoneLoc = "";
33 +               this.person.messagingRingtoneName = "";
34 +               this.person.MsgtoneDisplay = $L("Set a message tone");
35 +               this.person.MsgtoneSet = "";
36 +               this.person.dirty = true;
37 +               this.controller.get("MsgtoneBox").update(Mojo.View.render({
38 +                       object:this.person,
39 +                       template:"edit/msgtones"
40 +               }));
41 +       },
42 +       
43 +       pushMsgtonePicker:function(){
44 +                       var params = {
45 +                               actionType: 'attach',
46 +                               kinds: ['ringtone'],
47 +                               defaultKind: 'ringtone',
48 +                               filePath:this.person.messagingRingtoneLoc,
49 +                               onSelect: function(file){
50 +                                       this.attachMsgtone(this.sanitizeSystemPath(file.fullPath), file.name);
51 +                               }.bind(this)
52 +                       };
53 +                       //Mojo.Log.info("ContactMulti Picking a msgtone for " + this.contact.firstName + " " + this.contact.lastName);
54 +                       Mojo.FilePicker.pickFile(params, this.controller.stageController);
55 +
56 +       },
57 +       
58         attachFilePicker: function(event){
59                 if(this.contact.readOnly){
60                         return;
61 @@ -153,6 +202,20 @@ var FilepickerBehaviors = {
62                         template:"edit/ringtones"
63                       }));
64                 }
65 +       },
66 +       
67 +       attachMsgtone: function(msgtonePath, name){
68 +               if (msgtonePath) {
69 +                       this.person.dirty = true;
70 +                       this.person.messagingRingtoneName = name;
71 +                       this.person.MsgtoneDisplay = name;
72 +                       this.person.MsgtoneSet = "msgtone-set";
73 +                       this.person.messagingRingtoneLoc = msgtonePath;
74 +                       this.controller.get("MsgtoneBox").update(Mojo.View.render({
75 +                       object:this.person,
76 +                       template:"edit/msgtones"
77 +                     }));
78 +               }
79         }
80  }
81  
82 diff --git a/usr/palm/applications/com.palm.app.contacts/app/views/edit/lists-fake.html b/usr/palm/applications/com.palm.app.contacts/app/views/edit/lists-fake.html
83 index 306b79a..6238034 100644
84 --- a/usr/palm/applications/com.palm.app.contacts/app/views/edit/lists-fake.html
85 +++ b/usr/palm/applications/com.palm.app.contacts/app/views/edit/lists-fake.html
86 @@ -32,6 +32,20 @@
87          </div>
88      </div>
89  </div>
90 +<div>
91 +<div id="MsgtoneBox" class="">
92 +    <div class="palm-group unlabeled">
93 +        <div class="palm-list">
94 +            <div class="palm-row single" id="MsgtoneButton" x-mojo-tap-highlight="momentary">
95 +                <div class="palm-row-wrapper">
96 +                    <div class="title"  x-mojo-loc="">
97 +                        Set a message tone
98 +                    </div>
99 +                </div>
100 +            </div>
101 +        </div>
102 +    </div>
103 +</div>
104  </div>
105  <div>
106  <div id="emailList" name="emailList" class="contactPointList" >
107 Index: /usr/palm/applications/com.palm.app.contacts/app/views/edit/msgtones.html
108 ===================================================================
109 --- /dev/null
110 +++ /usr/palm/applications/com.palm.app.contacts/app/views/edit/msgtones.html
111 @@ -0,0 +1,16 @@
112 +<div class="palm-group unlabeled">
113 +  <div class="palm-list">
114 +    <div class="palm-row single #{MsgtoneSet} msgtone-button" id="MsgtoneButton" x-mojo-tap-highlight="momentary">
115 +      <div class="palm-row-wrapper">
116 +        <div class="label right truncating-text" x-mojo-loc=''>
117 +          Msgtone
118 +        </div>
119 +        <div class="title">
120 +          <div class="truncating-text">
121 +            #{MsgtoneDisplay}
122 +          </div>
123 +        </div>
124 +      </div>
125 +    </div>
126 +  </div>
127 +</div>
128 diff --git a/usr/palm/applications/com.palm.app.messaging/app/controllers/chatview-assistant.js b/usr/palm/applications/com.palm.app.messaging/app/controllers/chatview-assistant.js
129 index aa6a2b7..13fc64e 100644
130 --- a/usr/palm/applications/com.palm.app.messaging/app/controllers/chatview-assistant.js
131 +++ b/usr/palm/applications/com.palm.app.messaging/app/controllers/chatview-assistant.js
132 @@ -354,7 +354,7 @@ var ChatviewAssistant = Class.create({
133                 if (this.isScreenOn && data.chatThreadId == this.chatThreadId) {
134                         Mojo.Log.info("[CV] ****** chatview considerForNotification --- screen is on!");
135                         if (data.notificationType == this.Messaging.notificationTypes.newMessage) {
136 -                               data = {playSoundOnly:true};
137 +                               Object.extend(data, {playSoundOnly:true});
138                         } else if (data.notificationType == this.Messaging.notificationTypes.sendFailure) {
139                                 data = {}; // wipe out the notification because we are in the chat
140                         }
141 diff --git a/usr/palm/applications/com.palm.app.messaging/app/controllers/listview-assistant.js b/usr/palm/applications/com.palm.app.messaging/app/controllers/listview-assistant.js
142 index 5058e58..248d5e7 100644
143 --- a/usr/palm/applications/com.palm.app.messaging/app/controllers/listview-assistant.js
144 +++ b/usr/palm/applications/com.palm.app.messaging/app/controllers/listview-assistant.js
145 @@ -436,7 +436,7 @@ var ListviewAssistant = Class.create(App.Scene, {
146                 // if we are in the history view and the screen is on, do not display a banner + dashboard, just play a notification sound
147                 if (this.isScreenOn) {
148                         if (data.notificationType == this.Messaging.notificationTypes.newMessage && this.currentListView == this.Messaging.Views.HISTORY) {
149 -                               data = {playSoundOnly:true};
150 +                               Object.extend(data, {playSoundOnly:true});
151                         }
152                 }
153                 return data;
154 diff --git a/usr/palm/applications/com.palm.app.messaging/app/controllers/notification-assistant.js b/usr/palm/applications/com.palm.app.messaging/app/controllers/notification-assistant.js
155 index b84216d..64aab55 100644
156 --- a/usr/palm/applications/com.palm.app.messaging/app/controllers/notification-assistant.js
157 +++ b/usr/palm/applications/com.palm.app.messaging/app/controllers/notification-assistant.js
158 @@ -27,6 +27,8 @@ function NotificationAssistant(controller){
159         };
160  }
161  
162 +var contact = {};
163 +
164  NotificationAssistant.prototype.subscribeToNotifications = function(){
165         this.messageNotificationRequest = MessagingMojoService.registerForIncomingMessages({onSuccess: this.sendNotification.bind(this, this.Messaging.notificationTypes.newMessage)});
166         this.sendErrorNotificationRequest = MessagingMojoService.registerForSendFailures(this.sendNotification.bind(this, this.Messaging.notificationTypes.sendFailure));
167 @@ -35,6 +37,37 @@ NotificationAssistant.prototype.subscribeToNotifications = function(){
168         this.airplaneModeNotificationRequest = MessagingMojoService.registerForAirplaneModeNotifications(this.sendAirplaneModeNotification.bind(this));
169  };
170  
171 +NotificationAssistant.prototype.doBanner = function(bannerParams,bannerLaunchParams,bannerType,payload) {
172 +       if (payload.messagetone.fullPath)
173 +               bannerParams.soundFile = payload.messagetone.fullPath;
174 +       this.controller.showBanner(bannerParams,bannerLaunchParams,bannerType);
175 +};
176 +
177 +NotificationAssistant.prototype.playMessagetone = function(payload){
178 +       if (payload.messagetone.fullPath)
179 +               this.controller.playSoundNotification('alerts',payload.messagetone.fullPath);
180 +       else
181 +               this.controller.playSoundNotification('alerts','');
182 +};
183 +
184 +NotificationAssistant.prototype.doB = function(bannerParams,bannerLaunchParams,bannerType,contact) {
185 +        Mojo.Log.error("Banner Ringtone: %j",contact.ringtoneLoc);                                                                                                                          
186 +       if (contact.ringtoneLoc) {
187 +               bannerParams.soundFile = contact.ringtoneLoc;
188 +               this.controller.showBanner(bannerParams,bannerLaunchParams,bannerType);
189 +       } else {
190 +               MessagingMojoService.getMessagetone(this.doBanner.bind(this,bannerParams,bannerLaunchParams,'chat'));
191 +       }
192 +};
193 +
194 +NotificationAssistant.prototype.playmsgtone = function(contact){
195 +       Mojo.Log.error("Playmsgtone Ringtone: %j",contact.ringtoneLoc);
196 +       if (contact.ringtoneLoc)
197 +               this.controller.playSoundNotification('alerts',contact.ringtoneLoc);
198 +       else
199 +               MessagingMojoService.getMessagetone(this.playMessagetone.bind(this));
200 +};
201 +
202  NotificationAssistant.prototype.sendNotification = function(notificationType, resp){
203         if (window.PalmSystem && !resp.returnValue) {
204                 try {
205 @@ -154,9 +187,8 @@ NotificationAssistant.prototype.considerForNotification = function(notificationD
206         
207         // check if we should only play a sound (when you are already in a chat & a new message comes in)
208         if(notificationData.playSoundOnly && this.Messaging.messagingPrefs.enableNotificationSound) {
209 -               var notifParams = {};
210 -               this.setNotificationSound(notifParams);
211 -               this.controller.playSoundNotification(notifParams.soundClass, notifParams.soundFile);
212 +               var smsid = notificationData.address;
213 +               MessagingMojoService.rLookup(smsid,contact,this.playmsgtone.bind(this),this.playmsgtone.bind(this));
214                 return; // don't display any visual notification
215         }       
216         
217 @@ -191,10 +223,11 @@ NotificationAssistant.prototype.sendClass0PopupAlert = function(notificationData
218  
219         notificationData.carrierName = carrierName;
220         this.class0AlertData.list.push(notificationData);
221 -       this.renderClass0PopupAlert(true);
222 +       var smsid = notificationData.address;;
223 +       MessagingMojoService.getMessagetone(this.renderClass0PopupAlert.bind(this,true));
224  };
225  
226 -NotificationAssistant.prototype.renderClass0PopupAlert = function(playSound) {
227 +NotificationAssistant.prototype.renderClass0PopupAlert = function(playSound,messageTone) {
228         var class0Stage = this.controller.getStageController(Class0AlertStageName);
229  
230         if(class0Stage) {
231 @@ -206,6 +239,8 @@ NotificationAssistant.prototype.renderClass0PopupAlert = function(playSound) {
232                 var soundClass = 'none';
233                 if(playSound) {
234                         soundClass = 'alerts';
235 +                       if(messageTone)
236 +                               soundFile = messageTone;
237                 }               
238                 
239                 var pushClass0AlertScene = function(stageController) {
240 @@ -216,7 +251,8 @@ NotificationAssistant.prototype.renderClass0PopupAlert = function(playSound) {
241                         name: Class0AlertStageName,
242                         lightweight: true,
243                         height: Math.floor(Mojo.Environment.DeviceInfo.screenHeight * 0.50),
244 -                       soundclass: soundClass
245 +                       soundclass: soundClass,
246 +                       soundfile: soundFile
247                 }, pushClass0AlertScene, 'popupalert');         
248         }
249  
250 @@ -292,10 +328,17 @@ NotificationAssistant.prototype.sendNewMessageNotificationAndUpdateDashboard = f
251         
252         if (this.Messaging.DisplayState.isDisplayOn()) {
253                 Mojo.Log.info("notificationAssistant - executing full banner notification");    
254 +               if (this.Messaging.messagingPrefs.enableNotificationSound) {
255 +                       var smsid = notificationData.address;                                                  
256 +                       bannerParams.soundClass = "alerts";
257 +                       MessagingMojoService.rLookup(smsid,contact,this.doB.bind(this,bannerParams,bannerLaunchParams,'chat'),this.doB.bind(this,bannerParams,bannerLaunchParams,'chat'));
258 +               } else {
259 +                       Mojo.Log.error("Setting banner params");        
260                 this.controller.showBanner(bannerParams, bannerLaunchParams, 'chat');           
261 +               }       
262         } else if (this.Messaging.messagingPrefs.enableNotificationSound) {
263 -               Mojo.Log.info("notificationAssistant - playing sound notification only");
264 -               this.controller.playSoundNotification(bannerParams.soundClass, bannerParams.soundFile);
265 +               var smsid = notificationData.address;                                                  
266 +               MessagingMojoService.rLookup(smsid,contact,this.playmsgtone.bind(this),this.playmsgtone.bind(this));
267         }
268         
269         // Store the data so it can be used in the dashboard
270 @@ -354,14 +397,10 @@ NotificationAssistant.prototype.sendNewMessageNotificationAndUpdateDashboard = f
271                 // delay creating the dashboard window for the case where the banner is clicked on
272                 // to take you to the chat view.  This will likely result in the dashboard data
273                 // being cleared.  If the dashboard data is empty, we do not need to create the dashboard.              
274 -               if (this.Messaging.DisplayState.isDisplayOn()) {
275                         if (!this.isNewMessageDashboardPending) {
276                                 this.isNewMessageDashboardPending = true; 
277                                 createDashboard.delay(5);
278                         }
279 -               } else {
280 -                       createDashboard(); // if the screen is off, create the dashboard right away
281 -               }
282         }
283  };
284  
285 diff --git a/usr/palm/applications/com.palm.app.messaging/app/models/messaging-luna-service.js b/usr/palm/applications/com.palm.app.messaging/app/models/messaging-luna-service.js
286 index 119950a..34b55b3 100644
287 --- a/usr/palm/applications/com.palm.app.messaging/app/models/messaging-luna-service.js
288 +++ b/usr/palm/applications/com.palm.app.messaging/app/models/messaging-luna-service.js
289 @@ -1003,6 +1003,169 @@ var MessagingMojoService = {
290           });
291         },
292    
293 +               isNumberValid: function(number) {
294 +               return !(number === undefined
295 +                       || number == null
296 +                       || number == "" 
297 +                       || number == "unknown" 
298 +                       || number == "unknown caller"
299 +                       || number == "blocked caller") 
300 +       },
301 +       
302 +       // use contacts service and carrier book to perform reverse lookup on number.  stores results in passed contact object.
303 +       // runs callback when done.
304 +       // if the number isn't valid, marks contact lookup complete 
305 +       // if there's already one happening, or one already completed, just fires callback
306 +       // if there's a lateCallback provided, calls that if the result comes much later
307 +       rLookup: function(number, contact, callback, lateCallback){
308 +               
309 +               //Reset contact to always get the tone
310 +               contact = {};   
311 +               Mojo.Log.error("Current contact value: %j",contact);
312 +               Mojo.Log.error("SMS ID: %j",number);
313 +               
314 +               // bail if the number is invalid
315 +               if (!(this.isNumberValid(number))) {
316 +                               this.finishLookup(contact, callback);
317 +                               return;
318 +               }
319 +               
320 +               if (contact.lookupComplete) {
321 +                       callback(contact);      
322 +                       return;
323 +               }
324 +               
325 +               if (contact.lookupPending) {
326 +                       callback(contact);      
327 +                       return;
328 +               }
329 +               
330 +               
331 +               // use contacts service to perform lookup.
332 +               // if contact already has an id in it, use person lookup
333 +               // instead of doing reverse lookup on number
334 +               contact.lookupPending = true;
335 +               var method, params;
336 +               if (contact.initialId) {
337 +                       method = 'basicDetails'
338 +                       params =  {'id' : contact.initialId}
339 +                       delete contact.initialId;
340 +               } else {
341 +                       method = 'reverseLookup'
342 +                       params = {
343 +                'value': number,
344 +                'type': "phone"
345 +            }
346 +               }
347 +               this.lastRequest = new Mojo.Service.Request('palm://com.palm.contacts', {
348 +                       'method': method,
349 +            parameters: params,
350 +            onSuccess: this.onLookup.bind(this, number, contact, callback, lateCallback),
351 +                       onFailure: function() {
352 +                               // cancel previous lookup, so this doesn't fire on a service crash
353 +                               if (this.lastRequest) {
354 +                                       this.lastRequest.cancel();
355 +                                       this.lastRequest = undefined;
356 +                               }
357 +                               
358 +                               this.carrierBookLookup(number,contact);
359 +                               this.finishLookup(contact, callback);
360 +                       }.bind(this)
361 +        });
362 +               
363 +               // timeout if lookup hasn't completed in 4 seconds
364 +               this.lookupTimeout = setTimeout(this.onLookupTimeout.bind(this, contact, callback, lateCallback), 4000);
365 +    },
366 +       
367 +       // when contact lookup returns, check for valid result
368 +       // if valid result, grab name, ringtone; if there's a picture, start loading and set callback to measure it
369 +       // if no valid result, look in carrier book
370 +       // fire callback when done
371 +    onLookup: function(number, contact, callback, lateCallback, result){
372 +        Mojo.Log.info( "PhoneApp: Contact::onLookup CALLER ID LOOKUP %s RETURNED %j" , number , result);
373 +               var statusChange = "";
374 +               
375 +               // cancel previous lookup, so this doesn't fire on a service crash
376 +               if (this.lastRequest) {
377 +                       this.lastRequest.cancel();
378 +                       this.lastRequest = undefined;
379 +               }
380 +               
381 +               if (result.record) {
382 +                       /*              
383 +                       // don't match if the number we get back is different than the number
384 +                       // we passed in (provided the lengths are the same)
385 +                       if (!(result.record.number)
386 +                               || ( (result.record.number) && ( (result.record.number.length !== number.length) 
387 +                                       || (result.record.number.length === number.length 
388 +                                                && result.record.number === number)))) {
389 +                       */
390 +                       contact.id = result.record.id;
391 +                       
392 +       
393 +                       contact.ringtoneLoc = result.record.messagingRingtoneLoc;
394 +                       Mojo.Log.error("MSGTone: %j",contact.ringtoneLoc);                      
395 +
396 +               }
397 +               
398 +               this.finishLookup(contact, callback, lateCallback);
399 +    },
400 +       
401 +       
402 +
403 +       // mark complete; cancel timeout; fire callback if it hasn't fired yet
404 +       finishLookup: function(contact, callback, lateCallback) {
405 +               contact.lookupPending = false;
406 +               
407 +               // cancel lookup timeout
408 +               clearTimeout(this.lookupTimeout); 
409 +               this.lookupTimeout = undefined;
410 +               
411 +               if (!(contact.lookupComplete)) {
412 +                       contact.lookupComplete = true;
413 +                       callback(contact);
414 +               // if we have a late return, and we got a contact result, call
415 +               // the late return update 
416 +               } else if (lateCallback && contact.doLateCallback && contact.id) {
417 +                       contact.doLateCallback = false;
418 +                       lateCallback.delay(5, contact);
419 +               } else {
420 +               }
421 +               
422 +       },
423 +       
424 +       // flag lookup as done; proceed with callback
425 +       onLookupTimeout: function(contact, callback, lateCallback) {
426 +               
427 +               if (lateCallback) {
428 +                       contact.doLateCallback = true;
429 +               } else if (this.lastRequest && !lateCallback) {
430 +                       // cancel previous lookup, so this doesn't fire on a service crash
431 +                       this.lastRequest.cancel();
432 +                       this.lastRequest = undefined;
433 +               }
434 +
435 +               // clear timeout
436 +               this.lookupTimeout = undefined;
437 +               
438 +               // flag done; fire callback if it hasn't yet
439 +               contact.lookupComplete = true;
440 +               var lookupWasPending = contact.lookupPending;
441 +               contact.lookupPending = false;
442 +               if (lookupWasPending) 
443 +                       callback(contact);
444 +       },
445 +       
446 +       getMessagetone:  function(callback) {
447 +               var request = new Mojo.Service.Request('palm://com.palm.systemservice', {
448 +                       method: 'getPreferences',
449 +                       parameters: {"keys":["messagetone"]},
450 +                       onSuccess: callback,
451 +                       onFailure: callback
452 +               });
453 +               return request;   
454 +       },
455 +  
456         setSMSCAddressAndEmailGateway: function(address, gateway, sceneController) {
457                 var url = MessagingMojoService.identifier + '/sms' ;
458                 return sceneController.serviceRequest(url, {
459 diff --git a/usr/palm/applications/com.palm.app.soundsandalerts/app/controllers/soundsalertsconfig-assistant.js b/usr/palm/applications/com.palm.app.soundsandalerts/app/controllers/soundsalertsconfig-assistant.js
460 index 638958f..71bd161 100644
461 --- a/usr/palm/applications/com.palm.app.soundsandalerts/app/controllers/soundsalertsconfig-assistant.js
462 +++ b/usr/palm/applications/com.palm.app.soundsandalerts/app/controllers/soundsalertsconfig-assistant.js
463 @@ -96,9 +96,15 @@ var SoundsalertsconfigAssistant = Class.create({
464                 $('system_ui_sounds').observe('mojo-property-change', this.toggleSystemUISounds.bindAsEventListener(this));
465                 
466                 $('currentringtonerow').observe(Mojo.Event.tap, this.showAudioFilePicker.bindAsEventListener(this));
467 +               $('currentalertrow').observe(Mojo.Event.tap, this.showAlertFilePicker.bindAsEventListener(this));
468 +               $('currentnotificationrow').observe(Mojo.Event.tap, this.showNotificationFilePicker.bindAsEventListener(this));
469 +               $('currentmessagerow').observe(Mojo.Event.tap, this.showMessageFilePicker.bindAsEventListener(this));
470                                 
471                 this.getCurrentVolumes();
472                 this.getCurrentRingtone();
473 +               this.getCurrentAlert();
474 +               this.getCurrentNotification();
475 +               this.getCurrentMessage();
476                 this.getVibrateSettings();      
477                 this.getOtherSettings();
478                 
479 @@ -272,6 +278,84 @@ var SoundsalertsconfigAssistant = Class.create({
480                 $('currentringtone').innerHTML = file.name;
481         },
482         
483 +       // Alert Picking
484 +       getCurrentAlert: function() {
485 +       this.getCurrentAlertReq = SystemService.getAlerts(this.getCurrentAlertQuery.bind(this));
486 +       },
487 +       
488 +       getCurrentAlertQuery: function(payload) {
489 +       if (payload.alerttone) {
490 +       $('currentalert').innerHTML = payload.alerttone.name;
491 +       this.currAlertPath = payload.alerttone.fullPath;
492 +       }
493 +       else 
494 +       $('currentalert').innerHTML = $L("Pick an alert");
495 +       
496 +       },
497 +       
498 +       showAlertFilePicker: function(event) {
499 +       var params = {"kinds": ["ringtone"],"filePath":this.currAlertPath,"onSelect":this.selectedAlertFile.bind(this),actionType:"attach",actionName: $L("Done")};
500 +       Mojo.FilePicker.pickFile(params,Mojo.Controller.stageController);
501 +       },
502 +       
503 +       selectedAlertFile: function(file) {
504 +       //var params = {"fullPath": encodeURIComponent(file.fullPath), "name":file.name};
505 +       this.setAlertReq = SystemService.setAlerts(file);
506 +       $('currentalert').innerHTML = file.name;
507 +       },
508 +       
509 +       // Notification Picking
510 +       getCurrentNotification: function() {
511 +       this.getCurrentNotificationReq = SystemService.getNotifications(this.getCurrentNotificationQuery.bind(this));
512 +       },
513 +       
514 +       getCurrentNotificationQuery: function(payload) {
515 +       if (payload.notificationtone) {
516 +       $('currentnotification').innerHTML = payload.notificationtone.name;
517 +       this.currNotificationPath = payload.notificationtone.fullPath;
518 +       }
519 +       else 
520 +       $('currentnotification').innerHTML = $L("Pick a notification");
521 +       
522 +       },
523 +       
524 +       showNotificationFilePicker: function(event) {
525 +       var params = {"kinds": ["ringtone"],"filePath":this.currNotificationPath,"onSelect":this.selectedNotificationFile.bind(this),actionType:"attach",actionName: $L("Done")};
526 +       Mojo.FilePicker.pickFile(params,Mojo.Controller.stageController);
527 +       },
528 +       
529 +       selectedNotificationFile: function(file) {
530 +       //var params = {"fullPath": encodeURIComponent(file.fullPath), "name":file.name};
531 +       this.setNotificationReq = SystemService.setNotifications(file);
532 +       $('currentnotification').innerHTML = file.name;
533 +       },
534 +       
535 +       // Message Picking
536 +       getCurrentMessage: function() {
537 +               this.getCurrentMessageReq = SystemService.getMessages(this.getCurrentMessageQuery.bind(this));
538 +       },
539 +       
540 +       getCurrentMessageQuery: function(payload) {
541 +               if (payload.messagetone) {
542 +                       $('currentmessage').innerHTML = payload.messagetone.name;
543 +                       this.currMessagePath = payload.messagetone.fullPath;
544 +               }
545 +               else 
546 +               $('currentmessage').innerHTML = $L("Pick an message");
547 +       
548 +       },
549 +       
550 +       showMessageFilePicker: function(event) {
551 +               var params = {"kinds": ["ringtone"],"filePath":this.currMessagePath,"onSelect":this.selectedMessageFile.bind(this),actionType:"attach",actionName: $L("Done")};
552 +               Mojo.FilePicker.pickFile(params,Mojo.Controller.stageController);
553 +       },
554 +       
555 +       selectedMessageFile: function(file) {
556 +               //var params = {"fullPath": encodeURIComponent(file.fullPath), "name":file.name};
557 +               this.setMessageReq = SystemService.setMessages(file);
558 +               $('currentmessage').innerHTML = file.name;
559 +       },
560 +       
561         getVibrateSettings: function() {
562                 this.getVibrateSettingsReq = AudioService.getVibrateSettings(this.vibrateSettingsCB.bind(this),this);
563         },
564 diff --git a/usr/palm/applications/com.palm.app.soundsandalerts/app/models/SystemService.js b/usr/palm/applications/com.palm.app.soundsandalerts/app/models/SystemService.js
565 index c5babe5..ea32bde 100644
566 --- a/usr/palm/applications/com.palm.app.soundsandalerts/app/models/SystemService.js
567 +++ b/usr/palm/applications/com.palm.app.soundsandalerts/app/models/SystemService.js
568 @@ -28,6 +28,60 @@ SystemService.getRingtone = function(callback) {
569         return request;
570  }
571  
572 +SystemService.getAlerts = function(callback) {
573 +       var request = new Mojo.Service.Request(SystemService.identifier, {
574 +               method: 'getPreferences',
575 +               parameters: {"keys":["alerttone"]}, 
576 +               onSuccess: callback,
577 +               onFailure: callback
578 +       });
579 +       return request;
580 +}
581 +
582 +SystemService.setAlerts = function(value){
583 +       var request = new Mojo.Service.Request(SystemService.identifier, {
584 +               method: 'setPreferences',
585 +               parameters: {"alerttone":value}, 
586 +       });
587 +       return request;
588 +}
589 +
590 +SystemService.getNotifications = function(callback) {
591 +       var request = new Mojo.Service.Request(SystemService.identifier, {
592 +               method: 'getPreferences',
593 +               parameters: {"keys":["notificationtone"]}, 
594 +               onSuccess: callback,
595 +               onFailure: callback
596 +       });
597 +       return request;
598 +}
599 +
600 +SystemService.setNotifications = function(value){
601 +       var request = new Mojo.Service.Request(SystemService.identifier, {
602 +               method: 'setPreferences',
603 +               parameters: {"notificationtone":value}, 
604 +       });
605 +       return request;
606 +}
607 +
608 +SystemService.getMessages = function(callback) {
609 +       var request = new Mojo.Service.Request(SystemService.identifier, {
610 +               method: 'getPreferences',
611 +               parameters: {"keys":["messagetone"]}, 
612 +               onSuccess: callback,
613 +               onFailure: callback
614 +       });
615 +       return request;
616 +}
617 +
618 +SystemService.setMessages = function(value){
619 +       var request = new Mojo.Service.Request(SystemService.identifier, {
620 +               method: 'setPreferences',
621 +               parameters: {"messagetone":value}, 
622 +       });
623 +       return request;
624 +}
625 +
626  SystemService.getSystemUISounds = function(callback) {
627         var request = new Mojo.Service.Request(SystemService.identifier, {
628                         method: 'getPreferences',
629 diff --git a/usr/palm/applications/com.palm.app.soundsandalerts/app/views/soundsalertsconfig/soundsalertsconfig-scene.html b/usr/palm/applications/com.palm.app.soundsandalerts/app/views/soundsalertsconfig/soundsalertsconfig-scene.html
630 index f59d208..f807386 100644
631 --- a/usr/palm/applications/com.palm.app.soundsandalerts/app/views/soundsalertsconfig/soundsalertsconfig-scene.html
632 +++ b/usr/palm/applications/com.palm.app.soundsandalerts/app/views/soundsalertsconfig/soundsalertsconfig-scene.html
633 @@ -52,9 +52,27 @@
634                         </div>
635                     </div>
636              </div>
637 +           <div id='currentalertrow' class="palm-row" x-mojo-tap-highlight="momentary">
638 +               <div class="palm-row-wrapper">
639 +                               <div class="label" x-mojo-loc=''>Alert</div>
640 +                       <div id='currentalert' class="title"></div> 
641 +               </div>
642 +           </div>
643 +           <div id='currentnotificationrow' class="palm-row" x-mojo-tap-highlight="momentary">
644 +               <div class="palm-row-wrapper">
645 +                               <div class="label" x-mojo-loc=''>Notification</div>
646 +                       <div id='currentnotification' class="title"></div>
647 +               </div>
648 +           </div>
649 +           <div id='currentmessagerow' class="palm-row" x-mojo-tap-highlight="momentary">
650 +               <div class="palm-row-wrapper">
651 +                               <div class="label" x-mojo-loc=''>Messages</div>
652 +                       <div id='currentmessage' class="title"></div>     
653 +               </div>
654 +           </div>            
655                         <div class="palm-row last">
656                                 <div class="palm-row-wrapper">
657 -                                       <div class="title" x-mojo-loc=''>Volume</div>
658 +                                       <div class="title" x-mojo-loc=''>System Volume</div>
659                                         <div x-mojo-element="Slider" id='systemvolume' class="palm-slider"></div>
660                     </div>
661              </div>
662 Index: /usr/palm/applications/com.palm.app.contacts/app/controllers/edit-assistant.js
663 ===================================================================
664 --- .orig/usr/palm/applications/com.palm.app.contacts/app/controllers/edit-assistant.js
665 +++ /usr/palm/applications/com.palm.app.contacts/app/controllers/edit-assistant.js
666 @@ -64,6 +64,17 @@ EditAssistant = Class.create({
667                         template: "edit/ringtones"
668                 }));
669                 
670 +               if(this.person.messagingRingtoneName){
671 +                       this.person.MsgtoneDisplay = this.person.messagingRingtoneName;
672 +                       this.person.MsgtoneSet = "msgtone-set";
673 +               } else {
674 +                       this.person.MsgtoneDisplay = $L("Set a message tone");
675 +                       this.person.MsgtoneSet = "";
676 +               }
677 +               this.controller.get("MsgtoneBox").update(Mojo.View.render({
678 +                       object: this.person,
679 +                       template: "edit/msgtones"
680 +               }));            
681                 
682                 var that = this;
683                 
684 @@ -278,6 +289,11 @@ EditAssistant = Class.create({
685                                         object: {ringtoneDisplay:ringtoneName},
686                                         template: "edit/ringtones"
687                                 }));
688 +                               var messagingRingtoneName = this.person.messagingRingtoneName || $L("Set a message tone");
689 +                               this.controller.get("MsgtoneBox").update(Mojo.View.render({
690 +                                       object: {MsgtoneDisplay:messagingRingtoneName},
691 +                                       template: "edit/msgtones"
692 +                               }));
693                                 
694                         }
695                 }
696 @@ -543,6 +559,7 @@ EditAssistant = Class.create({
697                 this.controller.listen("NameSyncPickerWrapper", Mojo.Event.tap, this.popupContactChooser.bind(this));
698                 this.controller.get("edit-photo").observe(Mojo.Event.tap, this.attachFilePicker.bind(this));
699                 this.controller.get("RingtoneBox").observe(Mojo.Event.tap, this.attachRingtonePicker.bind(this));
700 +               this.controller.get("MsgtoneBox").observe(Mojo.Event.tap, this.attachMsgtonePicker.bind(this));
701                 this.renderLabels();
702                 this.setupContact();
703                 if (this.contact.readOnly) {