All effects working!

master
Nicolò Balzarotti 2017-10-10 00:05:43 +02:00
parent 6bdc4bbcab
commit 6c313e2e9b
21 changed files with 438 additions and 505 deletions

View File

@ -26,54 +26,55 @@ import android.widget.TextView;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.Map;
import java.util.ArrayList;
import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.devices.here.HereConstants;
import nodomain.freeyourgadget.gadgetbridge.entities.AudioEffect;
import nodomain.freeyourgadget.gadgetbridge.entities.AudioEffectType;
import nodomain.freeyourgadget.gadgetbridge.service.btle.BtLEAction;
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
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
};*/
LOG.debug("Create Audio Settings interface");
// FIXME: read enabled effects too
// FIXME: and EQ values XD
seekBar = (SeekBar) findViewById(R.id.volume_seekbar);
volume_text = (TextView) findViewById(R.id.volume_seekbar_volume);
int startingVolume = 30; // FIXME: how do I read it?
seekBar.setProgress(startingVolume);
setdB(startingVolume);
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;
// HERE's volume range is from 0xdb (-30dB on their app) to 0xff (+6dB)
// 0xff - 0xdb = 36 -> seekbar max value
// volume = seekbar + Min_volume (= 0xdb = 219)
volume = position + 219;
// 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");
AudioEffect eff = new AudioEffect(AudioEffectType.VOLUME, volume);
GBApplication.deviceService().onSetAudioProperty(eff);
// Show the volume on the UI in dB (range -30;6)
setdB(position);
}
@Override
@ -89,46 +90,35 @@ public class AudioSettingsActivity extends AbstractGBActivity {
// 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);
Map<Integer, AudioEffectType> checkboxesIds = new HashMap<Integer, AudioEffectType>();
checkboxesIds.put(R.id.audio_effect_echo, AudioEffectType.ECHO);
checkboxesIds.put(R.id.audio_effect_bassboost, AudioEffectType.BASSBOOST);
checkboxesIds.put(R.id.audio_effect_fuzz, AudioEffectType.FUZZ);
checkboxesIds.put(R.id.audio_effect_flange, AudioEffectType.FLANGE);
checkboxesIds.put(R.id.audio_effect_reverb, AudioEffectType.REVERB);
checkboxesIds.put(R.id.audio_effect_noisemask, AudioEffectType.NOISEMASK);
checkboxesIds.put(R.id.audio_effect_bitcrusher, AudioEffectType.BITCRUSHER);
checkboxesIds.put(R.id.audio_effect_chorus, AudioEffectType.CHORUS);
cbBassBoost.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
((CheckedTextView) v).toggle();
LOG.info("Enabled bassBoost");
applyEffect(AudioEffectType.BASSBOOST, ((CheckedTextView) v).isChecked());
}
});
for (int id : checkboxesIds.keySet()) {
final AudioEffectType effect = checkboxesIds.get(id);
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());
}
});
((CheckedTextView) findViewById(id)).setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
((CheckedTextView) v).toggle();
LOG.info("Toggled " + effect.name());
applyEffect(new AudioEffect(effect, ((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?
});
private void setdB(int volume) {
volume_text.setText(" " + (volume - 30) + " dB");
}
void applyEffect(AudioEffect effect) {
GBApplication.deviceService().onSetAudioProperty(effect);
}
}

View File

@ -5,17 +5,17 @@
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.
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.
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.adapter;
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.adapter;
import android.app.Activity;
import android.app.AlertDialog;
@ -85,27 +85,27 @@ public class GBDeviceAdapterv2 extends RecyclerView.Adapter<GBDeviceAdapterv2.Vi
holder.container.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (device.isInitialized() || device.isConnected()) {
showTransientSnackbar(R.string.controlcenter_snackbar_need_longpress);
} else {
showTransientSnackbar(R.string.controlcenter_snackbar_connecting);
GBApplication.deviceService().connect(device);
}
}
});
@Override
public void onClick(View v) {
if (device.isInitialized() || device.isConnected()) {
showTransientSnackbar(R.string.controlcenter_snackbar_need_longpress);
} else {
showTransientSnackbar(R.string.controlcenter_snackbar_connecting);
GBApplication.deviceService().connect(device);
}
}
});
holder.container.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
if (device.getState() != GBDevice.State.NOT_CONNECTED) {
showTransientSnackbar(R.string.controlcenter_snackbar_disconnecting);
GBApplication.deviceService().disconnect();
}
return true;
}
});
@Override
public boolean onLongClick(View v) {
if (device.getState() != GBDevice.State.NOT_CONNECTED) {
showTransientSnackbar(R.string.controlcenter_snackbar_disconnecting);
GBApplication.deviceService().disconnect();
}
return true;
}
});
holder.deviceImageView.setImageResource(R.drawable.level_list_device);
//level-list does not allow negative values, hence we always add 100 to the key.
holder.deviceImageView.setImageLevel(device.getType().getKey() + 100 + (device.isInitialized() ? 100 : 0));
@ -129,7 +129,7 @@ public class GBDeviceAdapterv2 extends RecyclerView.Adapter<GBDeviceAdapterv2.Vi
holder.batteryStatusLabel.setText(device.getBatteryLevel() + "%");
BatteryState batteryState = device.getBatteryState();
if (BatteryState.BATTERY_CHARGING.equals(batteryState) ||
BatteryState.BATTERY_CHARGING_FULL.equals(batteryState)) {
BatteryState.BATTERY_CHARGING_FULL.equals(batteryState)) {
holder.batteryIcon.setImageLevel(device.getBatteryLevel() + 100);
} else {
holder.batteryIcon.setImageLevel(device.getBatteryLevel());
@ -140,92 +140,91 @@ public class GBDeviceAdapterv2 extends RecyclerView.Adapter<GBDeviceAdapterv2.Vi
holder.fetchActivityDataBox.setVisibility((device.isInitialized() && coordinator.supportsActivityDataFetching()) ? View.VISIBLE : View.GONE);
holder.fetchActivityData.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v) {
showTransientSnackbar(R.string.busy_task_fetch_activity_data);
GBApplication.deviceService().onFetchActivityData();
}
}
);
{
@Override
public void onClick(View v) {
showTransientSnackbar(R.string.busy_task_fetch_activity_data);
GBApplication.deviceService().onFetchActivityData();
}
}
);
//take screenshot
holder.takeScreenshotView.setVisibility((device.isInitialized() && coordinator.supportsScreenshots()) ? View.VISIBLE : View.GONE);
holder.takeScreenshotView.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v) {
showTransientSnackbar(R.string.controlcenter_snackbar_requested_screenshot);
GBApplication.deviceService().onScreenshotReq();
}
}
);
{
@Override
public void onClick(View v) {
showTransientSnackbar(R.string.controlcenter_snackbar_requested_screenshot);
GBApplication.deviceService().onScreenshotReq();
}
}
);
//manage apps
holder.manageAppsView.setVisibility((device.isInitialized() && coordinator.supportsAppsManagement()) ? View.VISIBLE : View.GONE);
holder.manageAppsView.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v) {
DeviceCoordinator coordinator = DeviceHelper.getInstance().getCoordinator(device);
Class<? extends Activity> appsManagementActivity = coordinator.getAppsManagementActivity();
if (appsManagementActivity != null) {
Intent startIntent = new Intent(context, appsManagementActivity);
startIntent.putExtra(GBDevice.EXTRA_DEVICE, device);
context.startActivity(startIntent);
}
}
}
);
{
@Override
public void onClick(View v) {
DeviceCoordinator coordinator = DeviceHelper.getInstance().getCoordinator(device);
Class<? extends Activity> appsManagementActivity = coordinator.getAppsManagementActivity();
if (appsManagementActivity != null) {
Intent startIntent = new Intent(context, appsManagementActivity);
startIntent.putExtra(GBDevice.EXTRA_DEVICE, device);
context.startActivity(startIntent);
}
}
}
);
//set alarms
holder.setAlarmsView.setVisibility(coordinator.supportsAlarmConfiguration() ? View.VISIBLE : View.GONE);
holder.setAlarmsView.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v) {
Intent startIntent;
startIntent = new Intent(context, ConfigureAlarms.class);
startIntent.putExtra(GBDevice.EXTRA_DEVICE, device);
context.startActivity(startIntent);
}
}
);
{
@Override
public void onClick(View v) {
Intent startIntent;
startIntent = new Intent(context, ConfigureAlarms.class);
startIntent.putExtra(GBDevice.EXTRA_DEVICE, device);
context.startActivity(startIntent);
}
}
);
//show graphs
holder.showActivityGraphs.setVisibility(coordinator.supportsActivityTracking() ? View.VISIBLE : View.GONE);
holder.showActivityGraphs.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v) {
Intent startIntent;
startIntent = new Intent(context, ChartsActivity.class);
startIntent.putExtra(GBDevice.EXTRA_DEVICE, device);
context.startActivity(startIntent);
}
}
);
{
@Override
public void onClick(View v) {
Intent startIntent;
startIntent = new Intent(context, ChartsActivity.class);
startIntent.putExtra(GBDevice.EXTRA_DEVICE, device);
context.startActivity(startIntent);
}
}
);
// audio settings
holder.showAudioSettings.setVisibility(device.isInitialized() && coordinator.supportsAudioSettings() ? View.VISIBLE : View.GONE);
holder.showAudioSettings.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v) {
showTransientSnackbar(R.string.controlcenter_snackbar_requested_screenshot);
Intent startIntent;
startIntent = new Intent(context, AudioSettingsActivity.class);
startIntent.putExtra(GBDevice.EXTRA_DEVICE, device);
context.startActivity(startIntent);
}
}
);
holder.showAudioSettings.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showTransientSnackbar(R.string.controlcenter_snackbar_requested_screenshot);
Intent startIntent;
startIntent = new Intent(context, AudioSettingsActivity.class);
startIntent.putExtra(GBDevice.EXTRA_DEVICE, device);
context.startActivity(startIntent);
}
}
);
ItemWithDetailsAdapter infoAdapter = new ItemWithDetailsAdapter(context, device.getDeviceInfos());
infoAdapter.setHorizontalAlignment(true);
@ -239,96 +238,96 @@ public class GBDeviceAdapterv2 extends RecyclerView.Adapter<GBDeviceAdapterv2.Vi
holder.deviceInfoBox.setActivated(detailsShown);
holder.deviceInfoBox.setVisibility(detailsShown ? View.VISIBLE : View.GONE);
holder.deviceInfoView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
expandedDevicePosition = detailsShown ? -1 : position;
TransitionManager.beginDelayedTransition(parent);
notifyDataSetChanged();
}
}
@Override
public void onClick(View v) {
expandedDevicePosition = detailsShown ? -1 : position;
TransitionManager.beginDelayedTransition(parent);
notifyDataSetChanged();
}
}
);
);
holder.findDevice.setVisibility((device.isInitialized() &&
device.getType() != DeviceType.HERE) ? View.VISIBLE : View.GONE);
holder.findDevice.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v) {
if (device.getType() == DeviceType.VIBRATISSIMO) {
Intent startIntent;
startIntent = new Intent(context, VibrationActivity.class);
startIntent.putExtra(GBDevice.EXTRA_DEVICE, device);
context.startActivity(startIntent);
return;
}
GBApplication.deviceService().onFindDevice(true);
//TODO: extract string resource if we like this solution.
Snackbar.make(parent, R.string.control_center_find_lost_device, Snackbar.LENGTH_INDEFINITE).setAction("Found it!", new View.OnClickListener() {
@Override
public void onClick(View v) {
GBApplication.deviceService().onFindDevice(false);
}
}).setCallback(new Snackbar.Callback() {
@Override
public void onDismissed(Snackbar snackbar, int event) {
GBApplication.deviceService().onFindDevice(false);
super.onDismissed(snackbar, event);
}
}).show();
// ProgressDialog.show(
// context,
// context.getString(R.string.control_center_find_lost_device),
// context.getString(R.string.control_center_cancel_to_stop_vibration),
// true, true,
// new DialogInterface.OnCancelListener() {
// @Override
// public void onCancel(DialogInterface dialog) {
// GBApplication.deviceService().onFindDevice(false);
// }
// });
}
}
{
@Override
public void onClick(View v) {
if (device.getType() == DeviceType.VIBRATISSIMO) {
Intent startIntent;
startIntent = new Intent(context, VibrationActivity.class);
startIntent.putExtra(GBDevice.EXTRA_DEVICE, device);
context.startActivity(startIntent);
return;
}
GBApplication.deviceService().onFindDevice(true);
//TODO: extract string resource if we like this solution.
Snackbar.make(parent, R.string.control_center_find_lost_device, Snackbar.LENGTH_INDEFINITE).setAction("Found it!", new View.OnClickListener() {
@Override
public void onClick(View v) {
GBApplication.deviceService().onFindDevice(false);
}
}).setCallback(new Snackbar.Callback() {
@Override
public void onDismissed(Snackbar snackbar, int event) {
GBApplication.deviceService().onFindDevice(false);
super.onDismissed(snackbar, event);
}
}).show();
// ProgressDialog.show(
// context,
// context.getString(R.string.control_center_find_lost_device),
// context.getString(R.string.control_center_cancel_to_stop_vibration),
// true, true,
// new DialogInterface.OnCancelListener() {
// @Override
// public void onCancel(DialogInterface dialog) {
// GBApplication.deviceService().onFindDevice(false);
// }
// });
}
}
);
);
//remove device, hidden under details
holder.removeDevice.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v) {
new AlertDialog.Builder(context)
{
@Override
public void onClick(View v) {
new AlertDialog.Builder(context)
.setCancelable(true)
.setTitle(context.getString(R.string.controlcenter_delete_device_name, device.getName()))
.setMessage(R.string.controlcenter_delete_device_dialogmessage)
.setPositiveButton(R.string.Delete, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
try {
DeviceCoordinator coordinator = DeviceHelper.getInstance().getCoordinator(device);
if (coordinator != null) {
coordinator.deleteDevice(device);
}
DeviceHelper.getInstance().removeBond(device);
} catch (Exception ex) {
GB.toast(context, "Error deleting device: " + ex.getMessage(), Toast.LENGTH_LONG, GB.ERROR, ex);
} finally {
Intent refreshIntent = new Intent(DeviceManager.ACTION_REFRESH_DEVICELIST);
LocalBroadcastManager.getInstance(context).sendBroadcast(refreshIntent);
}
}
})
@Override
public void onClick(DialogInterface dialog, int which) {
try {
DeviceCoordinator coordinator = DeviceHelper.getInstance().getCoordinator(device);
if (coordinator != null) {
coordinator.deleteDevice(device);
}
DeviceHelper.getInstance().removeBond(device);
} catch (Exception ex) {
GB.toast(context, "Error deleting device: " + ex.getMessage(), Toast.LENGTH_LONG, GB.ERROR, ex);
} finally {
Intent refreshIntent = new Intent(DeviceManager.ACTION_REFRESH_DEVICELIST);
LocalBroadcastManager.getInstance(context).sendBroadcast(refreshIntent);
}
}
})
.setNegativeButton(R.string.Cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// do nothing
}
})
@Override
public void onClick(DialogInterface dialog, int which) {
// do nothing
}
})
.show();
}
});
}
});
}
@ -449,7 +448,7 @@ public class GBDeviceAdapterv2 extends RecyclerView.Adapter<GBDeviceAdapterv2.Vi
View snackbarView = snackbar.getView();
// change snackbar text color
// change snackbar text color
int snackbarTextId = android.support.design.R.id.snackbar_text;
TextView textView = (TextView) snackbarView.findViewById(snackbarTextId);
//textView.setTextColor();

View File

@ -20,8 +20,10 @@ package nodomain.freeyourgadget.gadgetbridge.devices;
import android.net.Uri;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.entities.AudioEffect;
import nodomain.freeyourgadget.gadgetbridge.entities.AudioEffectType;
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec;
@ -80,7 +82,7 @@ public interface EventHandler {
void onSetConstantVibration(int integer);
void onSetAudioProperty(int property, float[] params);
void onSetAudioProperty(AudioEffect effect);
void onScreenshotReq();

View File

@ -24,16 +24,14 @@ import android.database.Cursor;
import android.net.Uri;
import android.provider.ContactsContract;
import android.support.annotation.Nullable;
// FIXME: REMOVE
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.entities.AudioEffectType;
import nodomain.freeyourgadget.gadgetbridge.entities.AudioEffect;
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec;
import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
@ -50,8 +48,6 @@ import static nodomain.freeyourgadget.gadgetbridge.util.JavaExtensions.coalesce;
public class GBDeviceService implements DeviceService {
protected final Context mContext;
// FIXME: REMOVE
private static final Logger LOG = LoggerFactory.getLogger(DeviceCommunicationService.class);
private final Class<? extends Service> mServiceClass;
private final String[] transliterationExtras = new String[]{
@ -306,11 +302,10 @@ public class GBDeviceService implements DeviceService {
}
@Override
public void onSetAudioProperty(int property, float[] params) {
// volume = 0
Intent intent = createIntent().setAction(ACTION_SET_AUDIO_PROPERTY)
.putExtra(EXTRA_AUDIO_PROPERTY, property)
.putExtra(EXTRA_AUDIO_PARAMS, params);
public void onSetAudioProperty(AudioEffect effect) {
// volume = 0
Intent intent = createIntent().setAction(ACTION_SET_AUDIO_PROPERTY)
.putExtra(EXTRA_AUDIO_PROPERTY, (Serializable) effect);
invokeService(intent);
}

View File

@ -19,7 +19,10 @@ package nodomain.freeyourgadget.gadgetbridge.model;
import android.support.annotation.Nullable;
import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.devices.EventHandler;
import nodomain.freeyourgadget.gadgetbridge.entities.AudioEffect;
import nodomain.freeyourgadget.gadgetbridge.entities.AudioEffectType;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService;
@ -157,5 +160,5 @@ public interface DeviceService extends EventHandler {
*/
void requestDeviceInfo();
void onSetAudioProperty(int property, float[] params);
void onSetAudioProperty(AudioEffect effect);
}

View File

@ -40,7 +40,7 @@ public enum DeviceType {
EXRIZUK8(42, R.drawable.ic_device_hplus, R.drawable.ic_device_hplus_disabled),
NO1F1(50, R.drawable.ic_device_hplus, R.drawable.ic_device_hplus_disabled),
TECLASTH30(60, R.drawable.ic_device_h30_h10, R.drawable.ic_device_h30_h10_disabled),
// Single device made of L + R (71, 71)
// Single device made of L + R (71, 72)
// but each earbut can be controlled independently
HERE(70, R.drawable.ic_device_default, R.drawable.ic_device_default_disabled),
// HERER(71, R.drawable.ic_device_here, R.drawable.ic_device_here_disabled),

View File

@ -39,6 +39,7 @@ import android.widget.Toast;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Random;
import java.util.UUID;
@ -46,6 +47,7 @@ import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.entities.AudioEffect;
import nodomain.freeyourgadget.gadgetbridge.externalevents.AlarmClockReceiver;
import nodomain.freeyourgadget.gadgetbridge.externalevents.AlarmReceiver;
import nodomain.freeyourgadget.gadgetbridge.externalevents.BluetoothConnectReceiver;
@ -105,7 +107,6 @@ 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;
@ -218,7 +219,7 @@ public class DeviceCommunicationService extends Service implements SharedPrefere
if (action.equals(GBDevice.ACTION_DEVICE_CHANGED)) {
GBDevice device = intent.getParcelableExtra(GBDevice.EXTRA_DEVICE);
if (mGBDevice != null && mGBDevice.equals(device)) {
mGBDevice = device;
mGBDevice = device; // if is already .equals, why set it?
boolean enableReceivers = mDeviceSupport != null && (mDeviceSupport.useAutoConnect() || mGBDevice.isInitialized());
setReceiversEnableState(enableReceivers, mGBDevice.isInitialized(), DeviceHelper.getInstance().getCoordinator(device));
GB.updateNotification(mGBDevice.getName() + " " + mGBDevice.getStateString(), mGBDevice.isInitialized(), context);
@ -431,13 +432,8 @@ public class DeviceCommunicationService extends Service implements SharedPrefere
break;
}
case ACTION_SET_AUDIO_PROPERTY: {
LOG.info(mDeviceSupport.getDevice().toString());
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");
AudioEffect effect = (AudioEffect) intent.getSerializableExtra(EXTRA_AUDIO_PROPERTY);
mDeviceSupport.onSetAudioProperty(effect);
break;
}
case ACTION_CALLSTATE:

View File

@ -143,8 +143,8 @@ public class DeviceSupportFactory {
deviceSupport = new ServiceDeviceSupport(new No1F1Support(), EnumSet.of(ServiceDeviceSupport.Flags.BUSY_CHECKING));
break;
case HERE:
// case HERER:
// case HEREL:
// case HERER:
// case HEREL:
deviceSupport = new ServiceDeviceSupport(new HereSupport(), EnumSet.of(ServiceDeviceSupport.Flags.BUSY_CHECKING));
break;
case TECLASTH30:

View File

@ -26,8 +26,10 @@ import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.entities.AudioEffect;
import nodomain.freeyourgadget.gadgetbridge.entities.AudioEffectType;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
@ -154,8 +156,8 @@ public class ServiceDeviceSupport implements DeviceSupport {
}
@Override
public void onSetAudioProperty(int property, float [] params) {
delegate.onSetAudioProperty(property, params);
public void onSetAudioProperty(AudioEffect effect) {
delegate.onSetAudioProperty(effect);
}
@Override

View File

@ -25,11 +25,13 @@ import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
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.AudioEffect;
import nodomain.freeyourgadget.gadgetbridge.entities.AudioEffectType;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
@ -84,6 +86,7 @@ public class HereSupport extends AbstractBTLEDeviceSupport {
gbDevice.setState(GBDevice.State.INITIALIZED);
gbDevice.sendDeviceUpdateIntent(getContext());
requestCurrentVolume();
LOG.info("Initialization Done");
@ -159,57 +162,15 @@ public class HereSupport extends AbstractBTLEDeviceSupport {
}
@Override
public void onSetAudioProperty(int property, float[] params) {
AudioEffectType effect = AudioEffectType.getByEffectId(property);
public void onSetAudioProperty(AudioEffect effect) {
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});
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;
BluetoothGattCharacteristic characteristic;
if (effect.getType() == AudioEffectType.VOLUME) {
characteristic = volumeCharacteristic;
} else {
characteristic = effectCharacteristic;
}
builder.write(characteristic, effect.toByteMessage());
builder.queue(getQueue());
}
@ -224,7 +185,6 @@ public class HereSupport extends AbstractBTLEDeviceSupport {
@Override
public void onEnableRealtimeSteps(boolean enable) {
onEnableRealtimeHeartRateMeasurement(enable);
}
@Override
@ -321,90 +281,17 @@ public class HereSupport extends AbstractBTLEDeviceSupport {
// TODO: USE THIS
// private byte[] effectMessage(int id, int padding, float [] params) {};
public int requestCurrentVolume() {
TransactionBuilder builder = createTransactionBuilder("getAudio");
builder.read(volumeCharacteristic);
LOG.debug(builder.toString());
return 1;
}
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;
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;
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;
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;
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;
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;
default:
LOG.warn("Programming error! Enabled a non-existent effect (" +
effect.name()
+ "!");
message = new byte[]{};
}
AudioEffect eff = new AudioEffect(effect, true); // default params!
message = eff.toByteMessage();
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.AudioEffect;
import nodomain.freeyourgadget.gadgetbridge.entities.AudioEffectType;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
@ -433,7 +434,7 @@ public class HPlusSupport extends AbstractBTLEDeviceSupport {
}
@Override
public void onSetAudioProperty(int property, float[] params) {
public void onSetAudioProperty(AudioEffect effect) {
}

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.AudioEffect;
import nodomain.freeyourgadget.gadgetbridge.entities.AudioEffectType;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
@ -318,7 +319,7 @@ public class TeclastH30Support extends AbstractBTLEDeviceSupport {
}
@Override
public void onSetAudioProperty(int property, float[] params) {
public void onSetAudioProperty(AudioEffect effect) {
}

View File

@ -21,7 +21,7 @@ import android.net.Uri;
import java.util.ArrayList;
import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.entities.AudioEffectType;
import nodomain.freeyourgadget.gadgetbridge.entities.AudioEffect;
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec;
import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
@ -107,7 +107,7 @@ public class LiveviewSupport extends AbstractSerialDeviceSupport {
}
@Override
public void onSetAudioProperty(int property, float[] params) {
public void onSetAudioProperty(AudioEffect effect) {
}
@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.AudioEffect;
import nodomain.freeyourgadget.gadgetbridge.entities.AudioEffectType;
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
@ -454,7 +455,7 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
}
@Override
public void onSetAudioProperty(int property, float[] params) {
public void onSetAudioProperty(AudioEffect effect) {
}

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.AudioEffect;
import nodomain.freeyourgadget.gadgetbridge.entities.AudioEffectType;
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
@ -665,7 +666,7 @@ public class MiBand2Support extends AbstractBTLEDeviceSupport {
}
@Override
public void onSetAudioProperty(int property, float[] params) {
public void onSetAudioProperty(AudioEffect effect) {
}

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.AudioEffect;
import nodomain.freeyourgadget.gadgetbridge.entities.AudioEffectType;
import nodomain.freeyourgadget.gadgetbridge.entities.No1F1ActivitySample;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
@ -357,7 +358,7 @@ public class No1F1Support extends AbstractBTLEDeviceSupport {
}
@Override
public void onSetAudioProperty(int property, float[] params) {
public void onSetAudioProperty(AudioEffect effect) {
}

View File

@ -26,11 +26,13 @@ import org.json.JSONObject;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
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.AudioEffect;
import nodomain.freeyourgadget.gadgetbridge.entities.AudioEffectType;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
@ -129,7 +131,7 @@ public class PebbleSupport extends AbstractSerialDeviceSupport {
}
@Override
public void onSetAudioProperty(int property, float[] params) {
public void onSetAudioProperty(AudioEffect effect) {
}

View File

@ -29,10 +29,13 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventBatteryInfo;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventVersionInfo;
import nodomain.freeyourgadget.gadgetbridge.entities.AudioEffect;
import nodomain.freeyourgadget.gadgetbridge.entities.AudioEffectType;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec;
@ -186,7 +189,7 @@ public class VibratissimoSupport extends AbstractBTLEDeviceSupport {
}
@Override
public void onSetAudioProperty(int property, float [] params) {
public void onSetAudioProperty(AudioEffect effect) {
}

View File

@ -3,16 +3,16 @@
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:orientation="vertical"
android:weightSum="1">
<SeekBar
android:id="@+id/volume_seekbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="28"
android:max="36"
android:scaleY="4.0" />
<LinearLayout
@ -21,101 +21,139 @@
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"
/>
<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:id="@+id/audio_effect_selector_big"
android:layout_width="387dp"
android:layout_height="wrap_content"
android:baselineAligned="false"
android:orientation="horizontal">
android:orientation="vertical">
<android.support.v7.widget.AppCompatCheckedTextView
android:id="@+id/audio_effect_echo"
android:layout_width="wrap_content"
<LinearLayout
android:id="@+id/audio_effect_selector_l1"
android:layout_width="387dp"
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:baselineAligned="false"
android:orientation="horizontal">
<android.support.v7.widget.AppCompatCheckedTextView
android:id="@+id/audio_effect_reverb"
android:layout_width="wrap_content"
<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" />
</LinearLayout>
<LinearLayout
android:id="@+id/audio_effect_selector"
android:layout_width="387dp"
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:baselineAligned="false"
android:orientation="horizontal">
<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_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_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_bitcrusher"
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_bitcrusher"
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" />
<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" />
<android.support.v7.widget.AppCompatCheckedTextView
android:id="@+id/audio_effect_chorus"
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_chorus"
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
</LinearLayout>
<TextView
android:id="@+id/audio_equalizer_text"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/audio_equalizer"
/>
android:text="@string/audio_equalizer" />
<LinearLayout
android:layout_width="match_parent"
@ -123,98 +161,107 @@
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" />
<SeekBar
android:id="@+id/equalizer_band_0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:max="30"
android:scaleY="2.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>
android:layout_height="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:layout_height="wrap_content"
android:layout_weight="1.0"
android:max="30"
android:scaleY="2.0"
android:layout_weight="1.0" />
android:scaleY="2.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"
/>
android:layout_height="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:layout_height="wrap_content"
android:layout_weight="1.0"
android:max="30"
android:scaleY="2.0"
android:layout_weight="1.0" />
android:scaleY="2.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"
/>
android:layout_height="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:layout_height="wrap_content"
android:layout_weight="1.0"
android:max="30"
android:scaleY="2.0"
android:layout_weight="1.0" />
android:scaleY="2.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"
/>
android:layout_height="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:layout_height="wrap_content"
android:layout_weight="1.0"
android:max="30"
android:scaleY="2.0"
android:layout_weight="1.0" />
android:scaleY="2.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"
/>
android:layout_height="wrap_content"
android:text="@string/equalizer_band_4" />
</LinearLayout>
</LinearLayout>

View File

@ -396,7 +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>
<string name="audio_effect_echo">Echo</string>
<string name="audio_volume">Volume</string>
<string name="audio_effect_fuzz">Fuzz</string>
</resources>

View File

@ -490,4 +490,6 @@
<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>
<string name="audio_effect_bitcrusher">Bit Crusher</string>
<string name="audio_effect_chorus">Chorus</string>
</resources>