The Sound Manager sample application demonstrates how you can manage custom sound profiles. A sound profile is a structure consisting of a unique name and a list of volume values for all available sound types, such as ringtone, notification, and alarm.
The following figure illustrates the main screens of the Sound Manager.
Figure: Sound Manager screens
The application opens with the main screen, which shows a list of all sound profiles created by the user:
- To activate a sound profile, select the radio button next to the profile name.
When a profile is activated, the system sound settings are set to its values.
- To add a new profile, click Add and enters a name for the new profile.
The new profile is initialized with the current system sound settings.
- To modify the values of a sound profile, click the profile name.
The details screen opens, showing the various sound type volumes set for that profile. Use the range inputs to change the volume values.
If the currently active profile is modified, the changes are applied directly to the system settings.
To restore the profile values to the state they were in when the details screen was opened, click Reset. To delete the profile, click Delete.
Prerequisites
To ensure proper application execution, the following privilege must be set:
- http://tizen.org/privilege/volume.set
Source Files
You can create and view the sample application project including the source files in the IDE.
The application uses a simple Model View (MV) architecture. The core part determines the architecture, and the application part determines the application behavior. The core.js file implements a simple Asynchronous Module Definition (AMD) and specifies how modules are defined.
File name | Description |
---|---|
config.xml | This file contains the application information for the platform to install and launch the application, including the view mode and the icon to be used in the device menu. |
css/ | This directory contains the CSS (Cascading Style Sheets) files used in the application. |
css/style.css | This file contains the CSS styling for the application UI. |
index.html | This is a starting file from which the application starts loading. It contains the layout of the application screens. |
js/ | This directory contains the application code. |
js/core/ | This directory contains the application framework. |
js/helpers/ui.js | This file contains the UI helper methods. |
js/models/ | This directory contains the application model modules. |
js/models/soundProfiles.js | This file contains the methods related to sound profile data. |
js/views/ | This directory contains the files implementing the application views. |
js/views/details.js | This file contains the methods related to the details screen UI. |
js/views/main.js | This file contains the methods related to the profiles screen UI. |
templates/ | This directory contains the templates for list items. |
Implementation
Defining the Application Layout
The application has 2 screens defined in the index.html file:
- Main screen displays a list of sound profiles.
The screen layout consists of a header, a list of profiles, and a footer with the Add button:
<!--index.html--> <div class="ui-page ui-page-active" id="main"> <header class="ui-header"> <h2 class="ui-title">Sound Manager</h2> </header> <div class="ui-content"> <ul class="ui-listview" id="profiles"></ul> </div> <footer class="ui-footer"> <a id="addProfileButton" class="ui-btn ui-btn-footer-icon btn-add">Add</a> </footer> </div>
The profile list rows are generated from the templates/listItem.tpl template file. The template uses as parameters the profile ID and name, and a Boolean flag indicating whether the profile is active.
<!--templates/listItem.tpl--> <li class="li-has-radio" data-profile-id="{{id}}"> <label>{{title}}</label> <input data-profile-id="{{id}}" type="radio" name="profile-item" {{?isActive}}checked="checked"{{/isActive}}/> </li>
- Details screen displays the volumes of all sound types for the selected sound profile.
The screen layout consists of a header with the profile title, a list of sound types, and a footer with the Reset and Delete buttons:
<!--index.html--> <div class="ui-page" id="details"> <header class="ui-header"> <h2 class="ui-title"></h2> </header> <div class="ui-content"> <ul class="ui-listview" id="soundTypes"></ul> </div> <footer class="ui-footer ui-grid-col-2"> <a id="reset" class="ui-btn ui-btn-footer-icon btn-reset">Reset</a> <a id="delete" class="ui-btn ui-btn-footer-icon btn-trash">Delete</a> </footer> </div>
The sound type list rows are generated from the templates/soundTypeItem.tpl template file, which uses the sound type name as a parameter:
<!--templates/soundTypeItem.tpl--> <li> <label for="{{name}}">{{name}}<span></span></label> <input id="{{name}}" type="range" min="0" max="10"> </li>
Initializing the Application
To initialize the application:
Define variables for holding the values of the currently active profile, and all the user's sound profiles:
/* js/models/soundProfile.js */ var currentProfile = {}, profiles = [],
Define an array that holds the IDs of all sound types, and a variable for the active profile ID (null, if no profile is activated):
SOUND_TYPES = [ 'SYSTEM', 'NOTIFICATION', 'ALARM', 'MEDIA', 'VOICE', 'RINGTONE' ] activeProfileId = null;
Fill the currentProfile object with the current values. You can obtain the system values of all sound types using the getVolume() method:
/* js/models/soundProfile.js */ function init() { var i = 0, soundType = null; for (i = 0; i < SOUND_TYPES.length; i += 1) { soundType = SOUND_TYPES[i]; try { currentProfile[soundType] = tizen.sound.getVolume(soundType); } catch (e) { console.error(e.message); } }
Register a volume change listener and define a callback to monitor and react to volume changes outside the application.
If the volume is changed from outside the application, the application must save the new volume value to the currentProfile object and deactivate the active profile, if any, by setting the activeProfileId variable to null.
try { tizen.sound.setVolumeChangeListener(onVolumeChanged); } catch (e) { console.error(e.message); } } function onVolumeChanged(soundType, volume) { if (currentProfile[soundType] !== volume) { currentProfile[soundType] = volume; if (activeProfileId !== null) { activeProfileId = null; event.fire('changed'); } } }
The sound profile is represented by an object with the following fields:
- id: Unique identifier of the profile
- title: Profile title
- XXX – Value of the XXX sound type, where XXX is one of the SOUND_TYPES array values
For example:
{ id: 1313, title: 'Custom Profile', SYSTEM: 0.1, NOTIFICATION: 0.2, ALARM: 0.3, MEDIA: 0.5, VOICE: 0, RINGTONE: 1 }
Adding a New Sound Profile
A new sound profile is added with the current system values when the user clicks Add and enters the profile name.
The new profile is a copy of the currentProfile object with 2 additional fields:
title: Profile name
id: Profile ID
/* js/models/soundProfile.js */ function createProfile(title) { var currentProfileCopy = JSON.parse(JSON.stringify(currentProfile)), id = profiles.length ? profiles[profiles.length - 1].id + 1 : 0; currentProfileCopy.title = title; currentProfileCopy.id = id; profiles.push(currentProfileCopy); /* Save the profiles array to local storage */ }
Setting the Changed Volume
The application sets the volume of the specified sound type when:
- The selected profile is activated:
To activate a profile, the user clicks the radio button of the profile on the main screen. The application reads the profile values and updates system sound settings with these values.
To retrieve a profile with the specified ID, use the getProfile() method:
/* js/models/soundProfile.js */ function getProfile(id) { var i = 0, profile = null; for (i = 0; i < profiles.length; i += 1) { profile = profiles[i]; if (profile.id === id) { return profile; } } return null; }
In the changeSystemSoundVolume() method, set the specified volume value to the specified sound type using the setVolume() method:
/* js/models/soundProfile.js */ function changeSystemSoundVolume(soundType, volume) { try { currentProfile[soundType] = volume; tizen.sound.setVolume(soundType, volume); } catch (e) { console.error('Setting ' + soundType + ' error: ' + e.message); } }
To fill the system sound settings with the volume values from the specified profile, use the changeSystemProfile() method:
/* js/models/soundProfile.js */ function changeSystemProfile(profile) { var i = 0, soundType = null; for (i = 0; i < SOUND_TYPES.length; i += 1) { soundType = SOUND_TYPES[i]; changeSystemSoundVolume(soundType, profile[soundType]); } }
To activate the profile with the specified ID, use the setActive() method:
/* js/models/soundProfile.js */ function setActive(id) { if (activeProfileId !== id) { changeSystemProfile(getProfile(id)); activeProfileId = id; } }
- The sound type value of the active profile changes:
If the user opens the active profile in the details screens and modifies its values, the change is applied to the system settings immediately. The updateProfile() method updates the specified sound type in the specified profile, provided it is the active profile. The method gets as parameters the ID of the profile, the name of the sound type, and the new value.
/* js/models/soundProfile.js */ function updateProfile(profileId, soundType, volume) { var profile = getProfile(profileId); if (profile) { profile[soundType] = volume; if (profile.id === activeProfileId) { changeSystemSoundVolume(soundType, volume); } } }
Deleting a Sound Profile
To delete the profile with the specified ID:
/* js/models/soundProfile.js */ function deleteProfile(id) { var index = getProfileIndex(id); if (index !== -1) { profiles.splice(index, 1); } } function getProfileIndex(profileId) { var i = 0; for (i = 0; i < profiles.length; i += 1) { if (profiles[i].id === profileId) { return i; } } return -1; }