Lot of work on HERE support. Almost working effects + GUI EQ

master
Nicolò Balzarotti 2017-10-09 23:36:35 +02:00
parent ac07ddc932
commit 6bdc4bbcab
24 changed files with 552 additions and 347 deletions

View File

@ -389,7 +389,7 @@
android:label="@string/title_activity_vibration"
android:parentActivityName=".activities.ControlCenterv2" />
<activity
android:name=".activities.AudioActivity"
android:name=".activities.AudioSettingsActivity"
android:label="@string/title_audio_activity"
android:parentActivityName=".activities.ControlCenterv2" />
<provider

View File

@ -1,67 +0,0 @@
/* Copyright (C) 2016-2017 Andreas Shimokawa, Carsten Pfeiffer
This file is part of Gadgetbridge.
Gadgetbridge is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gadgetbridge is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.activities;
import android.os.Bundle;
import android.widget.SeekBar;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.devices.here.HereConstants;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
public class AudioActivity extends AbstractGBActivity {
private static final Logger LOG = LoggerFactory.getLogger(AudioActivity.class);
private SeekBar seekBar;
private int volume;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.audio_settings);
LOG.info("Create");
seekBar = (SeekBar) findViewById(R.id.volume_seekbar);
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int position, boolean fromUser) {
// HERE's volume range is from 0xe3 (-22dB on their app) to 0xff (+6dB)
// 0xff - 0xe3 = 28 -> seekbar max value
// volume = seekbar + Min_volume (= 0xe3 = 227)
volume = position + 227;
LOG.debug("Volume = " + (byte)volume + " = " + volume + "= " + position);
GBApplication.deviceService().onSetAudioProperty(0, volume);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
}

View File

@ -0,0 +1,134 @@
/* Copyright (C) 2016-2017 Andreas Shimokawa, Carsten Pfeiffer
This file is part of Gadgetbridge.
Gadgetbridge is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gadgetbridge is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.activities;
import android.os.Bundle;
import android.view.View;
import android.widget.CheckedTextView;
import android.widget.SeekBar;
import android.widget.TextView;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.entities.AudioEffectType;
public class AudioSettingsActivity extends AbstractGBActivity {
private static final Logger LOG = LoggerFactory.getLogger(AudioSettingsActivity.class);
private SeekBar seekBar;
private TextView volume_text;
private CheckedTextView cbBassBoost;
private CheckedTextView cbNoiseMask;
// private boolean[] enabledEffects;
private int volume;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_audio_settings);
LOG.debug("Create Audio Setttings interface");
// All of this is because HERE can't handle more than 2 effects.
// You _can_ enable them, but the device will not be able to manage them in realtime
// and you'll get "Xruns". We prevent more than 2 simultaneous checks (like their app does)
// But it's commented out until I'll read the one already enabled. Else this is useless :D
/*enabledEffects = new boolean[] {
false // echo
, false // reverb
, false // noise mask
, false // fuzz
, false // flange
, false // bass boost
};*/
seekBar = (SeekBar) findViewById(R.id.volume_seekbar);
volume_text = (TextView) findViewById(R.id.volume_seekbar_volume);
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int position, boolean fromUser) {
// HERE's volume range is from 0xe3 (-22dB on their app) to 0xff (+6dB)
// 0xff - 0xe3 = 28 -> seekbar max value
// volume = seekbar + Min_volume (= 0xe3 = 227)
volume = position + 227;
// LOG.debug("Volume = " + (byte)volume + " = " + volume + "= " + position);
GBApplication.deviceService().onSetAudioProperty(AudioEffectType.VOLUME.getKey(),
new float[] {volume});
// Show the volume on the UI in dB (range -22;6)
volume_text.setText(" " + (position - 22) + " dB");
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
// FIXME: we need to read the current value and display this.
// right now, I'm just showing 0 dB, Called after changeListener sets the value on
// the device too.
seekBar.setProgress(22);
cbBassBoost = (CheckedTextView) findViewById(R.id.audio_effect_bassboost);
cbBassBoost.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
((CheckedTextView) v).toggle();
LOG.info("Enabled bassBoost");
applyEffect(AudioEffectType.BASSBOOST, ((CheckedTextView) v).isChecked());
}
});
cbNoiseMask = (CheckedTextView) findViewById(R.id.audio_effect_noisemask);
cbNoiseMask.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
((CheckedTextView) v).toggle();
LOG.info("Enabled noisemask");
applyEffect(AudioEffectType.NOISEMASK, ((CheckedTextView) v).isChecked());
}
});
cbNoiseMask = (CheckedTextView) findViewById(R.id.audio_effect_echo);
cbNoiseMask.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
((CheckedTextView) v).toggle();
LOG.info("Enabled echo");
applyEffect(AudioEffectType.ECHO, ((CheckedTextView) v).isChecked());
}
});
}
void applyEffect(AudioEffectType effect, boolean enable) {
GBApplication.deviceService().onSetAudioProperty(
effect.getId(),
new float[] {
enable ? 1.0f : 0.0f,
// FIXME: add other params?
});
}
}

View File

@ -42,12 +42,11 @@ import android.widget.Toast;
import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.GBEnvironment;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.ConfigureAlarms;
import nodomain.freeyourgadget.gadgetbridge.activities.VibrationActivity;
import nodomain.freeyourgadget.gadgetbridge.activities.charts.ChartsActivity;
import nodomain.freeyourgadget.gadgetbridge.activities.AudioActivity;
import nodomain.freeyourgadget.gadgetbridge.activities.AudioSettingsActivity;
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceManager;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
@ -221,7 +220,7 @@ public class GBDeviceAdapterv2 extends RecyclerView.Adapter<GBDeviceAdapterv2.Vi
public void onClick(View v) {
showTransientSnackbar(R.string.controlcenter_snackbar_requested_screenshot);
Intent startIntent;
startIntent = new Intent(context, AudioActivity.class);
startIntent = new Intent(context, AudioSettingsActivity.class);
startIntent.putExtra(GBDevice.EXTRA_DEVICE, device);
context.startActivity(startIntent);
}

View File

@ -22,6 +22,7 @@ import android.net.Uri;
import java.util.ArrayList;
import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.entities.AudioEffectType;
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec;
import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
@ -79,7 +80,7 @@ public interface EventHandler {
void onSetConstantVibration(int integer);
void onSetAudioProperty(int property, int volume);
void onSetAudioProperty(int property, float[] params);
void onScreenshotReq();

View File

@ -22,4 +22,5 @@ public final class HereConstants {
public static final UUID UUID_VOLUME = UUID.fromString(String.format(BASE_HERE_UUID, "e7"));
// TODO: Put device in sleep mode, (byte)0x00 sleep, (byte)0x01 wake
public static final UUID UUID_SLEEP = UUID.fromString(String.format(BASE_HERE_UUID, "eb"));
public static final UUID UUID_EFFECTS = UUID.fromString(String.format(BASE_HERE_UUID, "e9"));
}

View File

@ -23,8 +23,7 @@ import android.net.Uri;
import android.support.annotation.NonNull;
import nodomain.freeyourgadget.gadgetbridge.GBException;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.AudioActivity;
import nodomain.freeyourgadget.gadgetbridge.activities.AudioSettingsActivity;
import nodomain.freeyourgadget.gadgetbridge.devices.AbstractDeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler;
import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider;
@ -72,7 +71,7 @@ public class HereCoordinator extends AbstractDeviceCoordinator {
@Override
public Class<? extends Activity> getPrimaryActivity() {
return AudioActivity.class;
return AudioSettingsActivity.class;
}
@Override

View File

@ -33,6 +33,7 @@ import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.entities.AudioEffectType;
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec;
import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
@ -305,10 +306,11 @@ public class GBDeviceService implements DeviceService {
}
@Override
public void onSetAudioProperty(int property, int intensity) {
public void onSetAudioProperty(int property, float[] params) {
// volume = 0
Intent intent = createIntent().setAction(ACTION_SET_AUDIO_PROPERTY)
.putExtra(EXTRA_AUDIO_PROPERTY, intensity);
.putExtra(EXTRA_AUDIO_PROPERTY, property)
.putExtra(EXTRA_AUDIO_PARAMS, params);
invokeService(intent);
}

View File

@ -20,6 +20,7 @@ package nodomain.freeyourgadget.gadgetbridge.model;
import android.support.annotation.Nullable;
import nodomain.freeyourgadget.gadgetbridge.devices.EventHandler;
import nodomain.freeyourgadget.gadgetbridge.entities.AudioEffectType;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService;
@ -78,6 +79,7 @@ public interface DeviceService extends EventHandler {
String EXTRA_FIND_START = "find_start";
String EXTRA_VIBRATION_INTENSITY = "vibration_intensity";
String EXTRA_AUDIO_PROPERTY = "audio_property";
String EXTRA_AUDIO_PARAMS = "audio_params";
String EXTRA_CALL_COMMAND = "call_command";
String EXTRA_CALL_PHONENUMBER = "call_phonenumber";
String EXTRA_CALL_DISPLAYNAME = "call_displayname";
@ -154,4 +156,6 @@ public interface DeviceService extends EventHandler {
* from the service will be reported.
*/
void requestDeviceInfo();
void onSetAudioProperty(int property, float[] params);
}

View File

@ -105,6 +105,7 @@ import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_ST
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_STARTAPP;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_TEST_NEW_FUNCTION;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_ALARMS;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_AUDIO_PARAMS;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_AUDIO_PROPERTY;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_APP_CONFIG;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_APP_START;
@ -431,8 +432,12 @@ public class DeviceCommunicationService extends Service implements SharedPrefere
}
case ACTION_SET_AUDIO_PROPERTY: {
LOG.info(mDeviceSupport.getDevice().toString());
int volume = intent.getIntExtra(EXTRA_AUDIO_PROPERTY, 0);
mDeviceSupport.onSetAudioProperty(0, volume);
int property = intent.getIntExtra(EXTRA_AUDIO_PROPERTY, 999);
float [] params = intent.getFloatArrayExtra(EXTRA_AUDIO_PARAMS);
LOG.debug(" "+property);
LOG.debug(""+params[0]);
mDeviceSupport.onSetAudioProperty(property, params);
LOG.debug("Called");
break;
}
case ACTION_CALLSTATE:

View File

@ -28,6 +28,7 @@ import java.util.ArrayList;
import java.util.EnumSet;
import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.entities.AudioEffectType;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec;
@ -153,8 +154,8 @@ public class ServiceDeviceSupport implements DeviceSupport {
}
@Override
public void onSetAudioProperty(int property, int intensity) {
delegate.onSetAudioProperty(property, intensity);
public void onSetAudioProperty(int property, float [] params) {
delegate.onSetAudioProperty(property, params);
}
@Override

View File

@ -18,25 +18,19 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.here;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import static nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEDeviceSupport.BASE_UUID;
import android.net.Uri;
import android.widget.Toast;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Arrays;
import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventBatteryInfo;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventVersionInfo;
import nodomain.freeyourgadget.gadgetbridge.devices.here.HereConstants;
import nodomain.freeyourgadget.gadgetbridge.entities.AudioEffectType;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec;
@ -48,8 +42,6 @@ import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec;
import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEDeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
public class HereSupport extends AbstractBTLEDeviceSupport {
@ -59,7 +51,7 @@ public class HereSupport extends AbstractBTLEDeviceSupport {
public BluetoothGattCharacteristic infoCharacteristic = null;
public BluetoothGattCharacteristic fwCharacteristic = null;
public BluetoothGattCharacteristic volumeCharacteristic = null;
public BluetoothGattCharacteristic effectCharacteristic = null;
private final GBDeviceEventVersionInfo versionCmd = new GBDeviceEventVersionInfo();
private final GBDeviceEventBatteryInfo batteryCmd = new GBDeviceEventBatteryInfo();
@ -67,7 +59,7 @@ public class HereSupport extends AbstractBTLEDeviceSupport {
super(LOG);
addSupportedService(HereConstants.UUID_BATTERY_VALUE);
addSupportedService(HereConstants.UUID_CHARACTERISTIC_INFO);
addSupportedService(HereConstants.UUID_AUDIO_SETTINGS);
addSupportedService(HereConstants.UUID_AUDIO_SETTINGS);
}
@Override
@ -80,14 +72,15 @@ public class HereSupport extends AbstractBTLEDeviceSupport {
batteryCharacteristic = getCharacteristic(HereConstants.UUID_CHARACTERISTIC_BATTERY);
infoCharacteristic = getCharacteristic(HereConstants.UUID_CHARACTERISTIC_INFO);
fwCharacteristic = getCharacteristic(HereConstants.UUID_CHARACTERISTIC_INFO);
volumeCharacteristic = getCharacteristic(HereConstants.UUID_VOLUME);
volumeCharacteristic = getCharacteristic(HereConstants.UUID_VOLUME);
effectCharacteristic = getCharacteristic(HereConstants.UUID_EFFECTS);
builder.setGattCallback(this);
builder.notify(batteryCharacteristic, true);
builder.read(fwCharacteristic);
syncSettings(builder);
// fw = builder.read(infoCharacteristic);
// fw = builder.read(infoCharacteristic);
gbDevice.setState(GBDevice.State.INITIALIZED);
gbDevice.sendDeviceUpdateIntent(getContext());
@ -114,112 +107,24 @@ public class HereSupport extends AbstractBTLEDeviceSupport {
handleGBDeviceEvent(batteryCmd);
return true;
} else if (HereConstants.UUID_FW_VERSION.equals(characteristicUUID)) {
LOG.info("Device info: " + (short)data[0]);
LOG.info("Device info: " + (short) data[0]);
LOG.info("Device info: " + data);
versionCmd.fwVersion = String.format("%s", data);
handleGBDeviceEvent(versionCmd);
} else {
return true;
} else {
return true;
}
return true;
}
private void syncDateAndTime(TransactionBuilder builder) {
// Calendar cal = Calendar.getInstance();
// String strYear = String.valueOf(cal.get(Calendar.YEAR));
// byte year1 = (byte)Integer.parseInt(strYear.substring(0, 2));
// byte year2 = (byte)Integer.parseInt(strYear.substring(2, 4));
// byte month = (byte)cal.get(Calendar.MONTH);
// byte day = (byte)cal.get(Calendar.DAY_OF_MONTH);
// byte hour = (byte)cal.get(Calendar.HOUR_OF_DAY);
// byte minute = (byte)cal.get(Calendar.MINUTE);
// byte second = (byte)cal.get(Calendar.SECOND);
// byte weekDay = (byte)cal.get(Calendar.DAY_OF_WEEK);
// builder.write(ctrlCharacteristic, commandWithChecksum(
// HereConstants.CMD_SET_DATE_AND_TIME,
// (year1 << 24) | (year2 << 16) | (month << 8) | day,
// (hour << 24) | (minute << 16) | (second << 8) | weekDay
// ));
private void syncDateAndTime(TransactionBuilder builder) {
}
private void syncSettings(TransactionBuilder builder) {
// syncDateAndTime(builder);
// // TODO: unhardcode and separate stuff
// builder.write(ctrlCharacteristic, commandWithChecksum(
// HereConstants.CMD_SET_HEARTRATE_WARNING_VALUE, 0, 152
// ));
// builder.write(ctrlCharacteristic, commandWithChecksum(
// HereConstants.CMD_SET_TARGET_STEPS, 0, 10000
// ));
// builder.write(ctrlCharacteristic, commandWithChecksum(
// HereConstants.CMD_GET_STEP_COUNT, 0, 0
// ));
// builder.write(ctrlCharacteristic, commandWithChecksum(
// HereConstants.CMD_GET_SLEEP_TIME, 0, 0
// ));
// builder.write(ctrlCharacteristic, commandWithChecksum(
// HereConstants.CMD_SET_NOON_TIME, 12 * 60 * 60, 14 * 60 * 60 // 12:00 - 14:00
// ));
// builder.write(ctrlCharacteristic, commandWithChecksum(
// HereConstants.CMD_SET_SLEEP_TIME, 21 * 60 * 60, 8 * 60 * 60 // 21:00 - 08:00
// ));
// builder.write(ctrlCharacteristic, commandWithChecksum(
// HereConstants.CMD_SET_INACTIVITY_WARNING_TIME, 0, 0
// ));
// // do not disturb and a couple more features
// byte dndStartHour = 22;
// byte dndStartMin = 0;
// byte dndEndHour = 8;
// byte dndEndMin = 0;
// boolean dndToggle = false;
// boolean vibrationToggle = true;
// boolean wakeOnRaiseToggle = true;
// builder.write(ctrlCharacteristic, commandWithChecksum(
// HereConstants.CMD_SET_DND_SETTINGS,
// (dndStartHour << 24) | (dndStartMin << 16) | (dndEndHour << 8) | dndEndMin,
// ((dndToggle ? 0 : 1) << 2) | ((vibrationToggle ? 1 : 0) << 1) | (wakeOnRaiseToggle ? 1 : 0)
// ));
}
private void showNotification(byte icon, String title, String message) {
// try {
// TransactionBuilder builder = performInitialized("ShowNotification");
// byte[] titleBytes = stringToUTF8Bytes(title, 16);
// byte[] messageBytes = stringToUTF8Bytes(message, 80);
// for (int i = 1; i <= 7; i++)
// {
// byte[] currentPacket = new byte[20];
// currentPacket[0] = HereConstants.CMD_ACTION_SHOW_NOTIFICATION;
// currentPacket[1] = 7;
// currentPacket[2] = (byte)i;
// switch(i) {
// case 1:
// currentPacket[4] = icon;
// break;
// case 2:
// if (titleBytes != null) {
// System.arraycopy(titleBytes, 0, currentPacket, 3, 6);
// System.arraycopy(titleBytes, 6, currentPacket, 10, 10);
// }
// break;
// default:
// if (messageBytes != null) {
// System.arraycopy(messageBytes, 16 * (i - 3), currentPacket, 3, 6);
// System.arraycopy(messageBytes, 6 + 16 * (i - 3), currentPacket, 10, 10);
// }
// break;
// }
// builder.write(ctrlCharacteristic, currentPacket);
// }
// performConnected(builder.getTransaction());
// } catch (IOException e) {
// LOG.warn(e.getMessage());
// }
}
@Override
@ -229,27 +134,6 @@ public class HereSupport extends AbstractBTLEDeviceSupport {
@Override
public void onNotification(NotificationSpec notificationSpec) {
// String notificationTitle = StringUtils.getFirstOf(notificationSpec.sender, notificationSpec.title);
// byte icon;
// switch (notificationSpec.type) {
// case GENERIC_SMS:
// icon = HereConstants.ICON_SMS;
// break;
// case FACEBOOK:
// case FACEBOOK_MESSENGER:
// icon = HereConstants.ICON_FACEBOOK;
// break;
// case TWITTER:
// icon = HereConstants.ICON_TWITTER;
// break;
// case WHATSAPP:
// icon = HereConstants.ICON_WHATSAPP;
// break;
// default:
// icon = HereConstants.ICON_LINE;
// break;
// }
// showNotification(icon, notificationTitle, notificationSpec.body);
}
@Override
@ -259,57 +143,14 @@ public class HereSupport extends AbstractBTLEDeviceSupport {
@Override
public void onSetAlarms(ArrayList<? extends Alarm> alarms) {
// try {
// TransactionBuilder builder = performInitialized("SetAlarms");
// for (int i = 0; i < alarms.size(); i++)
// {
// byte cmd;
// switch (i) {
// case 0:
// cmd = HereConstants.CMD_SET_ALARM_1;
// break;
// case 1:
// cmd = HereConstants.CMD_SET_ALARM_2;
// break;
// case 2:
// cmd = HereConstants.CMD_SET_ALARM_3;
// break;
// default:
// return;
// }
// Calendar cal = alarms.get(i).getAlarmCal();
// builder.write(ctrlCharacteristic, commandWithChecksum(
// cmd,
// alarms.get(i).isEnabled() ? cal.get(Calendar.HOUR_OF_DAY) : -1,
// alarms.get(i).isEnabled() ? cal.get(Calendar.MINUTE) : -1
// ));
// }
// performConnected(builder.getTransaction());
// GB.toast(getContext(), "Alarm settings applied - do note that the current device does not support day specification", Toast.LENGTH_LONG, GB.INFO);
// } catch(IOException e) {
// LOG.warn(e.getMessage());
// }
}
@Override
public void onSetTime() {
// try {
// TransactionBuilder builder = performInitialized("SetTime");
// syncDateAndTime(builder);
// performConnected(builder.getTransaction());
// } catch(IOException e) {
// LOG.warn(e.getMessage());
// }
}
@Override
public void onSetCallState(CallSpec callSpec) {
// switch (callSpec.command) {
// case CallSpec.CALL_INCOMING:
// showNotification(HereConstants.ICON_CALL, callSpec.name, callSpec.number);
// break;
// }
}
@Override
@ -318,22 +159,62 @@ public class HereSupport extends AbstractBTLEDeviceSupport {
}
@Override
public void onSetAudioProperty(int property, int volume) {
TransactionBuilder builder = new TransactionBuilder("volume");
LOG.info("setting audio");
switch (property) {
case 0: // volume
LOG.info("setting volume to "+volume);
public void onSetAudioProperty(int property, float[] params) {
AudioEffectType effect = AudioEffectType.getByEffectId(property);
TransactionBuilder builder = createTransactionBuilder("SetAudio");
switch (effect) {
case VOLUME: // volume
LOG.info("Setting the audio volume");
if (params.length != 1) {
LOG.error("Wrong number of params");
break;
}
// Only one param, the volume (int)
int volume = (int) params[0];
builder.write(volumeCharacteristic, new byte[]{(byte) volume});
builder.queue(getQueue());
break;
case ECHO:
case REVERB:
case NOISEMASK:
case FUZZ:
case FLANGE:
case BASSBOOST:
/*if (params.length < 2) {
LOG.error("Wrong number of params");
break;
}*/
// Bt dump: 81 (00 00 00) (9a99993e) (cdcccc3e)
// We add as a first param a boolean (enable/disable)
boolean enable = params[0] == 1.0; // 1.0 is true, other false
// float[] audioparams = Arrays.copyOfRange(params,1,params.length-1);
// enable with 80 + effect_id,
// disable with effect_id
byte[] message;
if (!enable) {
LOG.info("Disabling the " + effect.name() + " effect");
// To disable an effect, you just need to transmit its effect id
message = new byte[] {(byte) effect.getId()};
} else {
LOG.info("Enabling the " + effect.name() + " effect");
message = createMessage(effect);
}
builder.write(effectCharacteristic, message);
break;
case EQ:
LOG.info("Enabling the EQ effect");
LOG.warn("Still not implemented");
break;
default:
LOG.warn("Programming error! non-existent audio effect value");
break;
}
builder.queue(getQueue());
}
@Override
public void onSetMusicState(MusicStateSpec stateSpec) {
}
@Override
@ -383,42 +264,14 @@ public class HereSupport extends AbstractBTLEDeviceSupport {
@Override
public void onReboot() {
// try {
// TransactionBuilder builder = performInitialized("Reboot");
// builder.write(ctrlCharacteristic, commandWithChecksum(
// HereConstants.CMD_ACTION_REBOOT_DEVICE, 0, 0
// ));
// performConnected(builder.getTransaction());
// } catch(Exception e) {
// LOG.warn(e.getMessage());
// }
}
@Override
public void onHeartRateTest() {
// try {
// TransactionBuilder builder = performInitialized("HeartRateTest");
// builder.write(ctrlCharacteristic, commandWithChecksum(
// HereConstants.CMD_ACTION_HEARTRATE_SWITCH, 0, 1
// ));
// performConnected(builder.getTransaction());
// } catch(Exception e) {
// LOG.warn(e.getMessage());
// }
}
@Override
public void onEnableRealtimeHeartRateMeasurement(boolean enable) {
// // TODO: test
// try {
// TransactionBuilder builder = performInitialized("RealTimeHeartMeasurement");
// builder.write(ctrlCharacteristic, commandWithChecksum(
// HereConstants.CMD_SET_HEARTRATE_AUTO, 0, enable ? 1 : 0
// ));
// performConnected(builder.getTransaction());
// } catch(Exception e) {
// LOG.warn(e.getMessage());
// }
}
@Override
@ -465,48 +318,93 @@ public class HereSupport extends AbstractBTLEDeviceSupport {
}
// private byte[] commandWithChecksum(byte cmd, int argSlot1, int argSlot2)
// {
// // ByteBuffer buf = ByteBuffer.allocate(10);
// // buf.put(cmd);
// // buf.putInt(argSlot1);
// // buf.putInt(argSlot2);
// TODO: USE THIS
// private byte[] effectMessage(int id, int padding, float [] params) {};
// // byte[] bytesToWrite = buf.array();
private byte[] createMessage(AudioEffectType effect) {
byte [] message;
// TODO: replace this with FloatToReverseIEE754
switch (effect) {
case ECHO:
message = new byte[]{
(byte) (effect.getId() + 0x80),
(byte) 0x00, (byte) 0x00, (byte) 0x00, // padding
(byte) 0x9a, (byte) 0x99, (byte) 0x99, (byte) 0x3e, // 0.3
(byte) 0xcd, (byte) 0xcc, (byte) 0xcc, (byte) 0x3e // 0.4
};
break;
// // byte checksum = 0;
// // for (byte b : bytesToWrite) {
// // checksum += b;
// // }
case REVERB:
message = new byte[]{
(byte) (effect.getId() + 0x80),
(byte) 0x00, (byte) 0x00, (byte) 0x00, // padding
(byte) 0x66, (byte) 0x66, (byte) 0xe6, (byte) 0x3f,
(byte) 0x9a, (byte) 0x99, (byte) 0x99, (byte) 0x3f,
(byte) 0x8f, (byte) 0xc2, (byte) 0x75, (byte) 0x3c
};
break;
// // bytesToWrite[9] = checksum;
case NOISEMASK:
message = new byte[]{
(byte) (effect.getId() + 0x80),
(byte) 0x00, (byte) 0x00, (byte) 0x00, // padding
(byte) 0xcd, (byte) 0xcc, (byte) 0xcc, (byte) 0x3d,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x79, (byte) 0x59, (byte) 0x82, (byte) 0xd0
};
break;
// ByteBuffer buf = ByteBuffer.allocate(10);
// return buf;
// }
case FUZZ:
message = new byte[]{
(byte) (effect.getId() + 0x80),
(byte) 0x00, (byte) 0x00, (byte) 0x00, // padding
(byte) 0xcd, (byte) 0xcc, (byte) 0x4c, (byte) 0x3d,
(byte) 0x0a, (byte) 0xd7, (byte) 0xa3, (byte) 0x3c,
(byte) 0x0a, (byte) 0xd7, (byte) 0xa3, (byte) 0x3c,
(byte) 0x00, (byte) 0x00, (byte) 0x70, (byte) 0x42
};
break;
private byte[] stringToUTF8Bytes(String src, int byteCount) {
// try {
// if (src == null)
// return null;
case FLANGE:
message = new byte[] {
(byte) (effect.getId() + 0x80),
(byte) 0xcc, (byte) 0x5c, (byte) 0x00, // 0.3625 (fixed point ?fract24)
(byte) 0xbc, (byte) 0x74, (byte) 0x13, (byte) 0x3c,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x33, (byte) 0x33, (byte) 0x33, (byte) 0x3f,
(byte) 0x00, (byte) 0x00, (byte) 0x80, (byte) 0x3f
};
break;
// for (int i = src.length(); i > 0; i--) {
// String sub = src.substring(0, i);
// byte[] subUTF8 = sub.getBytes("UTF-8");
case BASSBOOST:
message = new byte[]{
(byte) (effect.getId() + 0x80),
(byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x20, (byte) 0xc1,
(byte) 0x00, (byte) 0x00, (byte) 0x20, (byte) 0x41
};
break;
// if (subUTF8.length == byteCount) {
// return subUTF8;
// }
// if (subUTF8.length < byteCount) {
// byte[] largerSubUTF8 = new byte[byteCount];
// System.arraycopy(subUTF8, 0, largerSubUTF8, 0, subUTF8.length);
// return largerSubUTF8;
// }
// }
// } catch (UnsupportedEncodingException e) {
// LOG.warn(e.getMessage());
// }
return null;
default:
LOG.warn("Programming error! Enabled a non-existent effect (" +
effect.name()
+ "!");
message = new byte[]{};
}
return message;
}
static byte[] FloatToReverseIEE754(float value) {
// Thanks to Maldivia on IRC #java
// and to https://stackoverflow.com/questions/2183240/java-integer-to-byte-array#2183279
int i = Float.floatToRawIntBits(value);
i = (i << 9) | (i >>> 23) & 0x1ff;
return new byte [] {
(byte)(i >>> 24),
(byte)(i >>> 16),
(byte)(i >>> 8),
(byte) value
};
}
}

View File

@ -49,6 +49,7 @@ import nodomain.freeyourgadget.gadgetbridge.activities.SettingsActivity;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventBatteryInfo;
import nodomain.freeyourgadget.gadgetbridge.devices.hplus.HPlusConstants;
import nodomain.freeyourgadget.gadgetbridge.devices.hplus.HPlusCoordinator;
import nodomain.freeyourgadget.gadgetbridge.entities.AudioEffectType;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec;
@ -432,7 +433,7 @@ public class HPlusSupport extends AbstractBTLEDeviceSupport {
}
@Override
public void onSetAudioProperty(int property, int volume) {
public void onSetAudioProperty(int property, float[] params) {
}

View File

@ -34,6 +34,7 @@ import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventBatteryInfo;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventVersionInfo;
import nodomain.freeyourgadget.gadgetbridge.devices.jyou.JYouConstants;
import nodomain.freeyourgadget.gadgetbridge.entities.AudioEffectType;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec;
@ -317,7 +318,7 @@ public class TeclastH30Support extends AbstractBTLEDeviceSupport {
}
@Override
public void onSetAudioProperty(int property, int volume) {
public void onSetAudioProperty(int property, float[] params) {
}

View File

@ -21,6 +21,7 @@ import android.net.Uri;
import java.util.ArrayList;
import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.entities.AudioEffectType;
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec;
import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
@ -106,7 +107,7 @@ public class LiveviewSupport extends AbstractSerialDeviceSupport {
}
@Override
public void onSetAudioProperty(int property, int volume) {
public void onSetAudioProperty(int property, float[] params) {
}
@Override

View File

@ -52,6 +52,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandFWHelper;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandSampleProvider;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandService;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.VibrationProfile;
import nodomain.freeyourgadget.gadgetbridge.entities.AudioEffectType;
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
import nodomain.freeyourgadget.gadgetbridge.entities.MiBandActivitySample;
@ -453,7 +454,7 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
}
@Override
public void onSetAudioProperty(int property, int volume) {
public void onSetAudioProperty(int property, float[] params) {
}

View File

@ -63,6 +63,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandService;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.VibrationProfile;
import nodomain.freeyourgadget.gadgetbridge.entities.AudioEffectType;
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
import nodomain.freeyourgadget.gadgetbridge.entities.MiBandActivitySample;
@ -664,7 +665,7 @@ public class MiBand2Support extends AbstractBTLEDeviceSupport {
}
@Override
public void onSetAudioProperty(int property, int volume) {
public void onSetAudioProperty(int property, float[] params) {
}

View File

@ -42,6 +42,7 @@ import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventBatteryInf
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventVersionInfo;
import nodomain.freeyourgadget.gadgetbridge.devices.no1f1.No1F1Constants;
import nodomain.freeyourgadget.gadgetbridge.devices.no1f1.No1F1SampleProvider;
import nodomain.freeyourgadget.gadgetbridge.entities.AudioEffectType;
import nodomain.freeyourgadget.gadgetbridge.entities.No1F1ActivitySample;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
@ -356,7 +357,7 @@ public class No1F1Support extends AbstractBTLEDeviceSupport {
}
@Override
public void onSetAudioProperty(int property, int volume) {
public void onSetAudioProperty(int property, float[] params) {
}

View File

@ -31,6 +31,7 @@ import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.SettingsActivity;
import nodomain.freeyourgadget.gadgetbridge.entities.AudioEffectType;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec;
@ -128,7 +129,7 @@ public class PebbleSupport extends AbstractSerialDeviceSupport {
}
@Override
public void onSetAudioProperty(int property, int volume) {
public void onSetAudioProperty(int property, float[] params) {
}

View File

@ -186,7 +186,7 @@ public class VibratissimoSupport extends AbstractBTLEDeviceSupport {
}
@Override
public void onSetAudioProperty(int property, int volume) {
public void onSetAudioProperty(int property, float [] params) {
}

View File

@ -0,0 +1,220 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerHorizontal="false"
android:orientation="vertical"
android:layout_centerInParent="false"
android:layout_centerVertical="false"
android:weightSum="1">
<SeekBar
android:id="@+id/volume_seekbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="28"
android:scaleY="4.0" />
<LinearLayout
android:id="@+id/audio_volume_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:baselineAligned="false"
android:orientation="horizontal">
<TextView
android:id="@+id/volume_seekbar_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/audio_volume"/>
<TextView
android:id="@+id/volume_seekbar_volume"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
<LinearLayout
android:id="@+id/audio_effect_selector"
android:layout_width="387dp"
android:layout_height="wrap_content"
android:baselineAligned="false"
android:orientation="horizontal">
<android.support.v7.widget.AppCompatCheckedTextView
android:id="@+id/audio_effect_echo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:layout_weight="1"
android:drawableTop="?android:attr/listChoiceIndicatorMultiple"
android:gravity="center"
android:text="@string/audio_effect_echo"
android:textAppearance="?android:attr/textAppearanceSmall" />
<android.support.v7.widget.AppCompatCheckedTextView
android:id="@+id/audio_effect_reverb"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:layout_weight="1"
android:drawableTop="?android:attr/listChoiceIndicatorMultiple"
android:gravity="center"
android:text="@string/audio_effect_reverb"
android:textAppearance="?android:attr/textAppearanceSmall" />
<android.support.v7.widget.AppCompatCheckedTextView
android:id="@+id/audio_effect_noisemask"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:layout_weight="1"
android:drawableTop="?android:attr/listChoiceIndicatorMultiple"
android:gravity="center"
android:text="@string/audio_effect_noisemask"
android:textAppearance="?android:attr/textAppearanceSmall" />
<android.support.v7.widget.AppCompatCheckedTextView
android:id="@+id/audio_effect_fuzz"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:layout_weight="1"
android:drawableTop="?android:attr/listChoiceIndicatorMultiple"
android:gravity="center"
android:text="@string/audio_effect_fuzz"
android:textAppearance="?android:attr/textAppearanceSmall" />
<android.support.v7.widget.AppCompatCheckedTextView
android:id="@+id/audio_effect_flange"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:layout_weight="1"
android:drawableTop="?android:attr/listChoiceIndicatorMultiple"
android:gravity="center"
android:text="@string/audio_effect_flange"
android:textAppearance="?android:attr/textAppearanceSmall" />
<android.support.v7.widget.AppCompatCheckedTextView
android:id="@+id/audio_effect_bassboost"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:layout_weight="1"
android:drawableTop="?android:attr/listChoiceIndicatorMultiple"
android:gravity="center"
android:text="@string/audio_effect_bassboost"
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
<TextView
android:id="@+id/audio_equalizer_text"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:gravity="center"
android:text="@string/audio_equalizer"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:baselineAligned="false"
android:orientation="horizontal"
android:weightSum="1">
<SeekBar
android:id="@+id/equalizer_band_0"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:max="30"
android:scaleY="2.0"
android:layout_weight="1.0" />
<TextView
android:id="@+id/equalizer_band_0_text"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@string/equalizer_band_0"
/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:baselineAligned="false"
android:orientation="horizontal"
android:weightSum="1">
<SeekBar
android:id="@+id/equalizer_band_1"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:max="30"
android:scaleY="2.0"
android:layout_weight="1.0" />
<TextView
android:id="@+id/equalizer_band_1_text"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@string/equalizer_band_1"
/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:baselineAligned="false"
android:orientation="horizontal"
android:weightSum="1">
<SeekBar
android:id="@+id/equalizer_band_2"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:max="30"
android:scaleY="2.0"
android:layout_weight="1.0" />
<TextView
android:id="@+id/equalizer_band_2_text"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@string/equalizer_band_2"
/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:baselineAligned="false"
android:orientation="horizontal"
android:weightSum="1">
<SeekBar
android:id="@+id/equalizer_band_3"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:max="30"
android:scaleY="2.0"
android:layout_weight="1.0" />
<TextView
android:id="@+id/equalizer_band_3_text"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@string/equalizer_band_3"
/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:baselineAligned="false"
android:orientation="horizontal"
android:weightSum="1">
<SeekBar
android:id="@+id/equalizer_band_4"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:max="30"
android:scaleY="2.0"
android:layout_weight="1.0" />
<TextView
android:id="@+id/equalizer_band_4_text"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@string/equalizer_band_4"
/>
</LinearLayout>
</LinearLayout>

View File

@ -1,16 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerHorizontal="false"
android:layout_centerInParent="false"
android:layout_centerVertical="false"
android:weightSum="1">
<SeekBar
android:id="@+id/volume_seekbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="28"
android:scaleY="4.0" />
</LinearLayout>

View File

@ -396,4 +396,7 @@
<string name="discovery_trying_to_connect_to">Tentativo di connessione con: %1$s</string>
<string name="discovery_enable_bluetooth">Abilitare Bluetooth per l\'individuazione dei dispositivi.</string>
<string name="discovery_dont_pair">Non connettersi</string>
<string name="audio_effect_echo">Echo</string>
<string name="audio_volume">Volume</string>
<string name="audio_effect_fuzz">Fuzz</string>
</resources>

View File

@ -476,4 +476,18 @@
<string name="_pebble_watch_mute">Mute</string>
<string name="_pebble_watch_reply">Reply</string>
<string name="title_audio_activity">Audio Settings</string>
<string name="audio_effect_echo">Echo</string>
<string name="audio_effect_reverb">Reverb</string>
<string name="audio_effect_noisemask">Noise mask</string>
<string name="audio_effect_flange">Flange</string>
<string name="audio_volume">Volume</string>
<string name="audio_effect_fuzz">Fuzz</string>
<string name="audio_effect_bassboost">Bass boost</string>
<string name="audio_equalizer">Equalizer (EQ)</string>
<!-- Space to align with the longer one -->
<string name="equalizer_band_0"> 180 Hz</string>
<string name="equalizer_band_1"> 360 Hz</string>
<string name="equalizer_band_2">1.1 kHz</string>
<string name="equalizer_band_3">3.3 kHz</string>
<string name="equalizer_band_4">6.8 kHz</string>
</resources>