mirror of
https://github.com/badaix/snapcast.git
synced 2025-05-04 20:56:38 +02:00
configurable volume
This commit is contained in:
parent
506f179ed2
commit
80ea2a37a3
7 changed files with 132 additions and 34 deletions
|
@ -10,17 +10,18 @@ import android.widget.TextView;
|
||||||
|
|
||||||
|
|
||||||
import de.badaix.snapcast.control.ClientInfo;
|
import de.badaix.snapcast.control.ClientInfo;
|
||||||
|
import de.badaix.snapcast.control.Volume;
|
||||||
|
|
||||||
public class ClientInfoItem extends LinearLayout {
|
public class ClientInfoItem extends LinearLayout implements SeekBar.OnSeekBarChangeListener {
|
||||||
|
|
||||||
public static interface OnAppItemChangedListener {
|
public interface ClientInfoItemListener {
|
||||||
abstract void onChanged(ClientInfo clientInfo, boolean enabled);
|
void onVolumeChanged(ClientInfoItem clientInfoItem, Volume volume);
|
||||||
}
|
}
|
||||||
|
|
||||||
private TextView title;
|
private TextView title;
|
||||||
private TextView summary;
|
|
||||||
private SeekBar volumeSeekBar;
|
private SeekBar volumeSeekBar;
|
||||||
private ClientInfo clientInfo;
|
private ClientInfo clientInfo;
|
||||||
|
private ClientInfoItemListener listener = null;
|
||||||
|
|
||||||
public ClientInfoItem(Context context, ClientInfo clientInfo) {
|
public ClientInfoItem(Context context, ClientInfo clientInfo) {
|
||||||
super(context);
|
super(context);
|
||||||
|
@ -28,10 +29,10 @@ public class ClientInfoItem extends LinearLayout {
|
||||||
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||||
vi.inflate(R.layout.client_info, this);
|
vi.inflate(R.layout.client_info, this);
|
||||||
title = (TextView) findViewById(R.id.title);
|
title = (TextView) findViewById(R.id.title);
|
||||||
summary = (TextView) findViewById(R.id.summary);
|
|
||||||
volumeSeekBar = (SeekBar) findViewById(R.id.volumeSeekBar);
|
volumeSeekBar = (SeekBar) findViewById(R.id.volumeSeekBar);
|
||||||
volumeSeekBar.setMax(100);
|
volumeSeekBar.setMax(100);
|
||||||
setClientInfo(clientInfo);
|
setClientInfo(clientInfo);
|
||||||
|
volumeSeekBar.setOnSeekBarChangeListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setClientInfo(final ClientInfo clientInfo) {
|
public void setClientInfo(final ClientInfo clientInfo) {
|
||||||
|
@ -40,7 +41,6 @@ public class ClientInfoItem extends LinearLayout {
|
||||||
title.setText(clientInfo.getName());
|
title.setText(clientInfo.getName());
|
||||||
else
|
else
|
||||||
title.setText(clientInfo.getHost());
|
title.setText(clientInfo.getHost());
|
||||||
summary.setText(clientInfo.getMac());
|
|
||||||
volumeSeekBar.setProgress(clientInfo.getVolume().getPercent());
|
volumeSeekBar.setProgress(clientInfo.getVolume().getPercent());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,4 +48,27 @@ public class ClientInfoItem extends LinearLayout {
|
||||||
return clientInfo;
|
return clientInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setListener(ClientInfoItemListener listener) {
|
||||||
|
this.listener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||||
|
if (fromUser && (listener != null)) {
|
||||||
|
Volume volume = new Volume(progress, false);
|
||||||
|
clientInfo.setVolume(volume);
|
||||||
|
listener.onVolumeChanged(this, volume);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,8 +38,9 @@ import java.io.OutputStream;
|
||||||
|
|
||||||
import de.badaix.snapcast.control.ClientInfo;
|
import de.badaix.snapcast.control.ClientInfo;
|
||||||
import de.badaix.snapcast.control.ServerInfo;
|
import de.badaix.snapcast.control.ServerInfo;
|
||||||
|
import de.badaix.snapcast.control.Volume;
|
||||||
|
|
||||||
public class MainActivity extends ActionBarActivity implements View.OnClickListener, TcpClient.TcpClientListener {
|
public class MainActivity extends ActionBarActivity implements View.OnClickListener, TcpClient.TcpClientListener, ClientInfoItem.ClientInfoItemListener {
|
||||||
|
|
||||||
private static final String TAG = "Main";
|
private static final String TAG = "Main";
|
||||||
|
|
||||||
|
@ -101,7 +102,7 @@ public class MainActivity extends ActionBarActivity implements View.OnClickListe
|
||||||
}
|
}
|
||||||
|
|
||||||
serverInfo = new ServerInfo();
|
serverInfo = new ServerInfo();
|
||||||
clientInfoAdapter = new ClientInfoAdapter(this, 0);
|
clientInfoAdapter = new ClientInfoAdapter(this, this);
|
||||||
lvClient.setAdapter(clientInfoAdapter);
|
lvClient.setAdapter(clientInfoAdapter);
|
||||||
|
|
||||||
copyAssets();
|
copyAssets();
|
||||||
|
@ -113,12 +114,15 @@ public class MainActivity extends ActionBarActivity implements View.OnClickListe
|
||||||
|
|
||||||
private class ClientInfoAdapter extends ArrayAdapter<ClientInfo> {
|
private class ClientInfoAdapter extends ArrayAdapter<ClientInfo> {
|
||||||
private Context context;
|
private Context context;
|
||||||
|
private ClientInfoItem.ClientInfoItemListener listener;
|
||||||
|
|
||||||
public ClientInfoAdapter(Context context, int textViewResourceId) {
|
public ClientInfoAdapter(Context context, ClientInfoItem.ClientInfoItemListener listener) {
|
||||||
super(context, textViewResourceId);
|
super(context, 0);
|
||||||
this.context = context;
|
this.context = context;
|
||||||
|
this.listener = listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View getView(int position, View convertView, ViewGroup parent) {
|
public View getView(int position, View convertView, ViewGroup parent) {
|
||||||
ClientInfo clientInfo = getItem(position);
|
ClientInfo clientInfo = getItem(position);
|
||||||
|
@ -130,11 +134,32 @@ public class MainActivity extends ActionBarActivity implements View.OnClickListe
|
||||||
} else {
|
} else {
|
||||||
clientInfoItem = new ClientInfoItem(context, clientInfo);
|
clientInfoItem = new ClientInfoItem(context, clientInfo);
|
||||||
}
|
}
|
||||||
|
clientInfoItem.setListener(listener);
|
||||||
return clientInfoItem;
|
return clientInfoItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addClient(ClientInfo clientInfo) {
|
||||||
|
if (clientInfo == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (int i = 0; i < getCount(); i++) {
|
||||||
|
ClientInfo client = getItem(i);
|
||||||
|
if (client.getMac().equals(clientInfo.getMac())) {
|
||||||
|
insert(clientInfo, i);
|
||||||
|
remove(client);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
add(clientInfo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPause() {
|
||||||
|
if ((tcpClient != null) && (tcpClient.isConnected()))
|
||||||
|
tcpClient.stop();
|
||||||
|
super.onPause();
|
||||||
|
}
|
||||||
|
|
||||||
private void copyAssets() {
|
private void copyAssets() {
|
||||||
AssetManager assetManager = getAssets();
|
AssetManager assetManager = getAssets();
|
||||||
|
@ -211,9 +236,13 @@ public class MainActivity extends ActionBarActivity implements View.OnClickListe
|
||||||
Toast.makeText(this, "Scan", Toast.LENGTH_SHORT).show();
|
Toast.makeText(this, "Scan", Toast.LENGTH_SHORT).show();
|
||||||
initializeDiscoveryListener();
|
initializeDiscoveryListener();
|
||||||
} else if (view == button) {
|
} else if (view == button) {
|
||||||
Toast.makeText(this, "Connecting", Toast.LENGTH_SHORT).show();
|
if ((tcpClient == null) || !tcpClient.isConnected()) {
|
||||||
tcpClient = new TcpClient(this);
|
Toast.makeText(this, "Connecting", Toast.LENGTH_SHORT).show();
|
||||||
tcpClient.start(host, port + 1);
|
tcpClient = new TcpClient(this);
|
||||||
|
tcpClient.start(host, port + 1);
|
||||||
|
} else {
|
||||||
|
tcpClient.sendMessage("{\"jsonrpc\": \"2.0\", \"method\": \"System.GetStatus\", \"id\": 1}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -336,7 +365,7 @@ public class MainActivity extends ActionBarActivity implements View.OnClickListe
|
||||||
JSONObject json = new JSONObject(message);
|
JSONObject json = new JSONObject(message);
|
||||||
if (json.has("id")) {
|
if (json.has("id")) {
|
||||||
Log.d(TAG, "ID: " + json.getString("id"));
|
Log.d(TAG, "ID: " + json.getString("id"));
|
||||||
if (json.getJSONObject("result").has("clients")) {
|
if ((json.get("result") instanceof JSONObject) && json.getJSONObject("result").has("clients")) {
|
||||||
JSONArray clients = json.getJSONObject("result").getJSONArray("clients");
|
JSONArray clients = json.getJSONObject("result").getJSONArray("clients");
|
||||||
for (int i = 0; i < clients.length(); i++) {
|
for (int i = 0; i < clients.length(); i++) {
|
||||||
final ClientInfo clientInfo = new ClientInfo(clients.getJSONObject(i));
|
final ClientInfo clientInfo = new ClientInfo(clients.getJSONObject(i));
|
||||||
|
@ -346,14 +375,14 @@ public class MainActivity extends ActionBarActivity implements View.OnClickListe
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (clientInfo.isConnected())
|
if (clientInfo.isConnected())
|
||||||
clientInfoAdapter.add(clientInfo);
|
clientInfoAdapter.addClient(clientInfo);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.d(TAG, "Notification: " + json.getString("method"));
|
Log.d(TAG, "Notification: " + json.getString("method"));
|
||||||
if (json.getString("method").equals("Client.OnUpdate")) {
|
if (json.getString("method").equals("Client.OnUpdate") || json.getString("method").equals("Client.OnConnect")) {
|
||||||
final ClientInfo clientInfo = new ClientInfo(json.getJSONObject("params").getJSONObject("data"));
|
final ClientInfo clientInfo = new ClientInfo(json.getJSONObject("params").getJSONObject("data"));
|
||||||
Log.d(TAG, "ClientInfo: " + clientInfo);
|
Log.d(TAG, "ClientInfo: " + clientInfo);
|
||||||
Log.d(TAG, "Changed: " + serverInfo.addClient(clientInfo));
|
Log.d(TAG, "Changed: " + serverInfo.addClient(clientInfo));
|
||||||
|
@ -362,7 +391,7 @@ public class MainActivity extends ActionBarActivity implements View.OnClickListe
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (clientInfo.isConnected())
|
if (clientInfo.isConnected())
|
||||||
clientInfoAdapter.add(clientInfo);
|
clientInfoAdapter.addClient(clientInfo);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -382,5 +411,13 @@ public class MainActivity extends ActionBarActivity implements View.OnClickListe
|
||||||
public void onDisconnected(TcpClient tcpClient) {
|
public void onDisconnected(TcpClient tcpClient) {
|
||||||
Log.d(TAG, "onDisconnected");
|
Log.d(TAG, "onDisconnected");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onVolumeChanged(ClientInfoItem clientInfoItem, Volume volume) {
|
||||||
|
ClientInfo client = clientInfoItem.getClientInfo();
|
||||||
|
tcpClient.sendMessage("{\"jsonrpc\": \"2.0\", \"method\": \"Client.SetVolume\", \"params\": {\"client\": \"" + client.getMac() + "\", \"volume\": " + client.getVolume().getPercent() + "}, \"id\": 3}");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,9 @@ public class TcpClient {
|
||||||
// class at on asynckTask doInBackground
|
// class at on asynckTask doInBackground
|
||||||
public interface TcpClientListener {
|
public interface TcpClientListener {
|
||||||
void onMessageReceived(TcpClient tcpClient, String message);
|
void onMessageReceived(TcpClient tcpClient, String message);
|
||||||
|
|
||||||
void onConnected(TcpClient tcpClient);
|
void onConnected(TcpClient tcpClient);
|
||||||
|
|
||||||
void onDisconnected(TcpClient tcpClient);
|
void onDisconnected(TcpClient tcpClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,6 +38,7 @@ public class TcpClient {
|
||||||
// used to read messages from the server
|
// used to read messages from the server
|
||||||
private BufferedReader mBufferIn;
|
private BufferedReader mBufferIn;
|
||||||
private Thread worker = null;
|
private Thread worker = null;
|
||||||
|
private Socket socket = null;
|
||||||
|
|
||||||
private String uid;
|
private String uid;
|
||||||
|
|
||||||
|
@ -47,6 +50,12 @@ public class TcpClient {
|
||||||
mMessageListener = listener;
|
mMessageListener = listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isConnected() {
|
||||||
|
if (socket == null)
|
||||||
|
return false;
|
||||||
|
return socket.isConnected();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends the message entered by client to the server
|
* Sends the message entered by client to the server
|
||||||
*
|
*
|
||||||
|
@ -90,7 +99,7 @@ public class TcpClient {
|
||||||
Log.d(TAG, "Connecting to " + serverAddr.getCanonicalHostName() + ":" + port);
|
Log.d(TAG, "Connecting to " + serverAddr.getCanonicalHostName() + ":" + port);
|
||||||
|
|
||||||
// create a socket to make the connection with the server
|
// create a socket to make the connection with the server
|
||||||
Socket socket = new Socket(serverAddr, port);
|
socket = new Socket(serverAddr, port);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
|
33
android/Snapcast/src/main/res/drawable/big_card.xml
Normal file
33
android/Snapcast/src/main/res/drawable/big_card.xml
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||||
|
|
||||||
|
<item>
|
||||||
|
<shape android:shape="rectangle" >
|
||||||
|
<solid android:color="@color/second_grey" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
<item
|
||||||
|
android:bottom="10dp"
|
||||||
|
android:left="10dp"
|
||||||
|
android:right="10dp"
|
||||||
|
android:top="10dp">
|
||||||
|
<shape android:shape="rectangle" >
|
||||||
|
<corners android:radius="3dp" />
|
||||||
|
|
||||||
|
<solid android:color="@color/card_shadow" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
<item
|
||||||
|
android:bottom="12dp"
|
||||||
|
android:left="10dp"
|
||||||
|
android:right="10dp"
|
||||||
|
android:top="10dp">
|
||||||
|
<shape android:shape="rectangle" >
|
||||||
|
<corners android:radius="3dp" />
|
||||||
|
|
||||||
|
<solid android:color="@color/card_white" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
|
||||||
|
|
||||||
|
</layer-list>
|
|
@ -2,11 +2,12 @@
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
|
android:background="?android:attr/selectableItemBackground"
|
||||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||||
android:paddingRight="?android:attr/scrollbarSize"
|
android:paddingRight="?android:attr/scrollbarSize"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
<!-- android:background="@drawable/big_card"-->
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
@ -28,18 +29,7 @@
|
||||||
android:fadingEdge="horizontal"
|
android:fadingEdge="horizontal"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
android:text="Title"
|
android:text="Title"
|
||||||
android:textAppearance="?android:attr/textAppearanceLarge" />
|
android:textAppearance="?android:attr/textAppearanceMedium" />
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/summary"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignLeft="@id/title"
|
|
||||||
android:layout_below="@id/title"
|
|
||||||
android:maxLines="4"
|
|
||||||
android:text="Summary"
|
|
||||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
|
||||||
android:textColor="?android:attr/textColorSecondary" />
|
|
||||||
|
|
||||||
<SeekBar
|
<SeekBar
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
6
android/Snapcast/src/main/res/values/colors.xml
Normal file
6
android/Snapcast/src/main/res/values/colors.xml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<color name="second_grey">#ff999999</color>
|
||||||
|
<color name="card_white">#ffffffff</color>
|
||||||
|
<color name="card_shadow">#8c666666</color>
|
||||||
|
</resources>
|
|
@ -49,8 +49,8 @@ doRequest("{\"jsonrpc\": \"2.0\", \"method\": \"Client.SetMute\", \"params\": {\
|
||||||
doRequest("{\"jsonrpc\": \"2.0\", \"method\": \"Client.SetMute\", \"params\": {\"client\": \"80:1f:02:ed:fd:e0\", \"mute\": false}, \"id\": 9}\r\n")
|
doRequest("{\"jsonrpc\": \"2.0\", \"method\": \"Client.SetMute\", \"params\": {\"client\": \"80:1f:02:ed:fd:e0\", \"mute\": false}, \"id\": 9}\r\n")
|
||||||
doRequest("{\"jsonrpc\": \"2.0\", \"method\": \"Client.SetMute\", \"params\": {\"client\": \"80:1f:02:ed:fd:e0\", \"mute\": true}, \"id\": 9}\r\n")
|
doRequest("{\"jsonrpc\": \"2.0\", \"method\": \"Client.SetMute\", \"params\": {\"client\": \"80:1f:02:ed:fd:e0\", \"mute\": true}, \"id\": 9}\r\n")
|
||||||
doRequest("{\"jsonrpc\": \"2.0\", \"method\": \"Client.SetMute\", \"params\": {\"client\": \"80:1f:02:ed:fd:e0\", \"mute\": false}, \"id\": 9}\r\n")
|
doRequest("{\"jsonrpc\": \"2.0\", \"method\": \"Client.SetMute\", \"params\": {\"client\": \"80:1f:02:ed:fd:e0\", \"mute\": false}, \"id\": 9}\r\n")
|
||||||
doRequest("{\"jsonrpc\": \"2.0\", \"method\": \"Client.SetLatency\", \"params\": {\"client\": \"80:1f:02:ed:fd:e0\", \"latency\": 10}, \"id\": 7}\r\n")
|
doRequest("{\"jsonrpc\": \"2.0\", \"method\": \"Client.SetLatency\", \"params\": {\"client\": \"80:1f:02:ed:fd:e0\", \"latency\": 0}, \"id\": 7}\r\n")
|
||||||
doRequest("{\"jsonrpc\": \"2.0\", \"method\": \"Client.SetName\", \"params\": {\"client\": \"80:1f:02:ed:fd:e0\", \"name\": \"living room\"}, \"id\": 8}\r\n")
|
doRequest("{\"jsonrpc\": \"2.0\", \"method\": \"Client.SetName\", \"params\": {\"client\": \"80:1f:02:ed:fd:e0\", \"name\": \"T400\"}, \"id\": 8}\r\n")
|
||||||
#invalid json
|
#invalid json
|
||||||
doRequest("some message to test invalid requests\r\n")
|
doRequest("some message to test invalid requests\r\n")
|
||||||
#missing id
|
#missing id
|
||||||
|
|
Loading…
Add table
Reference in a new issue