configurable volume

This commit is contained in:
badaix 2016-01-07 21:08:25 +01:00
parent 506f179ed2
commit 80ea2a37a3
7 changed files with 132 additions and 34 deletions

View file

@ -10,17 +10,18 @@ import android.widget.TextView;
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 {
abstract void onChanged(ClientInfo clientInfo, boolean enabled);
public interface ClientInfoItemListener {
void onVolumeChanged(ClientInfoItem clientInfoItem, Volume volume);
}
private TextView title;
private TextView summary;
private SeekBar volumeSeekBar;
private ClientInfo clientInfo;
private ClientInfoItemListener listener = null;
public ClientInfoItem(Context context, ClientInfo clientInfo) {
super(context);
@ -28,10 +29,10 @@ public class ClientInfoItem extends LinearLayout {
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
vi.inflate(R.layout.client_info, this);
title = (TextView) findViewById(R.id.title);
summary = (TextView) findViewById(R.id.summary);
volumeSeekBar = (SeekBar) findViewById(R.id.volumeSeekBar);
volumeSeekBar.setMax(100);
setClientInfo(clientInfo);
volumeSeekBar.setOnSeekBarChangeListener(this);
}
public void setClientInfo(final ClientInfo clientInfo) {
@ -40,7 +41,6 @@ public class ClientInfoItem extends LinearLayout {
title.setText(clientInfo.getName());
else
title.setText(clientInfo.getHost());
summary.setText(clientInfo.getMac());
volumeSeekBar.setProgress(clientInfo.getVolume().getPercent());
}
@ -48,4 +48,27 @@ public class ClientInfoItem extends LinearLayout {
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) {
}
}

View file

@ -38,8 +38,9 @@ import java.io.OutputStream;
import de.badaix.snapcast.control.ClientInfo;
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";
@ -101,7 +102,7 @@ public class MainActivity extends ActionBarActivity implements View.OnClickListe
}
serverInfo = new ServerInfo();
clientInfoAdapter = new ClientInfoAdapter(this, 0);
clientInfoAdapter = new ClientInfoAdapter(this, this);
lvClient.setAdapter(clientInfoAdapter);
copyAssets();
@ -113,12 +114,15 @@ public class MainActivity extends ActionBarActivity implements View.OnClickListe
private class ClientInfoAdapter extends ArrayAdapter<ClientInfo> {
private Context context;
private ClientInfoItem.ClientInfoItemListener listener;
public ClientInfoAdapter(Context context, int textViewResourceId) {
super(context, textViewResourceId);
public ClientInfoAdapter(Context context, ClientInfoItem.ClientInfoItemListener listener) {
super(context, 0);
this.context = context;
this.listener = listener;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ClientInfo clientInfo = getItem(position);
@ -130,11 +134,32 @@ public class MainActivity extends ActionBarActivity implements View.OnClickListe
} else {
clientInfoItem = new ClientInfoItem(context, clientInfo);
}
clientInfoItem.setListener(listener);
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() {
AssetManager assetManager = getAssets();
@ -211,9 +236,13 @@ public class MainActivity extends ActionBarActivity implements View.OnClickListe
Toast.makeText(this, "Scan", Toast.LENGTH_SHORT).show();
initializeDiscoveryListener();
} else if (view == button) {
if ((tcpClient == null) || !tcpClient.isConnected()) {
Toast.makeText(this, "Connecting", Toast.LENGTH_SHORT).show();
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);
if (json.has("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");
for (int i = 0; i < clients.length(); i++) {
final ClientInfo clientInfo = new ClientInfo(clients.getJSONObject(i));
@ -346,14 +375,14 @@ public class MainActivity extends ActionBarActivity implements View.OnClickListe
@Override
public void run() {
if (clientInfo.isConnected())
clientInfoAdapter.add(clientInfo);
clientInfoAdapter.addClient(clientInfo);
}
});
}
}
} else {
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"));
Log.d(TAG, "ClientInfo: " + clientInfo);
Log.d(TAG, "Changed: " + serverInfo.addClient(clientInfo));
@ -362,7 +391,7 @@ public class MainActivity extends ActionBarActivity implements View.OnClickListe
@Override
public void run() {
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) {
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}");
}
}

View file

@ -22,7 +22,9 @@ public class TcpClient {
// class at on asynckTask doInBackground
public interface TcpClientListener {
void onMessageReceived(TcpClient tcpClient, String message);
void onConnected(TcpClient tcpClient);
void onDisconnected(TcpClient tcpClient);
}
@ -36,6 +38,7 @@ public class TcpClient {
// used to read messages from the server
private BufferedReader mBufferIn;
private Thread worker = null;
private Socket socket = null;
private String uid;
@ -47,6 +50,12 @@ public class TcpClient {
mMessageListener = listener;
}
public boolean isConnected() {
if (socket == null)
return false;
return socket.isConnected();
}
/**
* Sends the message entered by client to the server
*
@ -90,7 +99,7 @@ public class TcpClient {
Log.d(TAG, "Connecting to " + serverAddr.getCanonicalHostName() + ":" + port);
// create a socket to make the connection with the server
Socket socket = new Socket(serverAddr, port);
socket = new Socket(serverAddr, port);
try {

View 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>

View file

@ -2,11 +2,12 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
android:gravity="center_vertical"
android:background="?android:attr/selectableItemBackground"
android:minHeight="?android:attr/listPreferredItemHeight"
android:paddingRight="?android:attr/scrollbarSize"
android:orientation="vertical">
<!-- android:background="@drawable/big_card"-->
<RelativeLayout
android:layout_width="wrap_content"
@ -28,18 +29,7 @@
android:fadingEdge="horizontal"
android:singleLine="true"
android:text="Title"
android:textAppearance="?android:attr/textAppearanceLarge" />
<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" />
android:textAppearance="?android:attr/textAppearanceMedium" />
<SeekBar
android:layout_width="match_parent"

View 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>

View file

@ -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\": 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.SetLatency\", \"params\": {\"client\": \"80:1f:02:ed:fd:e0\", \"latency\": 10}, \"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.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\": \"T400\"}, \"id\": 8}\r\n")
#invalid json
doRequest("some message to test invalid requests\r\n")
#missing id