Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 103 additions & 14 deletions Snapcast/src/main/java/de/badaix/snapcast/GroupItem.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,14 @@
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.SeekBar;
import android.widget.TextView;
Expand All @@ -37,6 +40,7 @@
import de.badaix.snapcast.control.json.Group;
import de.badaix.snapcast.control.json.ServerStatus;
import de.badaix.snapcast.control.json.Stream;
import de.badaix.snapcast.control.json.StreamProperties;
import de.badaix.snapcast.control.json.Volume;

/**
Expand All @@ -48,7 +52,6 @@ public class GroupItem extends LinearLayout implements SeekBar.OnSeekBarChangeLi

private static final String TAG = "GroupItem";

// private TextView title;
private final SeekBar volumeSeekBar;
private final ImageButton ibMute;
private final ImageButton ibSettings;
Expand All @@ -58,7 +61,15 @@ public class GroupItem extends LinearLayout implements SeekBar.OnSeekBarChangeLi
private TextView tvStreamName = null;
private GroupItemListener listener = null;
private final LinearLayout llVolume;
private final LinearLayout llNowPlaying;
private final ImageView ivAlbumArt;
private final TextView tvTrackTitle;
private final TextView tvTrackArtist;
private final ImageButton ibPrevious;
private final ImageButton ibPlayPause;
private final ImageButton ibNext;
private boolean hideOffline = false;
private boolean showNowPlaying = true;
private Vector<ClientItem> clientItems = null;
private Vector<Integer> clientVolumes = null;
private int groupVolume = 0;
Expand All @@ -68,7 +79,6 @@ public GroupItem(Context context, ServerStatus server, Group group) {
LayoutInflater vi = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
vi.inflate(R.layout.group_item, this);
// title = (TextView) findViewById(R.id.title);
volumeSeekBar = findViewById(R.id.volumeSeekBar);
ibMute = findViewById(R.id.ibMute);
ibMute.setImageResource(R.drawable.volume_up_24px);
Expand All @@ -86,6 +96,18 @@ public void onClick(View view) {
streamChoiceDialog();
}
});

llNowPlaying = findViewById(R.id.llNowPlaying);
ivAlbumArt = findViewById(R.id.ivAlbumArt);
tvTrackTitle = findViewById(R.id.tvTrackTitle);
tvTrackArtist = findViewById(R.id.tvTrackArtist);
ibPrevious = findViewById(R.id.ibPrevious);
ibPlayPause = findViewById(R.id.ibPlayPause);
ibNext = findViewById(R.id.ibNext);
ibPrevious.setOnClickListener(this);
ibPlayPause.setOnClickListener(this);
ibNext.setOnClickListener(this);

volumeSeekBar.setOnSeekBarChangeListener(this);
volumeSeekBar.setOnTouchListener(this);
volumeSeekBar.setOnFocusChangeListener(this);
Expand Down Expand Up @@ -124,18 +146,60 @@ private void update() {
if ((tvStreamName == null) || (stream == null))
return;
tvStreamName.setText(stream.getName());
/* String codec = stream.getUri().getQuery().get("codec");
if (codec.contains(":"))
codec = codec.split(":")[0];
tvStreamState.setText(stream.getUri().getQuery().get("sampleformat") + " - " + codec + " - " + stream.getStatus().toString());

title.setEnabled(group.isConnected());
volumeSeekBar.setProgress(group.getConfig().getVolume().getPercent());
if (client.getConfig().getVolume().isMuted())
ibMute.setImageResource(R.drawable.ic_mute_icon);
else
ibMute.setImageResource(R.drawable.ic_speaker_icon);
*/
updateNowPlaying(stream);
}

private void updateNowPlaying(Stream stream) {
StreamProperties props = stream.getProperties();
if (!showNowPlaying || props == null || (!props.hasMetadata() && !props.canControl())) {
llNowPlaying.setVisibility(GONE);
return;
}

llNowPlaying.setVisibility(VISIBLE);

if (props.hasMetadata()) {
String title = props.getTitle();
String artist = props.getArtistString();
tvTrackTitle.setText(TextUtils.isEmpty(title) ? "" : title);
tvTrackTitle.setVisibility(TextUtils.isEmpty(title) ? GONE : VISIBLE);
tvTrackArtist.setText(TextUtils.isEmpty(artist) ? props.getAlbum() : artist);
tvTrackArtist.setVisibility(TextUtils.isEmpty(artist) && TextUtils.isEmpty(props.getAlbum()) ? GONE : VISIBLE);

Bitmap art = props.getArtBitmap();
if (art != null) {
ivAlbumArt.setImageBitmap(art);
ivAlbumArt.setVisibility(VISIBLE);
} else {
ivAlbumArt.setVisibility(GONE);
}
} else {
tvTrackTitle.setVisibility(GONE);
tvTrackArtist.setVisibility(GONE);
ivAlbumArt.setVisibility(GONE);
}

if (props.canControl()) {
ibPrevious.setVisibility(VISIBLE);
ibPlayPause.setVisibility(VISIBLE);
ibNext.setVisibility(VISIBLE);
ibPrevious.setEnabled(props.canGoPrevious());
ibPrevious.setAlpha(props.canGoPrevious() ? 1.0f : 0.3f);
ibNext.setEnabled(props.canGoNext());
ibNext.setAlpha(props.canGoNext() ? 1.0f : 0.3f);

if (props.isPlaying()) {
ibPlayPause.setImageResource(R.drawable.ic_pause_24px);
} else {
ibPlayPause.setImageResource(R.drawable.ic_play_arrow_24px);
}
ibPlayPause.setEnabled(props.canPause() || props.canPlay());
ibPlayPause.setAlpha((props.canPause() || props.canPlay()) ? 1.0f : 0.3f);
} else {
ibPrevious.setVisibility(GONE);
ibPlayPause.setVisibility(GONE);
ibNext.setVisibility(GONE);
}
}

private void updateVolume() {
Expand Down Expand Up @@ -167,6 +231,13 @@ public void setHideOffline(boolean hideOffline) {
update();
}

public void setShowNowPlaying(boolean show) {
if (this.showNowPlaying == show)
return;
this.showNowPlaying = show;
update();
}

@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (!fromUser)
Expand Down Expand Up @@ -231,6 +302,22 @@ public void onClick(View v) {
listener.onMute(this, group.isMuted());
} else if (v == ibSettings) {
listener.onPropertiesClicked(this);
} else if (v == ibPrevious || v == ibPlayPause || v == ibNext) {
if (listener == null)
return;
String streamId = group.getStreamId();
if (v == ibPrevious) {
listener.onStreamControl(streamId, "previous");
} else if (v == ibNext) {
listener.onStreamControl(streamId, "next");
} else {
Stream stream = server.getStream(streamId);
if (stream != null && stream.getProperties() != null && stream.getProperties().isPlaying()) {
listener.onStreamControl(streamId, "pause");
} else {
listener.onStreamControl(streamId, "play");
}
}
}
}

Expand Down Expand Up @@ -307,6 +394,8 @@ public interface GroupItemListener {
void onPropertiesClicked(GroupItem group);

void onGroupStreamChanged(Group group, String streamId);

void onStreamControl(String streamId, String command);
}

}
12 changes: 12 additions & 0 deletions Snapcast/src/main/java/de/badaix/snapcast/GroupListFragment.java
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,18 @@ View getView(int position, @Nullable View convertView,
}
groupItem.setHideOffline(hideOffline);
groupItem.setListener(listener);

boolean isFirstForStream = true;
String streamId = group.getStreamId();
for (int i = 0; i < position; i++) {
Group prev = getItem(i);
if (prev != null && streamId.equals(prev.getStreamId())) {
isFirstForStream = false;
break;
}
}
groupItem.setShowNowPlaying(isFirstForStream);

return groupItem;
}

Expand Down
23 changes: 23 additions & 0 deletions Snapcast/src/main/java/de/badaix/snapcast/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
import de.badaix.snapcast.control.json.Group;
import de.badaix.snapcast.control.json.ServerStatus;
import de.badaix.snapcast.control.json.Stream;
import de.badaix.snapcast.control.json.StreamProperties;
import de.badaix.snapcast.control.json.Volume;
import de.badaix.snapcast.utils.NsdHelper;
import de.badaix.snapcast.utils.Settings;
Expand Down Expand Up @@ -758,4 +759,26 @@ public void onUpdate(String streamId, Stream stream) {
serverStatus.updateStream(stream);
groupListFragment.updateServer(serverStatus);
}

@Override
public void onStreamPropertiesChanged(String streamId, StreamProperties properties) {
Stream stream = serverStatus.getStream(streamId);
if (stream == null) {
remoteControl.getServerStatus();
return;
}
StreamProperties existing = stream.getProperties();
if (existing != null) {
existing.merge(properties);
} else {
stream.setProperties(properties);
}
groupListFragment.updateServer(serverStatus);
}

@Override
public void onStreamControl(String streamId, String command) {
if (remoteControl != null)
remoteControl.controlStream(streamId, command);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import de.badaix.snapcast.control.json.Group;
import de.badaix.snapcast.control.json.ServerStatus;
import de.badaix.snapcast.control.json.Stream;
import de.badaix.snapcast.control.json.StreamProperties;
import de.badaix.snapcast.control.json.Volume;

/**
Expand Down Expand Up @@ -159,6 +160,8 @@ private void processJson(JSONObject json) {
listener.onUpdate(new ServerStatus(response.result.getJSONObject("server")));
} else if (request.method.equals("Server.DeleteClient")) {
listener.onUpdate(new ServerStatus(response.result.getJSONObject("server")));
} else if (request.method.equals("Stream.Control")) {
// response is just "ok", nothing to propagate
}
} else {
/// Notification
Expand All @@ -183,6 +186,12 @@ private void processJson(JSONObject json) {
listener.onStreamChanged(rpcEvent, notification.params.getString("id"), notification.params.getString("stream_id"));
} else if (notification.method.equals("Stream.OnUpdate")) {
listener.onUpdate(notification.params.getString("id"), new Stream(notification.params.getJSONObject("stream")));
} else if (notification.method.equals("Stream.OnProperties")) {
String streamId = notification.params.getString("id");
JSONObject propsJson = notification.params.has("properties")
? notification.params.getJSONObject("properties")
: notification.params;
listener.onStreamPropertiesChanged(streamId, new StreamProperties(propsJson));
} else if (notification.method.equals("Group.OnUpdate")) {
listener.onUpdate(new Group(notification.params.getJSONObject("group")));
} else if (notification.method.equals("Server.OnUpdate")) {
Expand Down Expand Up @@ -347,6 +356,20 @@ public void delete(Client client) {
}
}

public void controlStream(String streamId, String command) {
try {
JSONObject params = new JSONObject();
params.put("id", streamId);
params.put("command", command);
params.put("params", new JSONObject());
RPCRequest request = jsonRequest("Stream.Control", params);
if (isConnected())
tcpClient.sendMessage(request.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}

public enum ClientEvent {
connected("Client.OnConnect"),
disconnected("Client.OnDisconnect"),
Expand Down Expand Up @@ -399,6 +422,8 @@ public interface GroupListener {

public interface StreamListener {
void onUpdate(String streamId, Stream stream);

void onStreamPropertiesChanged(String streamId, StreamProperties properties);
}

public interface ServerListener {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ public boolean updateStream(Stream stream) {
if (stream.getId().equals(s.getId())) {
if (s.equals(stream))
return false;
if (stream.getProperties() == null && s.getProperties() != null)
stream.setProperties(s.getProperties());
streams.set(i, stream);
return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public class Stream implements JsonSerialisable {
private StreamUri uri;
private String id;
private Status status;
private StreamProperties properties;

public Stream(JSONObject json) {
fromJson(json);
Expand All @@ -47,6 +48,9 @@ public void fromJson(JSONObject json) {
id = json.getString("id");
status = Status.unknown;
}
if (json.has("properties")) {
properties = new StreamProperties(json.getJSONObject("properties"));
}
} catch (JSONException e) {
e.printStackTrace();
}
Expand All @@ -59,6 +63,8 @@ public JSONObject toJson() {
json.put("uri", uri.toJson());
json.put("id", id);
json.put("status", status);
if (properties != null)
json.put("properties", properties.toJson());
} catch (JSONException e) {
e.printStackTrace();
}
Expand All @@ -74,14 +80,16 @@ public boolean equals(Object o) {

if (!Objects.equals(uri, stream.uri)) return false;
if (!Objects.equals(id, stream.id)) return false;
return Objects.equals(status, stream.status);
if (!Objects.equals(status, stream.status)) return false;
return Objects.equals(properties, stream.properties);
}

@Override
public int hashCode() {
int result = uri != null ? uri.hashCode() : 0;
result = 31 * result + (id != null ? id.hashCode() : 0);
result = 31 * result + (status != null ? status.hashCode() : 0);
result = 31 * result + (properties != null ? properties.hashCode() : 0);
return result;
}

Expand Down Expand Up @@ -113,6 +121,14 @@ public String getName() {
return uri.getName();
}

public StreamProperties getProperties() {
return properties;
}

public void setProperties(StreamProperties properties) {
this.properties = properties;
}

@Override
public String toString() {
return toJson().toString();
Expand Down
Loading
Loading