mirror of
https://github.com/badaix/snapcast.git
synced 2025-05-11 08:06:41 +02:00
Groups: interims commit
This commit is contained in:
parent
22f768311d
commit
0af508f6ee
14 changed files with 555 additions and 328 deletions
|
@ -20,8 +20,8 @@ package de.badaix.snapcast;
|
|||
|
||||
import android.content.Context;
|
||||
import android.support.v7.widget.PopupMenu;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.ImageButton;
|
||||
|
@ -36,19 +36,21 @@ import de.badaix.snapcast.control.json.Volume;
|
|||
|
||||
public class ClientItem extends LinearLayout implements SeekBar.OnSeekBarChangeListener, View.OnClickListener, PopupMenu.OnMenuItemClickListener {
|
||||
|
||||
private static final String TAG = "ClientItem";
|
||||
|
||||
private TextView title;
|
||||
private SeekBar volumeSeekBar;
|
||||
private ImageButton ibMute;
|
||||
private ImageButton ibOverflow;
|
||||
private Client client;
|
||||
private ServerStatus server;
|
||||
private ClientInfoItemListener listener = null;
|
||||
private ClientItemListener listener = null;
|
||||
|
||||
public ClientItem(Context context, ServerStatus server, Client client) {
|
||||
super(context);
|
||||
LayoutInflater vi = (LayoutInflater) context
|
||||
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
vi.inflate(R.layout.client_info, this);
|
||||
vi.inflate(R.layout.client_item, this);
|
||||
title = (TextView) findViewById(R.id.title);
|
||||
volumeSeekBar = (SeekBar) findViewById(R.id.volumeSeekBar);
|
||||
ibMute = (ImageButton) findViewById(R.id.ibMute);
|
||||
|
@ -59,9 +61,11 @@ public class ClientItem extends LinearLayout implements SeekBar.OnSeekBarChangeL
|
|||
setClient(client);
|
||||
volumeSeekBar.setOnSeekBarChangeListener(this);
|
||||
this.server = server;
|
||||
update();
|
||||
}
|
||||
|
||||
private void update() {
|
||||
Log.d(TAG, "update: " + client.getVisibleName() + ", connected: " + client.isConnected());
|
||||
title.setText(client.getVisibleName());
|
||||
title.setEnabled(client.isConnected());
|
||||
volumeSeekBar.setProgress(client.getConfig().getVolume().getPercent());
|
||||
|
@ -80,7 +84,7 @@ public class ClientItem extends LinearLayout implements SeekBar.OnSeekBarChangeL
|
|||
update();
|
||||
}
|
||||
|
||||
public void setListener(ClientInfoItemListener listener) {
|
||||
public void setListener(ClientItemListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
|
@ -95,7 +99,7 @@ public class ClientItem extends LinearLayout implements SeekBar.OnSeekBarChangeL
|
|||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (v == ibMute) {
|
||||
/* TODO: group if (v == ibMute) {
|
||||
Volume volume = client.getConfig().getVolume();
|
||||
volume.setMuted(!volume.isMuted());
|
||||
update();
|
||||
|
@ -125,6 +129,7 @@ public class ClientItem extends LinearLayout implements SeekBar.OnSeekBarChangeL
|
|||
popup.setOnMenuItemClickListener(this);
|
||||
popup.show();
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -151,7 +156,7 @@ public class ClientItem extends LinearLayout implements SeekBar.OnSeekBarChangeL
|
|||
}
|
||||
}
|
||||
|
||||
public interface ClientInfoItemListener {
|
||||
public interface ClientItemListener {
|
||||
void onVolumeChanged(ClientItem clientItem, int percent);
|
||||
|
||||
void onMute(ClientItem clientItem, boolean mute);
|
||||
|
@ -159,8 +164,6 @@ public class ClientItem extends LinearLayout implements SeekBar.OnSeekBarChangeL
|
|||
void onDeleteClicked(ClientItem clientItem);
|
||||
|
||||
void onPropertiesClicked(ClientItem clientItem);
|
||||
|
||||
void onStreamClicked(ClientItem clientItem, Stream stream);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -27,17 +27,15 @@ import android.view.View;
|
|||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import de.badaix.snapcast.control.json.Client;
|
||||
import de.badaix.snapcast.control.json.Group;
|
||||
import de.badaix.snapcast.control.json.ServerStatus;
|
||||
import de.badaix.snapcast.control.json.Stream;
|
||||
|
||||
|
||||
/**
|
||||
* A simple {@link Fragment} subclass.
|
||||
* Activities that contain this fragment must implement the
|
||||
* {@link ClientItem.ClientInfoItemListener} interface
|
||||
* {@link GroupItem.GroupItemListener} interface
|
||||
* to handle interaction events.
|
||||
*/
|
||||
public class ClientListFragment extends Fragment {
|
||||
|
@ -49,14 +47,10 @@ public class ClientListFragment extends Fragment {
|
|||
private static final String ARG_PARAM1 = "param1";
|
||||
private static final String ARG_PARAM2 = "param2";
|
||||
|
||||
// TODO: Rename and change types of parameters
|
||||
private Stream stream;
|
||||
|
||||
private ClientItem.ClientInfoItemListener clientInfoItemListener;
|
||||
private ClientInfoAdapter clientInfoAdapter;
|
||||
private GroupItem.GroupItemListener groupItemListener;
|
||||
private GroupAdapter groupAdapter;
|
||||
private ServerStatus serverStatus = null;
|
||||
private boolean hideOffline = false;
|
||||
private TextView tvStreamState = null;
|
||||
|
||||
public ClientListFragment() {
|
||||
// Required empty public constructor
|
||||
|
@ -93,35 +87,27 @@ public class ClientListFragment extends Fragment {
|
|||
// Inflate the layout for this fragment
|
||||
Log.d(TAG, "onCreateView: " + this.toString());
|
||||
View view = inflater.inflate(R.layout.fragment_client_list, container, false);
|
||||
tvStreamState = (TextView) view.findViewById(R.id.tvStreamState);
|
||||
ListView lvClient = (ListView) view.findViewById(R.id.lvClient);
|
||||
clientInfoAdapter = new ClientInfoAdapter(getContext(), clientInfoItemListener);
|
||||
clientInfoAdapter.setHideOffline(hideOffline);
|
||||
clientInfoAdapter.updateServer(serverStatus);
|
||||
lvClient.setAdapter(clientInfoAdapter);
|
||||
ListView lvGroup = (ListView) view.findViewById(R.id.lvGroup);
|
||||
groupAdapter = new GroupAdapter(getContext(), groupItemListener);
|
||||
groupAdapter.setHideOffline(hideOffline);
|
||||
groupAdapter.updateServer(serverStatus);
|
||||
lvGroup.setAdapter(groupAdapter);
|
||||
updateGui();
|
||||
return view;
|
||||
}
|
||||
|
||||
|
||||
private void updateGui() {
|
||||
Log.d(TAG, "(tvStreamState == null): " + (tvStreamState == null) + " " + this.toString());
|
||||
if ((tvStreamState == null) || (stream == null))
|
||||
return;
|
||||
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());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
if (context instanceof ClientItem.ClientInfoItemListener) {
|
||||
clientInfoItemListener = (ClientItem.ClientInfoItemListener) context;
|
||||
if (context instanceof GroupItem.GroupItemListener) {
|
||||
groupItemListener = (GroupItem.GroupItemListener) context;
|
||||
} else {
|
||||
throw new RuntimeException(context.toString()
|
||||
+ " must implement ClientInfoItemListener");
|
||||
+ " must implement GroupItemListener");
|
||||
}
|
||||
updateGui();
|
||||
}
|
||||
|
@ -129,39 +115,28 @@ public class ClientListFragment extends Fragment {
|
|||
@Override
|
||||
public void onDetach() {
|
||||
super.onDetach();
|
||||
clientInfoItemListener = null;
|
||||
groupItemListener = null;
|
||||
}
|
||||
|
||||
public void updateServer(ServerStatus serverStatus) {
|
||||
this.serverStatus = serverStatus;
|
||||
if (clientInfoAdapter != null)
|
||||
clientInfoAdapter.updateServer(this.serverStatus);
|
||||
if (groupAdapter != null)
|
||||
groupAdapter.updateServer(this.serverStatus);
|
||||
}
|
||||
|
||||
public void setHideOffline(boolean hide) {
|
||||
this.hideOffline = hide;
|
||||
if (clientInfoAdapter != null)
|
||||
clientInfoAdapter.setHideOffline(hideOffline);
|
||||
if (groupAdapter != null)
|
||||
groupAdapter.setHideOffline(hideOffline);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return stream.getName();
|
||||
}
|
||||
|
||||
public void setStream(Stream stream) {
|
||||
Log.d(TAG, "setStream: " + stream.getName() + ", status: " + stream.getStatus());
|
||||
this.stream = stream;
|
||||
updateGui();
|
||||
}
|
||||
|
||||
|
||||
public class ClientInfoAdapter extends ArrayAdapter<Client> {
|
||||
public class GroupAdapter extends ArrayAdapter<Group> {
|
||||
private Context context;
|
||||
private ClientItem.ClientInfoItemListener listener;
|
||||
private GroupItem.GroupItemListener listener;
|
||||
private boolean hideOffline = false;
|
||||
private ServerStatus serverStatus = new ServerStatus();
|
||||
|
||||
public ClientInfoAdapter(Context context, ClientItem.ClientInfoItemListener listener) {
|
||||
public GroupAdapter(Context context, GroupItem.GroupItemListener listener) {
|
||||
super(context, 0);
|
||||
this.context = context;
|
||||
this.listener = listener;
|
||||
|
@ -169,22 +144,22 @@ public class ClientListFragment extends Fragment {
|
|||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
Client client = getItem(position);
|
||||
final ClientItem clientItem;
|
||||
Group group = getItem(position);
|
||||
final GroupItem groupItem;
|
||||
|
||||
if (convertView != null) {
|
||||
clientItem = (ClientItem) convertView;
|
||||
clientItem.setClient(client);
|
||||
groupItem = (GroupItem) convertView;
|
||||
groupItem.setGroup(group);
|
||||
} else {
|
||||
clientItem = new ClientItem(context, serverStatus, client);
|
||||
groupItem = new GroupItem(context, serverStatus, group);
|
||||
}
|
||||
clientItem.setListener(listener);
|
||||
return clientItem;
|
||||
groupItem.setListener(listener);
|
||||
return groupItem;
|
||||
}
|
||||
|
||||
public void updateServer(final ServerStatus serverStatus) {
|
||||
if (serverStatus != null) {
|
||||
ClientInfoAdapter.this.serverStatus = serverStatus;
|
||||
GroupAdapter.this.serverStatus = serverStatus;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
@ -192,10 +167,16 @@ public class ClientListFragment extends Fragment {
|
|||
|
||||
public void update() {
|
||||
clear();
|
||||
for (Client client : ClientInfoAdapter.this.serverStatus.getClientInfos()) {
|
||||
if ((client != null) && (!hideOffline || client.isConnected()) && !client.isDeleted() && client.getConfig().getStream().equals(ClientListFragment.this.stream.getId()))
|
||||
add(client);
|
||||
// TODO: group
|
||||
for (Group group : GroupAdapter.this.serverStatus.getGroups()) {
|
||||
add(group);
|
||||
/* for (Client client : group.getClients()) {
|
||||
if ((client != null) && (!hideOffline || client.isConnected()) && !client.isDeleted())// && client.getConfig().getStream().equals(ClientListFragment.this.stream.getId()))
|
||||
add(client);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
if (getActivity() != null) {
|
||||
ClientListFragment.this.getActivity().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
|
|
|
@ -94,6 +94,7 @@ public class ClientSettingsFragment extends PreferenceFragment {
|
|||
prefStream = (ListPreference) findPreference("pref_client_stream");
|
||||
prefStream.setEntries(streamNames);
|
||||
prefStream.setEntryValues(streamIds);
|
||||
/* TODO: group
|
||||
for (int i = 0; i < streams.size(); ++i) {
|
||||
if (streamIds[i].equals(client.getConfig().getStream())) {
|
||||
prefStream.setSummary(streamNames[i]);
|
||||
|
@ -116,6 +117,7 @@ public class ClientSettingsFragment extends PreferenceFragment {
|
|||
return false;
|
||||
}
|
||||
});
|
||||
*/
|
||||
prefMac = (Preference) findPreference("pref_client_mac");
|
||||
prefId = (Preference) findPreference("pref_client_id");
|
||||
prefIp = (Preference) findPreference("pref_client_ip");
|
||||
|
|
237
android/Snapcast/src/main/java/de/badaix/snapcast/GroupItem.java
Normal file
237
android/Snapcast/src/main/java/de/badaix/snapcast/GroupItem.java
Normal file
|
@ -0,0 +1,237 @@
|
|||
/*
|
||||
* This file is part of snapcast
|
||||
* Copyright (C) 2014-2016 Johannes Pohl
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.badaix.snapcast;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.v7.widget.PopupMenu;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import de.badaix.snapcast.control.json.Client;
|
||||
import de.badaix.snapcast.control.json.Group;
|
||||
import de.badaix.snapcast.control.json.ServerStatus;
|
||||
import de.badaix.snapcast.control.json.Stream;
|
||||
|
||||
/**
|
||||
* Created by johannes on 04.12.16.
|
||||
*/
|
||||
|
||||
|
||||
public class GroupItem extends LinearLayout implements SeekBar.OnSeekBarChangeListener, View.OnClickListener, PopupMenu.OnMenuItemClickListener, ClientItem.ClientItemListener {
|
||||
|
||||
private static final String TAG = "GroupItem";
|
||||
|
||||
// private TextView title;
|
||||
private SeekBar volumeSeekBar;
|
||||
private ImageButton ibMute;
|
||||
private ImageButton ibOverflow;
|
||||
private LinearLayout llClient;
|
||||
private Group group;
|
||||
private ServerStatus server;
|
||||
private TextView tvStreamState = null;
|
||||
private GroupItemListener listener = null;
|
||||
private Stream stream = null;
|
||||
private LinearLayout llVolume;
|
||||
|
||||
public GroupItem(Context context, ServerStatus server, Group group) {
|
||||
super(context);
|
||||
LayoutInflater vi = (LayoutInflater) context
|
||||
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
vi.inflate(R.layout.group_item, this);
|
||||
// title = (TextView) findViewById(R.id.title);
|
||||
volumeSeekBar = (SeekBar) findViewById(R.id.volumeSeekBar);
|
||||
ibMute = (ImageButton) findViewById(R.id.ibMute);
|
||||
ibMute.setImageResource(R.drawable.ic_speaker_icon);
|
||||
ibMute.setOnClickListener(this);
|
||||
ibOverflow = (ImageButton) findViewById(R.id.ibOverflow);
|
||||
ibOverflow.setOnClickListener(this);
|
||||
llVolume = (LinearLayout) findViewById(R.id.llVolume);
|
||||
llVolume.setVisibility(GONE);
|
||||
llClient = (LinearLayout) findViewById(R.id.llClient);
|
||||
llClient.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
|
||||
tvStreamState = (TextView) findViewById(R.id.tvStreamState);
|
||||
setGroup(group);
|
||||
volumeSeekBar.setOnSeekBarChangeListener(this);
|
||||
this.server = server;
|
||||
stream = server.getStream(group.getStreamId());
|
||||
update();
|
||||
}
|
||||
|
||||
private void update() {
|
||||
// title.setText(group.getName());
|
||||
llClient.removeAllViews();
|
||||
for (Client client : group.getClients()) {
|
||||
ClientItem clientItem = new ClientItem(this.getContext(), server, client);
|
||||
clientItem.setListener(this);
|
||||
llClient.addView(clientItem);
|
||||
}
|
||||
Log.d(TAG, "(tvStreamState == null): " + (tvStreamState == null) + " " + this.toString());
|
||||
|
||||
if ((tvStreamState == null) || (stream == null))
|
||||
return;
|
||||
tvStreamState.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);
|
||||
*/
|
||||
}
|
||||
|
||||
public Group getGroup() {
|
||||
return group;
|
||||
}
|
||||
|
||||
public void setGroup(final Group group) {
|
||||
this.group = group;
|
||||
update();
|
||||
}
|
||||
|
||||
public void setStream(Stream stream) {
|
||||
Log.d(TAG, "setStream: " + stream.getName() + ", status: " + stream.getStatus());
|
||||
this.stream = stream;
|
||||
update();
|
||||
}
|
||||
|
||||
public void setListener(GroupItemListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||
/* if (fromUser && (listener != null)) {
|
||||
Volume volume = new Volume(progress, false);
|
||||
client.setVolume(volume);
|
||||
listener.onVolumeChanged(this, volume.getPercent());
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
/* TODO: group if (v == ibMute) {
|
||||
Volume volume = client.getConfig().getVolume();
|
||||
volume.setMuted(!volume.isMuted());
|
||||
update();
|
||||
listener.onMute(this, volume.isMuted());
|
||||
} else if (v == ibOverflow) {
|
||||
PopupMenu popup = new PopupMenu(v.getContext(), v);
|
||||
popup.getMenu().add(Menu.NONE, R.id.menu_details, 0, R.string.menu_details);
|
||||
if (!client.isConnected())
|
||||
popup.getMenu().add(Menu.NONE, R.id.menu_delete, 1, R.string.menu_delete);
|
||||
if ((server != null) && (server.getStreams().size() > 1)) {
|
||||
int pos = 2;
|
||||
for (final Stream stream : server.getStreams()) {
|
||||
if (client.getConfig().getStream().equals(stream.getId()))
|
||||
continue;
|
||||
final MenuItem menuItem = popup.getMenu().add(Menu.NONE, Menu.NONE, pos, stream.getName());
|
||||
menuItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
listener.onStreamClicked(ClientItem.this, stream);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
popup.setOnMenuItemClickListener(this);
|
||||
popup.show();
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
/* switch (item.getItemId()) {
|
||||
case R.id.menu_details:
|
||||
listener.onPropertiesClicked(this);
|
||||
return true;
|
||||
case R.id.menu_delete:
|
||||
listener.onDeleteClicked(this);
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onVolumeChanged(ClientItem clientItem, int percent) {
|
||||
if (listener != null)
|
||||
listener.onVolumeChanged(this, clientItem, percent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMute(ClientItem clientItem, boolean mute) {
|
||||
if (listener != null)
|
||||
listener.onMute(this, clientItem, mute);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeleteClicked(ClientItem clientItem) {
|
||||
if (listener != null)
|
||||
listener.onDeleteClicked(this, clientItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPropertiesClicked(ClientItem clientItem) {
|
||||
if (listener != null)
|
||||
listener.onPropertiesClicked(this, clientItem);
|
||||
}
|
||||
|
||||
|
||||
public interface GroupItemListener {
|
||||
void onVolumeChanged(GroupItem group, ClientItem clientItem, int percent);
|
||||
|
||||
void onMute(GroupItem group, ClientItem clientItem, boolean mute);
|
||||
|
||||
void onDeleteClicked(GroupItem group, ClientItem clientItem);
|
||||
|
||||
void onPropertiesClicked(GroupItem group, ClientItem clientItem);
|
||||
|
||||
void onStreamClicked(GroupItem group, Stream stream);
|
||||
}
|
||||
|
||||
}
|
|
@ -35,11 +35,6 @@ import android.os.IBinder;
|
|||
import android.support.design.widget.CoordinatorLayout;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.design.widget.TabLayout;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentPagerAdapter;
|
||||
import android.support.v4.app.FragmentStatePagerAdapter;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
|
@ -48,24 +43,20 @@ import android.text.TextUtils;
|
|||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Vector;
|
||||
|
||||
import de.badaix.snapcast.control.RemoteControl;
|
||||
import de.badaix.snapcast.control.json.Client;
|
||||
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.utils.NsdHelper;
|
||||
import de.badaix.snapcast.utils.Settings;
|
||||
import de.badaix.snapcast.utils.Setup;
|
||||
|
||||
public class MainActivity extends AppCompatActivity implements ClientItem.ClientInfoItemListener, RemoteControl.RemoteControlListener, SnapclientService.SnapclientListener, NsdHelper.NsdHelperListener {
|
||||
public class MainActivity extends AppCompatActivity implements GroupItem.GroupItemListener, RemoteControl.RemoteControlListener, SnapclientService.SnapclientListener, NsdHelper.NsdHelperListener {
|
||||
|
||||
static final int CLIENT_PROPERTIES_REQUEST = 1;
|
||||
private static final String TAG = "Main";
|
||||
|
@ -80,17 +71,12 @@ public class MainActivity extends AppCompatActivity implements ClientItem.Client
|
|||
private RemoteControl remoteControl = null;
|
||||
private ServerStatus serverStatus = null;
|
||||
private SnapclientService snapclientService;
|
||||
private SectionsPagerAdapter sectionsPagerAdapter;
|
||||
private ClientListFragment clientListFragment;
|
||||
private TabLayout tabLayout;
|
||||
private Snackbar warningSamplerateSnackbar = null;
|
||||
private int nativeSampleRate = 0;
|
||||
private CoordinatorLayout coordinatorLayout;
|
||||
|
||||
/**
|
||||
* The {@link ViewPager} that will host the section contents.
|
||||
*/
|
||||
private ViewPager mViewPager;
|
||||
|
||||
|
||||
/**
|
||||
* Defines callbacks for service binding, passed to bindService()
|
||||
|
@ -139,15 +125,8 @@ public class MainActivity extends AppCompatActivity implements ClientItem.Client
|
|||
setSupportActionBar(toolbar);
|
||||
// Create the adapter that will return a fragment for each of the three
|
||||
// primary sections of the activity.
|
||||
sectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
|
||||
|
||||
// Set up the ViewPager with the sections adapter.
|
||||
mViewPager = (ViewPager) findViewById(R.id.container);
|
||||
mViewPager.setAdapter(sectionsPagerAdapter);
|
||||
|
||||
tabLayout = (TabLayout) findViewById(R.id.tabs);
|
||||
tabLayout.setupWithViewPager(mViewPager);
|
||||
mViewPager.setVisibility(View.GONE);
|
||||
clientListFragment = (ClientListFragment) getSupportFragmentManager().findFragmentById(R.id.clientListFragment);
|
||||
|
||||
setActionbarSubtitle("Host: no Snapserver found");
|
||||
|
||||
|
@ -159,8 +138,6 @@ public class MainActivity extends AppCompatActivity implements ClientItem.Client
|
|||
Log.d(TAG, "done copying snapclient");
|
||||
}
|
||||
}).start();
|
||||
|
||||
sectionsPagerAdapter.setHideOffline(Settings.getInstance(this).getBoolean("hide_offline", false));
|
||||
}
|
||||
|
||||
public void checkFirstRun() {
|
||||
|
@ -195,7 +172,6 @@ public class MainActivity extends AppCompatActivity implements ClientItem.Client
|
|||
boolean isChecked = Settings.getInstance(this).getBoolean("hide_offline", false);
|
||||
MenuItem menuItem = menu.findItem(R.id.action_hide_offline);
|
||||
menuItem.setChecked(isChecked);
|
||||
sectionsPagerAdapter.setHideOffline(isChecked);
|
||||
// setHost(host, port, controlPort);
|
||||
if (remoteControl != null) {
|
||||
updateMenuItems(remoteControl.isConnected());
|
||||
|
@ -241,7 +217,7 @@ public class MainActivity extends AppCompatActivity implements ClientItem.Client
|
|||
} else if (id == R.id.action_hide_offline) {
|
||||
item.setChecked(!item.isChecked());
|
||||
Settings.getInstance(this).put("hide_offline", item.isChecked());
|
||||
sectionsPagerAdapter.setHideOffline(item.isChecked());
|
||||
//TODO: group sectionsPagerAdapter.setHideOffline(item.isChecked());
|
||||
return true;
|
||||
} else if (id == R.id.action_refresh) {
|
||||
startRemoteControl();
|
||||
|
@ -407,7 +383,7 @@ public class MainActivity extends AppCompatActivity implements ClientItem.Client
|
|||
return;
|
||||
}
|
||||
if (requestCode == CLIENT_PROPERTIES_REQUEST) {
|
||||
Client client = null;
|
||||
/* TODO: group Client client = null;
|
||||
try {
|
||||
client = new Client(new JSONObject(data.getStringExtra("client")));
|
||||
} catch (JSONException e) {
|
||||
|
@ -432,17 +408,12 @@ public class MainActivity extends AppCompatActivity implements ClientItem.Client
|
|||
remoteControl.setLatency(client, client.getConfig().getLatency());
|
||||
serverStatus.updateClient(client);
|
||||
sectionsPagerAdapter.updateServer(serverStatus);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnected(RemoteControl remoteControl) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mViewPager.setVisibility(View.VISIBLE);
|
||||
}
|
||||
});
|
||||
setActionbarSubtitle(remoteControl.getHost());
|
||||
remoteControl.getServerStatus();
|
||||
updateMenuItems(true);
|
||||
|
@ -457,7 +428,7 @@ public class MainActivity extends AppCompatActivity implements ClientItem.Client
|
|||
public void onDisconnected(RemoteControl remoteControl, Exception e) {
|
||||
Log.d(TAG, "onDisconnected");
|
||||
serverStatus = new ServerStatus();
|
||||
sectionsPagerAdapter.updateServer(serverStatus);
|
||||
//TODO: group sectionsPagerAdapter.updateServer(serverStatus);
|
||||
if (e != null) {
|
||||
if (e instanceof UnknownHostException)
|
||||
setActionbarSubtitle("error: unknown host");
|
||||
|
@ -466,38 +437,38 @@ public class MainActivity extends AppCompatActivity implements ClientItem.Client
|
|||
} else {
|
||||
setActionbarSubtitle("not connected");
|
||||
}
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mViewPager.setVisibility(View.GONE);
|
||||
}
|
||||
});
|
||||
updateMenuItems(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClientEvent(RemoteControl remoteControl, Client client, RemoteControl.ClientEvent event) {
|
||||
Log.d(TAG, "onClientEvent: " + event.toString());
|
||||
remoteControl.getServerStatus();
|
||||
/* TODO: group
|
||||
if (event == RemoteControl.ClientEvent.deleted)
|
||||
serverStatus.removeClient(client);
|
||||
else
|
||||
serverStatus.updateClient(client);
|
||||
|
||||
sectionsPagerAdapter.updateServer(serverStatus);
|
||||
*/
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServerStatus(RemoteControl remoteControl, ServerStatus serverStatus) {
|
||||
this.serverStatus = serverStatus;
|
||||
for (Stream s : serverStatus.getStreams())
|
||||
Log.d(TAG, s.toString());
|
||||
sectionsPagerAdapter.updateServer(serverStatus);
|
||||
MainActivity.this.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
clientListFragment.updateServer(MainActivity.this.serverStatus);
|
||||
}
|
||||
});
|
||||
// TODO: group sectionsPagerAdapter.updateServer(serverStatus);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStreamUpdate(RemoteControl remoteControl, Stream stream) {
|
||||
serverStatus.updateStream(stream);
|
||||
sectionsPagerAdapter.updateServer(serverStatus);
|
||||
// TODO: group sectionsPagerAdapter.updateServer(serverStatus);
|
||||
}
|
||||
|
||||
|
||||
|
@ -558,19 +529,20 @@ public class MainActivity extends AppCompatActivity implements ClientItem.Client
|
|||
|
||||
|
||||
@Override
|
||||
public void onVolumeChanged(ClientItem clientItem, int percent) {
|
||||
public void onVolumeChanged(GroupItem groupItem, ClientItem clientItem, int percent) {
|
||||
remoteControl.setVolume(clientItem.getClient(), percent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMute(ClientItem clientItem, boolean mute) {
|
||||
public void onMute(GroupItem groupItem, ClientItem clientItem, boolean mute) {
|
||||
remoteControl.setMute(clientItem.getClient(), mute);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeleteClicked(final ClientItem clientItem) {
|
||||
public void onDeleteClicked(GroupItem groupItem, final ClientItem clientItem) {
|
||||
final Client client = clientItem.getClient();
|
||||
client.setDeleted(true);
|
||||
/* TODO: group
|
||||
serverStatus.updateClient(client);
|
||||
sectionsPagerAdapter.updateServer(serverStatus);
|
||||
Snackbar mySnackbar = Snackbar.make(findViewById(R.id.myCoordinatorLayout),
|
||||
|
@ -595,10 +567,11 @@ public class MainActivity extends AppCompatActivity implements ClientItem.Client
|
|||
}
|
||||
});
|
||||
mySnackbar.show();
|
||||
*/
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPropertiesClicked(ClientItem clientItem) {
|
||||
public void onPropertiesClicked(GroupItem groupItem, ClientItem clientItem) {
|
||||
Intent intent = new Intent(this, ClientSettingsActivity.class);
|
||||
intent.putExtra("client", clientItem.getClient().toJson().toString());
|
||||
intent.putExtra("streams", serverStatus.getJsonStreams().toString());
|
||||
|
@ -607,78 +580,15 @@ public class MainActivity extends AppCompatActivity implements ClientItem.Client
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onStreamClicked(ClientItem clientItem, Stream stream) {
|
||||
public void onStreamClicked(GroupItem groupItem, Stream stream) {
|
||||
/* TODO: group
|
||||
Client client = clientItem.getClient();
|
||||
client.getConfig().setStream(stream.getId());
|
||||
remoteControl.setStream(client, client.getConfig().getStream());
|
||||
serverStatus.updateClient(client);
|
||||
sectionsPagerAdapter.updateServer(serverStatus);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A {@link FragmentPagerAdapter} that returns a fragment corresponding to
|
||||
* one of the sections/tabs/pages.
|
||||
*/
|
||||
public class SectionsPagerAdapter extends FragmentStatePagerAdapter {
|
||||
|
||||
private Vector<ClientListFragment> fragments = new Vector<>();
|
||||
private int streamCount = 0;
|
||||
private boolean hideOffline = false;
|
||||
|
||||
public SectionsPagerAdapter(FragmentManager fm) {
|
||||
super(fm);
|
||||
}
|
||||
|
||||
public void updateServer(final ServerStatus serverStatus) {
|
||||
MainActivity.this.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Log.d(TAG, "updateServer: " + serverStatus.getStreams().size());
|
||||
boolean changed = (serverStatus.getStreams().size() != streamCount);
|
||||
|
||||
while (serverStatus.getStreams().size() > fragments.size())
|
||||
fragments.add(new ClientListFragment());
|
||||
|
||||
for (int i = 0; i < serverStatus.getStreams().size(); ++i) {
|
||||
fragments.get(i).setStream(serverStatus.getStreams().get(i));
|
||||
fragments.get(i).updateServer(serverStatus);
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
streamCount = serverStatus.getStreams().size();
|
||||
notifyDataSetChanged();
|
||||
tabLayout.setTabsFromPagerAdapter(SectionsPagerAdapter.this);
|
||||
}
|
||||
setHideOffline(hideOffline);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public void setHideOffline(boolean hide) {
|
||||
this.hideOffline = hide;
|
||||
for (ClientListFragment clientListFragment : fragments)
|
||||
clientListFragment.setHideOffline(hide);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
return fragments.get(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return streamCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getPageTitle(int position) {
|
||||
return fragments.get(position).getName();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -88,27 +88,28 @@ public class ServerStatus implements JsonSerialisable {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
public boolean updateClient(Client client) {
|
||||
if (client == null)
|
||||
return false;
|
||||
|
||||
public boolean updateClient(Client client) {
|
||||
if (client == null)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < clients.size(); ++i) {
|
||||
Client clientInfo = clients.get(i);
|
||||
if (clientInfo == null)
|
||||
for (Group group : groups) {
|
||||
for (int i = 0; i < group.getClients().size(); ++i) {
|
||||
Client c = group.getClients().get(i);
|
||||
if (c == null)
|
||||
continue;
|
||||
|
||||
if (client.getId().equals(clientInfo.getId())) {
|
||||
if (clientInfo.equals(client))
|
||||
return false;
|
||||
clients.set(i, client);
|
||||
if (client.getId().equals(c.getId())) {
|
||||
if (client.equals(c))
|
||||
return true;
|
||||
group.getClients().set(i, client);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
clients.add(client);
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean updateStream(Stream stream) {
|
||||
if (stream == null)
|
||||
return false;
|
||||
|
@ -137,6 +138,13 @@ public class ServerStatus implements JsonSerialisable {
|
|||
return streams;
|
||||
}
|
||||
|
||||
public Stream getStream(String id) {
|
||||
for (Stream s : streams)
|
||||
if ((s != null) && (s.getId().equals(id)))
|
||||
return s;
|
||||
return null;
|
||||
}
|
||||
|
||||
public JSONArray getJsonStreams() {
|
||||
JSONArray jsonArray = new JSONArray();
|
||||
for (Stream stream : streams)
|
||||
|
|
|
@ -44,53 +44,15 @@
|
|||
|
||||
</android.support.v7.widget.Toolbar>
|
||||
|
||||
<android.support.design.widget.TabLayout
|
||||
android:id="@+id/tabs"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
</android.support.design.widget.AppBarLayout>
|
||||
|
||||
<android.support.v4.view.ViewPager
|
||||
android:id="@+id/container"
|
||||
<fragment
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="@dimen/activity_vertical_margin"
|
||||
android:paddingLeft="@dimen/activity_horizontal_margin"
|
||||
android:paddingRight="@dimen/activity_horizontal_margin"
|
||||
android:paddingTop="@dimen/activity_vertical_margin">
|
||||
|
||||
<!--
|
||||
<TextView
|
||||
android:id="@+id/tvInfo"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="3dp"
|
||||
android:text="Info: this is a prototype"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"/>
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/cbScreenWakelock"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Keep screen on"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="New Button"
|
||||
android:visibility="gone"/>
|
||||
-->
|
||||
</LinearLayout>
|
||||
android:layout_marginTop="?attr/actionBarSize"
|
||||
android:name="de.badaix.snapcast.ClientListFragment"
|
||||
android:id="@+id/clientListFragment"
|
||||
tools:layout="@layout/fragment_client_list"/>
|
||||
|
||||
</android.support.design.widget.CoordinatorLayout>
|
||||
|
||||
|
|
86
android/Snapcast/src/main/res/layout/client_item.xml
Normal file
86
android/Snapcast/src/main/res/layout/client_item.xml
Normal file
|
@ -0,0 +1,86 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ This file is part of snapcast
|
||||
~ Copyright (C) 2014-2016 Johannes Pohl
|
||||
~
|
||||
~ This program is free software: you can redistribute it and/or modify
|
||||
~ it under the terms of the GNU General Public License as published by
|
||||
~ the Free Software Foundation, either version 3 of the License, or
|
||||
~ (at your option) any later version.
|
||||
~
|
||||
~ This program 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 General Public License for more details.
|
||||
~
|
||||
~ You should have received a copy of the GNU General Public License
|
||||
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<!-- android:descendantFocusability="afterDescendants"-->
|
||||
<!-- android:paddingRight="?android:attr/scrollbarSize"-->
|
||||
<!-- android:background="@drawable/big_card"-->
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/ibOverflow"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:background="@null"
|
||||
android:src="@drawable/abc_ic_menu_moreoverflow_mtrl_alpha"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_toLeftOf="@id/ibOverflow"
|
||||
android:orientation="vertical">
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="marquee"
|
||||
android:fadingEdge="horizontal"
|
||||
android:paddingBottom="1dp"
|
||||
android:paddingLeft="5dp"
|
||||
android:paddingTop="2dp"
|
||||
android:singleLine="true"
|
||||
android:text="Title"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"/>
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal"
|
||||
android:paddingBottom="4dp"
|
||||
android:paddingLeft="3dp">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/ibMute"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@null"
|
||||
android:src="@drawable/ic_speaker_icon"/>
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/volumeSeekBar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:max="100"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
</FrameLayout>
|
||||
|
|
@ -23,38 +23,19 @@
|
|||
android:layout_height="match_parent"
|
||||
tools:context="de.badaix.snapcast.ClientListFragment">
|
||||
|
||||
|
||||
<RelativeLayout
|
||||
<ListView
|
||||
android:id="@+id/lvGroup"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ListView
|
||||
android:id="@+id/lvClient"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_above="@+id/tvStreamState"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:cacheColorHint="@android:color/transparent"
|
||||
android:divider="@null"
|
||||
android:dividerHeight="1dp"
|
||||
android:listSelector="@android:color/transparent"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvStreamState"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:padding="5dp"
|
||||
android:text="Stream state"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"/>
|
||||
</RelativeLayout>
|
||||
android:layout_height="match_parent"
|
||||
android:layout_above="@+id/tvStreamState"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:cacheColorHint="@android:color/transparent"
|
||||
android:divider="@null"
|
||||
android:dividerHeight="1dp"
|
||||
android:listSelector="@android:color/transparent"/>
|
||||
|
||||
</FrameLayout>
|
||||
|
|
|
@ -20,7 +20,8 @@
|
|||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
android:layout_height="wrap_content"
|
||||
>
|
||||
<!-- android:descendantFocusability="afterDescendants"-->
|
||||
<!-- android:paddingRight="?android:attr/scrollbarSize"-->
|
||||
<!-- android:background="@drawable/big_card"-->
|
||||
|
@ -32,21 +33,20 @@
|
|||
card_view:cardUseCompatPadding="true"
|
||||
card_view:contentPadding="2dp">
|
||||
|
||||
<RelativeLayout
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/ibOverflow"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:background="@null"
|
||||
android:src="@drawable/abc_ic_menu_moreoverflow_mtrl_alpha"/>
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/llClient"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"/>
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/llVolume"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
|
@ -54,19 +54,20 @@
|
|||
android:orientation="vertical">
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="marquee"
|
||||
android:fadingEdge="horizontal"
|
||||
android:paddingBottom="1dp"
|
||||
android:paddingLeft="5dp"
|
||||
android:paddingTop="2dp"
|
||||
android:singleLine="true"
|
||||
android:text="Title"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"/>
|
||||
|
||||
<!--
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="marquee"
|
||||
android:fadingEdge="horizontal"
|
||||
android:paddingBottom="1dp"
|
||||
android:paddingLeft="5dp"
|
||||
android:paddingTop="2dp"
|
||||
android:singleLine="true"
|
||||
android:text="Title"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"/>
|
||||
-->
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
|
@ -90,7 +91,33 @@
|
|||
android:max="100"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/ibOverflow"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:background="@null"
|
||||
android:src="@drawable/abc_ic_menu_moreoverflow_mtrl_alpha"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvStreamState"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:padding="5dp"
|
||||
android:text="Stream state"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"/>
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
||||
</android.support.v7.widget.CardView>
|
||||
</FrameLayout>
|
||||
|
|
@ -93,10 +93,13 @@ ClientInfoPtr Config::getClientInfo(const std::string& clientId) const
|
|||
if (clientId.empty())
|
||||
return nullptr;
|
||||
|
||||
for (auto client: clients)
|
||||
for (auto group: groups)
|
||||
{
|
||||
if (client->id == clientId)
|
||||
return client;
|
||||
for (auto client: group->clients)
|
||||
{
|
||||
if (client->id == clientId)
|
||||
return client;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
@ -109,13 +112,26 @@ ClientInfoPtr Config::addClientInfo(const std::string& clientId)
|
|||
if (!client)
|
||||
{
|
||||
client = make_shared<ClientInfo>(clientId);
|
||||
clients.push_back(client);
|
||||
//TODO: strange contruct
|
||||
getGroup(client);
|
||||
}
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
|
||||
GroupPtr Config::getGroup(const std::string& groupId) const
|
||||
{
|
||||
for (auto group: groups)
|
||||
{
|
||||
if (group->id == groupId)
|
||||
return group;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
GroupPtr Config::getGroup(ClientInfoPtr client)
|
||||
{
|
||||
for (auto group: groups)
|
||||
|
@ -127,8 +143,7 @@ GroupPtr Config::getGroup(ClientInfoPtr client)
|
|||
}
|
||||
}
|
||||
|
||||
GroupPtr group = std::make_shared<Group>();
|
||||
group->id = generateUUID();
|
||||
GroupPtr group = std::make_shared<Group>();//client);
|
||||
group->clients.push_back(client);
|
||||
groups.push_back(group);
|
||||
|
||||
|
@ -136,9 +151,9 @@ GroupPtr Config::getGroup(ClientInfoPtr client)
|
|||
}
|
||||
|
||||
|
||||
json Config::getServerStatus(const std::string& clientId, const json& streams) const
|
||||
json Config::getServerStatus(const json& streams) const
|
||||
{
|
||||
json jClient = json::array();
|
||||
/* json jClient = json::array();
|
||||
if (clientId != "")
|
||||
{
|
||||
ClientInfoPtr client = getClientInfo(clientId);
|
||||
|
@ -147,7 +162,7 @@ json Config::getServerStatus(const std::string& clientId, const json& streams) c
|
|||
}
|
||||
else
|
||||
jClient = getClientInfos();
|
||||
|
||||
*/
|
||||
Host host;
|
||||
host.update();
|
||||
//TODO: Set MAC and IP
|
||||
|
@ -157,7 +172,7 @@ json Config::getServerStatus(const std::string& clientId, const json& streams) c
|
|||
{"host", host.toJson()},//getHostName()},
|
||||
{"snapserver", snapserver.toJson()}
|
||||
}},
|
||||
{"clients", jClient},
|
||||
{"groups", getGroups()},
|
||||
{"streams", streams}
|
||||
};
|
||||
|
||||
|
@ -165,14 +180,14 @@ json Config::getServerStatus(const std::string& clientId, const json& streams) c
|
|||
}
|
||||
|
||||
|
||||
json Config::getClientInfos() const
|
||||
/*json Config::getClientInfos() const
|
||||
{
|
||||
json result = json::array();
|
||||
for (auto client: clients)
|
||||
result.push_back(client->toJson());
|
||||
return result;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
json Config::getGroups() const
|
||||
{
|
||||
|
@ -186,9 +201,9 @@ json Config::getGroups() const
|
|||
void Config::remove(ClientInfoPtr client)
|
||||
{
|
||||
auto group = getGroup(client);
|
||||
if (group->clients.size() == 1)
|
||||
groups.erase(std::remove(groups.begin(), groups.end(), group), groups.end());
|
||||
|
||||
auto clients = group->clients;
|
||||
clients.erase(std::remove(clients.begin(), clients.end(), client), clients.end());
|
||||
if (group->clients.empty())
|
||||
groups.erase(std::remove(groups.begin(), groups.end(), group), groups.end());
|
||||
}
|
||||
|
||||
|
|
|
@ -257,8 +257,11 @@ struct ClientInfo
|
|||
|
||||
struct Group
|
||||
{
|
||||
Group()
|
||||
Group(const ClientInfoPtr client = nullptr)
|
||||
{
|
||||
if (client)
|
||||
id = client->id;
|
||||
id = generateUUID();
|
||||
}
|
||||
|
||||
void fromJson(const json& j)
|
||||
|
@ -314,15 +317,16 @@ public:
|
|||
void remove(ClientInfoPtr client);
|
||||
|
||||
GroupPtr getGroup(ClientInfoPtr client);
|
||||
GroupPtr getGroup(const std::string& groupId) const;
|
||||
|
||||
json getClientInfos() const;
|
||||
// json getClientInfos() const;
|
||||
json getGroups() const;
|
||||
json getServerStatus(const std::string& clientId, const json& streams) const;
|
||||
json getServerStatus(const json& streams) const;
|
||||
|
||||
void save();
|
||||
|
||||
std::vector<GroupPtr> groups;
|
||||
std::vector<ClientInfoPtr> clients;
|
||||
// std::vector<ClientInfoPtr> clients;
|
||||
|
||||
private:
|
||||
Config();
|
||||
|
|
|
@ -115,9 +115,17 @@ void StreamServer::onMessageReceived(ControlSession* controlSession, const std::
|
|||
|
||||
json response;
|
||||
ClientInfoPtr clientInfo = nullptr;
|
||||
GroupPtr group = nullptr;
|
||||
msg::ServerSettings serverSettings;
|
||||
serverSettings.setBufferMs(settings_.bufferMs);
|
||||
|
||||
if (request.method.find("Group.Set") == 0)
|
||||
{
|
||||
group = Config::instance().getGroup(request.getParam("group").get<string>());
|
||||
if (group == nullptr)
|
||||
throw JsonInternalErrorException("Group not found", request.id);
|
||||
}
|
||||
|
||||
if (request.method.find("Client.Set") == 0)
|
||||
{
|
||||
clientInfo = Config::instance().getClientInfo(request.getParam("client").get<string>());
|
||||
|
@ -127,8 +135,9 @@ void StreamServer::onMessageReceived(ControlSession* controlSession, const std::
|
|||
|
||||
if (request.method == "Server.GetStatus")
|
||||
{
|
||||
/// TODO: rpc
|
||||
string clientId = request.hasParam("client") ? request.getParam("client").get<string>() : "";
|
||||
response = Config::instance().getServerStatus(clientId, streamManager_->toJson());
|
||||
response = Config::instance().getServerStatus(/*clientId,*/ streamManager_->toJson());
|
||||
// logO << response.dump(4);
|
||||
}
|
||||
else if (request.method == "Server.DeleteClient")
|
||||
|
@ -153,24 +162,25 @@ void StreamServer::onMessageReceived(ControlSession* controlSession, const std::
|
|||
clientInfo->config.volume.muted = request.getParam<bool>("mute", false, true);
|
||||
response = clientInfo->config.volume.muted;
|
||||
}
|
||||
else if (request.method == "Client.SetStream")
|
||||
else if (request.method == "Group.SetStream")
|
||||
{
|
||||
/* TODO: Group.SetStream
|
||||
string streamId = request.getParam("id").get<string>();
|
||||
PcmStreamPtr stream = streamManager_->getStream(streamId);
|
||||
if (stream == nullptr)
|
||||
throw JsonInternalErrorException("Stream not found", request.id);
|
||||
|
||||
clientInfo->config.streamId = streamId;
|
||||
response = clientInfo->config.streamId;
|
||||
group->streamId = streamId;
|
||||
response = group->streamId;
|
||||
|
||||
session_ptr session = getStreamSession(request.getParam("client").get<string>());
|
||||
if (session != nullptr)
|
||||
for (auto client: group->clients)
|
||||
{
|
||||
session->sendAsync(stream->getHeader());
|
||||
session->setPcmStream(stream);
|
||||
session_ptr session = getStreamSession(client->id);
|
||||
if (session != nullptr)
|
||||
{
|
||||
session->sendAsync(stream->getHeader());
|
||||
session->setPcmStream(stream);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
else if (request.method == "Client.SetLatency")
|
||||
{
|
||||
|
@ -247,7 +257,6 @@ void StreamServer::onMessageReceived(StreamSession* connection, const msg::BaseM
|
|||
logD << "request kServerSettings: " << connection->clientId << "\n";
|
||||
// std::lock_guard<std::mutex> mlock(mutex_);
|
||||
ClientInfoPtr client = Config::instance().addClientInfo(connection->clientId);
|
||||
|
||||
GroupPtr group = Config::instance().getGroup(client);
|
||||
|
||||
logD << "request kServerSettings\n";
|
||||
|
@ -289,6 +298,8 @@ void StreamServer::onMessageReceived(StreamSession* connection, const msg::BaseM
|
|||
json notification = JsonNotification::getJson("Client.OnConnect", client->toJson());
|
||||
// logO << notification.dump(4) << "\n";
|
||||
controlServer_->send(notification.dump());
|
||||
// cout << Config::instance().getServerStatus(streamManager_->toJson()).dump(4) << "\n";
|
||||
// cout << group->toJson().dump(4) << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue