πŸ“œ ⬆️ ⬇️

Using the system API in Sailfish OS

Introduction


Voice assistants in mobile devices do not stand still and are constantly evolving. Voice assistant for Sailfish OS, introduced last fall, is no exception and also acquires new functionality.

That article covered the basic principle of the internal work of the application. This material opens a series of two articles in which it will be discussed in more detail:
  1. Work with undocumented API for device management (current);
  2. Work with D-Bus interfaces provided by the operating system.

The current article describes how to control the screen brightness and system volume, as well as how to turn on and off Bluetooth and flight mode.

It is understood that the reader has already installed Sailfish OS SDK and developed applications using it.

How to get information


During development under Sailfish OS, it is impossible to do without documentation provided both on the official site and in the IDE. The documentation is written qualitatively, with examples, but not without flaw - it is short and covers only the basic functionality available to the programmer.
')
But Sailfish OS, like other operating systems, hides in itself more described in the documentation. You just need to know where to look. And you need to search in the source code, as in the most reliable source of information. The benefit of Sailfish OS is a fairly open software product based on GNU / Linux.

First you need to connect to the phone via SSH (Figure 1). To do this, you must allow the remote connection (1), set a password for it (2) and use one of the specified IP addresses (3). After the done actions, go to the /usr/share directory. This directory contains the interface codes and scripts of almost all applications installed on the phone.

Figure 1 - Setting up the connection to the phone via SSH.
[Figure 1 - Setting up the connection to the phone via SSH.]

Third-party application directories begin (in most cases) with the harbour prefix followed by the program identifier. Such a prefix avoids the possible intersection of names with system names. Catalogs of standard applications are accompanied by jolla and sailfish . The rest is related to system functions.

Figure 2 - Example application directories.
[Figure 2 - Example Application Directories.]

Adjust screen brightness


The screen brightness control refers to the user settings of the system, hence the interest is the /usr/share/jolla-settings , which contains the following objects:

From the list it is clear that in the indicated task it is required to refer to the pages directory. It is divided into subdirectories according to the types of settings: bluetooth , sounds , etc. The screen settings are located in the display directory. Therefore, /usr/share/jolla-settings/pages/display is the complete path relative to which the subsequent work will take place.

The first thing you do is search by keyword:
grep -H 'brightness' *
$ cd /usr/share/jolla-settings/pages/display
$ grep -H 'brightness' *
BrightnessSlider.qml: label: qsTrId("settings_display-la-brightness")
BrightnessSlider.qml: value: displaySettings.brightness
BrightnessSlider.qml: onValueChanged: displaySettings.brightness = Math.round(value)
BrightnessSlider.qml: onBrightnessChanged: slider.value = brightness
display.qml: id: brightnessSlider
display.qml: entryPath: "system_settings/look_and_feel/display/brightness_slider"
display.qml: text: qsTrId("settings_display-la-adaptive_brightness")


From the obtained results it can be seen that the screen brightness adjustment code is in the BrightnessSlider.qml file.

Next, you need to clarify exactly how control is performed:
grep -C 1 'displaySettings' ./BrightnessSlider.qml
$ grep -C 1 'displaySettings' ./BrightnessSlider.qml
label: qsTrId("settings_display-la-brightness")
maximumValue: displaySettings.maximumBrightness
minimumValue: 1
value: displaySettings.brightness
stepSize: 1

onValueChanged: displaySettings.brightness = Math.round(value)

DisplaySettings {
id: displaySettings
onBrightnessChanged: slider.value = brightness


After searching the file, it becomes obvious that to control the brightness of the device, you need to create a DisplaySettings object and change the brightness field value, taking into account that the minimum brightness value is one and the maximum is stored in the maximumBrightness field.

The final touch is to determine the required import:
grep 'import' ./BrightnessSlider.qml
$ grep 'import' ./BrightnessSlider.qml
import QtQuick 2.0
import Sailfish.Silica 1.0
import com.jolla.settings.system 1.0
import org.nemomobile.systemsettings 1.0


QtQuick and Sailfish.Silica are standard interface development modules and do not provide access to settings. com.jolla.settings.system contains internal objects for the settings application to work and is not of interest to other programs. It remains org.nemomobile.systemsettings , describing the necessary component.

Thus, it becomes possible to create your own screen brightness control for later inclusion in the project:
BrightnessControl.qml
 import QtQuick 2.0 import org.nemomobile.systemsettings 1.0 Item { id: brightnessControl /*     . * @param: value --   1 ()  maximumBrightness () */ function setBrightness(value) { if (value <= 1) setMinimumBrightness(); else if (value >= displaySettings.maximumBrightness) setMaximumBrightness(); else displaySettings.brightness = value; } /*  . * @param: percents --    . */ function increaseBrightness(percents) { setBrightness(displaySettings.brightness + _calcDelta(percents)) } /*  . * @param: percents --    . */ function decreaseBrightness(percents) { setBrightness(displaySettings.brightness - _calcDelta(percents)) } /*   . */ function setMinimumBrightness() { displaySettings.brightness = 1 } /*   . */ function setMaximumBrightness() { displaySettings.brightness = displaySettings.maximumBrightness } /*    . * @param: percents --    . * @return:      . */ function _calcDelta(percents) { return Math.round(displaySettings.maximumBrightness / 100 * percents) } DisplaySettings { id: displaySettings } } 


Adjusting the system volume


It uses the already known method of searching for information. Go to the /usr/share/jolla-settings/pages/sounds directory and check the keywords:
grep -i -C 1 -H 'volume' *
$ cd /usr/share/jolla-settings/pages/sounds
$ grep -i -C 1 -H 'volume' *
SoundsPage.qml-
SoundsPage.qml: VolumeSlider {
SoundsPage.qml: id: volumeSlider
SoundsPage.qml: property string entryPath: "system_settings/look_and_feel/sounds/ringer_volume"
SoundsPage.qml- width: parent.width
--
VolumeSlider.qml- height: implicitHeight + valueLabel.height + Theme.paddingSmall
VolumeSlider.qml: //% "Ringtone volume"
VolumeSlider.qml: label: qsTrId("settings_sounds_la_volume")
VolumeSlider.qml- maximumValue: 100
--
VolumeSlider.qml- if (!externalChange) {
VolumeSlider.qml: profileControl.ringerVolume = value
VolumeSlider.qml- profileControl.profile = (value > 0) ? "general" : "silent"
--
VolumeSlider.qml- slider.externalChange = true
VolumeSlider.qml: slider.value = profileControl.ringerVolume
VolumeSlider.qml- slider.externalChange = false
--
VolumeSlider.qml-
VolumeSlider.qml: onRingerVolumeChanged: {
VolumeSlider.qml- slider.externalChange = true
VolumeSlider.qml: slider.value = profileControl.ringerVolume
VolumeSlider.qml- slider.externalChange = false


The result of the command shows that the maximum allowable volume value is 100, the minimum is 0; and control is performed using the profileControl element, and requires not only specifying the volume value, but also switching the profile. We will get more detailed information about the mentioned element:
grep -C 1 'profileControl' ./VolumeSlider.qml
$ grep -C 1 'profileControl' ./VolumeSlider.qml
if (!externalChange) {
profileControl.ringerVolume = value
profileControl.profile = (value > 0) ? "general" : "silent"
}
--
slider.externalChange = true
slider.value = profileControl.ringerVolume
slider.externalChange = false
--
ProfileControl {
id: profileControl

--
slider.externalChange = true
slider.value = profileControl.ringerVolume
slider.externalChange = false
$ grep 'import' ./VolumeSlider.qml
import QtQuick 2.0
import Sailfish.Silica 1.0
import com.jolla.settings.system 1.0
import org.nemomobile.systemsettings 1.0


Based on the search results and information from the previous section, it becomes possible to implement a module to control the system volume:
VolumeControl.qml
 import QtQuick 2.0 import org.nemomobile.systemsettings 1.0 Item { id: volumeControl /*     . * @param: value --   0 ()  100 (). */ function setVolume(value) { if (value <= 0) { setMinimumVolume(); } else if (value >= 100) { setMaximumVolume(); } else { profileControl.ringerVolume = value; _setProfile(); } } /*  . * @param: percents --    . */ function increaseVolume(percents) { setVolume(profileControl.ringerVolume + percents) } /*  . * @param: percents --    . */ function decreaseVolume(percents) { setVolume(profileControl.ringerVolume - percents) } /*   . */ function setMinimumVolume() { profileControl.ringerVolume = 0; _setProfile(); } /*   . */ function setMaximumVolume() { profileControl.ringerVolume = 100; _setProfile(); } /*      . */ function _setProfile() { profileControl.profile = (profileControl.ringerVolume > 0) ? "general" : "silent" } ProfileControl { id: profileControl } } 


Here you should pay attention to the use of the general and silent keywords to control the sound profile of the system (main and silent, respectively). These are two reserved values ​​that determine the behavior of the system depending on the set volume value.

Toggle Flight Mode and Bluetooth


The principle of API search is absolutely identical to that described above, so we will proceed directly to the consideration of ready-made elements.

To control the flight mode, you need to connect the MeeGo.Connman module, which provides the NetworkManagerFactory component. By setting the value of the instance.offlineMode field of this object to true or false , it becomes possible to turn the specified mode on and off, respectively.
FlightControl.qml
 import QtQuick 2.0 import MeeGo.Connman 0.2 Item { id: flightControl /*   β€œ ”. */ function turnOnFlightMode() { connMgr.instance.offlineMode = true } /*   β€œ ”. */ function turnOffFlightMode() { connMgr.instance.offlineMode = false } /*   β€œ ”. */ function switchFlightMode() { connMgr.instance.offlineMode = !connMgr.instance.offlineMode } NetworkManagerFactory { id: connMgr } } 


To control the state of Bluetooth, the MeeGo.Connman module is also connected, but it uses the TechnologyModel component, the value of the field whose powered accepts is true or false to turn on or turn off Bluetooth, respectively. It is worth noting that the rest of the work with the interface is performed using standard Qt features .
BluetoothControl.qml
 import QtQuick 2.0 import MeeGo.Connman 0.2 Item { id: bluetoothControl /*  bluetooth. */ function turnOnBluetooth() { btTechModel.powered = true } /*  bluetooth. */ function turnOffBluetooth() { btTechModel.powered = false } /*  bluetooth. */ function switchBluetooth() { btTechModel.powered = !btTechModel.powered } TechnologyModel { id: btTechModel name: "bluetooth" } } 


Conclusion


This article shows one of the ways to search for undocumented features in Sailfish OS and presents code examples for controlling brightness, volume, Bluetooth, and flight mode. You can learn more about the implementation of these and other system settings management modules (as well as how to use them) on GitHub .

However, before you watch the finished code, try to independently implement and connect any module, and only then compare with the published example. You can, for example, try changing the design (search by ambience ) or system font size ( fontSize ), control Wi-Fi ( wifi ) or Internet sharing ( tethering ).

The next article will be devoted to what interfaces and functions D-Bus provides Sailfish OS to the programmer.

Questions and ideas arising in the course of development can always be discussed in the Telegram-chat and in the VKontakte group .

I express my gratitude to ragequit habraiser for an invitee, which gave the opportunity to publish this and subsequent articles.

Source: https://habr.com/ru/post/336278/


All Articles