summaryrefslogtreecommitdiff
path: root/vdrmanager/src/de/bjusystems
diff options
context:
space:
mode:
Diffstat (limited to 'vdrmanager/src/de/bjusystems')
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/app/VdrManagerApp.java134
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/data/AliveState.java36
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/data/Channel.java41
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/data/Epg.java65
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/data/EpgSearchParams.java43
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/data/EpgSearchTimeValue.java49
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/data/EpgSearchTimeValues.java62
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/data/Event.java21
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/data/EventFormatter.java43
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/data/EventListItem.java100
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/data/MenuActionHandler.java16
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/data/Preferences.java301
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/data/Timer.java186
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/data/WakeupState.java36
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/gui/ChannelAdapter.java75
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/gui/ChannelHolder.java9
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/gui/ChannelListActivity.java187
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/gui/EpgDetailsActivity.java91
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/gui/EpgListActivity.java408
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/gui/EpgSearchActivity.java63
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/gui/EpgSearchTimesListActivity.java130
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/gui/EventAdapter.java171
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/gui/EventListItemHolder.java12
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/gui/PreferencesActivity.java34
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/gui/SvdrpProgressDialog.java72
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/gui/TimerDetailsActivity.java232
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/gui/TimerListActivity.java238
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/gui/VdrManagerActivity.java228
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/gui/VideoActivity.java67
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/tasks/AsyncProgressTask.java55
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/tasks/DeleteTimerTask.java18
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/tasks/ToggleTimerTask.java25
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/utils/date/DateFormatter.java43
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/utils/http/HttpHelper.java263
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/AliveClient.java49
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/ChannelClient.java44
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/EpgClient.java91
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/SetTimerClient.java59
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/SvdrpAsyncListener.java7
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/SvdrpAsyncTask.java61
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/SvdrpClient.java271
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/SvdrpEvent.java17
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/SvdrpException.java22
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/SvdrpListener.java7
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/TimerClient.java50
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/WakeupClient.java51
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/utils/wakeup/AsyncWakeupTask.java84
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/utils/wakeup/WakeupProgress.java8
48 files changed, 4375 insertions, 0 deletions
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/app/VdrManagerApp.java b/vdrmanager/src/de/bjusystems/vdrmanager/app/VdrManagerApp.java
new file mode 100644
index 0000000..e60d396
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/app/VdrManagerApp.java
@@ -0,0 +1,134 @@
+package de.bjusystems.vdrmanager.app;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import android.app.Activity;
+import android.app.Application;
+import de.bjusystems.vdrmanager.data.Channel;
+import de.bjusystems.vdrmanager.data.Epg;
+import de.bjusystems.vdrmanager.data.EpgSearchParams;
+import de.bjusystems.vdrmanager.data.Timer;
+
+public class VdrManagerApp extends Application {
+
+ public enum EpgListState {
+ EPG_TIME,
+ EPG_CHANNEL,
+ EPG_SEARCH
+ }
+
+ private EpgListState epgListState;
+ private Epg currentEvent;
+ private Timer currentTimer;
+ private Channel currentChannel;
+ private List<Channel> channels;
+ private EpgSearchParams currentSearch;
+ private Class<? extends Activity> nextActivity;
+ private final List<Activity> activitiesToFinish = new ArrayList<Activity>();
+ private boolean reload;
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ }
+
+ public void clear() {
+ this.currentEvent = null;
+ this.currentTimer = null;
+ this.currentChannel = null;
+ this.currentSearch = null;
+
+ this.epgListState = EpgListState.EPG_TIME;
+ }
+
+ public Epg getCurrentEvent() {
+ return currentEvent;
+ }
+
+ public void setCurrentEvent(final Epg currentEvent) {
+ clear();
+ this.currentEvent = currentEvent;
+ if (currentEvent.getTimer() != null) {
+ this.currentTimer = currentEvent.getTimer();
+ } else {
+ this.currentTimer = new Timer(currentEvent);
+ }
+ }
+
+ public Timer getCurrentTimer() {
+ return currentTimer;
+ }
+
+ public void setCurrentTimer(final Timer currentTimer) {
+ clear();
+ this.currentTimer = currentTimer;
+ }
+
+ public Channel getCurrentChannel() {
+ return currentChannel;
+ }
+
+ public void setCurrentChannel(final Channel currentChannel) {
+ clear();
+ this.currentChannel = currentChannel;
+ this.epgListState = EpgListState.EPG_CHANNEL;
+ }
+
+ public List<Channel> getChannels() {
+ return channels;
+ }
+
+ public void setChannels(final List<Channel> channels) {
+ this.channels = channels;
+ }
+
+ public EpgSearchParams getCurrentSearch() {
+ return currentSearch;
+ }
+
+ public void setCurrentSearch(final EpgSearchParams currentSearch) {
+ clear();
+ this.currentSearch = currentSearch;
+ this.epgListState = EpgListState.EPG_SEARCH;
+ }
+
+ public EpgListState getEpgListState() {
+ return epgListState;
+ }
+
+ public Class<? extends Activity> getNextActivity() {
+ return nextActivity;
+ }
+
+ public void setNextActivity(final Class<? extends Activity> nextActivity) {
+ this.nextActivity = nextActivity;
+ }
+
+ public List<Activity> getActivitiesToFinish() {
+ return activitiesToFinish;
+ }
+
+ public void clearActivitiesToFinish() {
+ activitiesToFinish.clear();
+ }
+
+ public void addActivityToFinish(final Activity activityToFinish) {
+ activitiesToFinish.add(activityToFinish);
+ }
+
+ public void finishActivities() {
+ for(final Activity activity : activitiesToFinish) {
+ activity.finish();
+ }
+ activitiesToFinish.clear();
+ }
+
+ public boolean isReload() {
+ return reload;
+ }
+
+ public void setReload(final boolean reload) {
+ this.reload = reload;
+ }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/data/AliveState.java b/vdrmanager/src/de/bjusystems/vdrmanager/data/AliveState.java
new file mode 100644
index 0000000..cf96efa
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/data/AliveState.java
@@ -0,0 +1,36 @@
+package de.bjusystems.vdrmanager.data;
+
+public class AliveState {
+
+ public static AliveState ALIVE = new AliveState(0);
+ public static AliveState DEAD = new AliveState(1);
+ public static AliveState UNKNOWN = new AliveState(2);
+
+ private final int value;
+ private static AliveState state;
+
+ private AliveState(final int value) {
+ this.value = value;
+ }
+
+ public static AliveState getState() {
+ return state;
+ }
+
+ public static void setState(final AliveState state) {
+ AliveState.state = state;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (!(o instanceof AliveState)) {
+ return false;
+ }
+ return this.value == ((AliveState)o).value;
+ }
+
+ @Override
+ public int hashCode() {
+ return Integer.valueOf(value).hashCode();
+ }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/data/Channel.java b/vdrmanager/src/de/bjusystems/vdrmanager/data/Channel.java
new file mode 100644
index 0000000..bb9e0a7
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/data/Channel.java
@@ -0,0 +1,41 @@
+package de.bjusystems.vdrmanager.data;
+
+
+public class Channel {
+
+ private final int number;
+ private final String name;
+
+ public Channel(final String channelData) {
+
+ final String[] words = channelData.split(":");
+ this.number = Integer.valueOf(words[0].substring(1));
+ this.name = words[1];
+ }
+
+ public Channel() {
+ this.number = 0;
+ this.name = "Unknown";
+ }
+
+ public boolean isGroupSeparator() {
+ return number == 0;
+ }
+
+ public int getNumber() {
+ return number;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder text = new StringBuilder();
+ text.append(number);
+ text.append(" - ");
+ text.append(name);
+ return text.toString();
+ }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/data/Epg.java b/vdrmanager/src/de/bjusystems/vdrmanager/data/Epg.java
new file mode 100644
index 0000000..e228565
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/data/Epg.java
@@ -0,0 +1,65 @@
+package de.bjusystems.vdrmanager.data;
+
+import java.util.Date;
+
+/**
+ * Class for EPG events
+ * @author bju
+ */
+public class Epg implements Event {
+
+ private final String channelNumber;
+ private final String channelName;
+ private final String title;
+ private final String description;
+ private final Date start;
+ private final Date stop;
+ private Timer timer;
+
+ public Epg(final String line) {
+
+ final String[] words = line.split(":");
+
+ channelNumber = words[0].substring(1);
+ channelName = words[1];
+ start = new Date(Long.parseLong(words[2])*1000);
+ stop = new Date(Long.parseLong(words[3])*1000);
+ title = words[4];
+ description = words.length > 5 ? words[5] : "";
+ }
+
+ public String getChannelNumber() {
+ return channelNumber;
+ }
+ public String getChannelName() {
+ return channelName;
+ }
+ public String getTitle() {
+ return title;
+ }
+ public String getDescription() {
+ return description;
+ }
+ public Date getStart() {
+ return start;
+ }
+ public Date getStop() {
+ return stop;
+ }
+
+ public Timer getTimer() {
+ return timer;
+ }
+
+ public void setTimer(final Timer timer) {
+ this.timer = timer;
+ }
+
+ public TimerState getTimerState() {
+ if (timer == null) {
+ return TimerState.None;
+ } else {
+ return timer.getTimerState();
+ }
+ }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/data/EpgSearchParams.java b/vdrmanager/src/de/bjusystems/vdrmanager/data/EpgSearchParams.java
new file mode 100644
index 0000000..62ca4e2
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/data/EpgSearchParams.java
@@ -0,0 +1,43 @@
+package de.bjusystems.vdrmanager.data;
+
+import java.util.Date;
+
+/**
+ * Class for EPG events
+ * @author bju
+ */
+public class EpgSearchParams {
+
+ private String channelNumber;
+ private String title;
+ private Date start;
+ private Date end;
+
+ public String getChannelNumber() {
+ return channelNumber;
+ }
+ public void setChannelNumber(final String channelNumber) {
+ this.channelNumber = channelNumber;
+ }
+ public String getTitle() {
+ return title;
+ }
+ public void setTitle(final String title) {
+ this.title = title;
+ }
+ public Date getStart() {
+ return start;
+ }
+ public void setStart(final Date start) {
+ this.start = start;
+ }
+ public Date getEnd() {
+ return end;
+ }
+ public void setEnd(final Date end) {
+ this.end = end;
+ }
+ public String toCommandLine() {
+ return title;
+ }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/data/EpgSearchTimeValue.java b/vdrmanager/src/de/bjusystems/vdrmanager/data/EpgSearchTimeValue.java
new file mode 100644
index 0000000..281b020
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/data/EpgSearchTimeValue.java
@@ -0,0 +1,49 @@
+package de.bjusystems.vdrmanager.data;
+
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+
+public class EpgSearchTimeValue {
+
+ private final int index;
+ private final String text;
+
+ public EpgSearchTimeValue(final int index, final String text) {
+ this.index = index;
+ this.text = text;
+ }
+
+ public EpgSearchTimeValue() {
+ this.index = 0;
+ this.text = "";
+ }
+
+ public String getValue() {
+ switch (index) {
+ case 0:
+ return "now";
+ case 1:
+ return "next";
+ default:
+ final String[] values = text.split(":");
+ final Calendar cal = new GregorianCalendar();
+ cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(values[0]));
+ cal.set(Calendar.MINUTE, Integer.parseInt(values[1]));
+ cal.set(Calendar.SECOND, 0);
+ cal.set(Calendar.MILLISECOND, 0);
+
+ // next day?
+ final Calendar now = new GregorianCalendar();
+ if (now.after(cal)) {
+ cal.add(Calendar.DAY_OF_MONTH, 1);
+ }
+
+ return String.format("%d", cal.getTimeInMillis() / 1000);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return text;
+ }
+} \ No newline at end of file
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/data/EpgSearchTimeValues.java b/vdrmanager/src/de/bjusystems/vdrmanager/data/EpgSearchTimeValues.java
new file mode 100644
index 0000000..6fba7ba
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/data/EpgSearchTimeValues.java
@@ -0,0 +1,62 @@
+package de.bjusystems.vdrmanager.data;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import android.content.Context;
+import de.bjusystems.vdrmanager.R;
+
+public class EpgSearchTimeValues {
+
+ private final List<EpgSearchTimeValue> values = new ArrayList<EpgSearchTimeValue>();
+ private final Context context;
+
+ public EpgSearchTimeValues(final Context context) {
+
+ this.context = context;
+ }
+
+ public List<EpgSearchTimeValue> getValues() {
+
+ final Preferences prefs = Preferences.getPreferences();
+
+ // fixed values for now and next
+ values.add(new EpgSearchTimeValue(0, context.getString(R.string.epg_list_time_now)));
+ values.add(new EpgSearchTimeValue(1, context.getString(R.string.epg_list_time_next)));
+
+ // get user defined values
+ final String userValueString = prefs.getEpgSearchTimes();
+
+ final String[] userValues = userValueString.split(",");
+
+ Arrays.sort(userValues);
+
+ for(final String userValue : userValues) {
+ if (userValue.contains(":")) {
+ values.add(new EpgSearchTimeValue(values.size(), userValue));
+ }
+ }
+
+ return values;
+ }
+
+ public void saveValues(final List<EpgSearchTimeValue> values) {
+
+ // get old values
+ final Preferences prefs = Preferences.getPreferences();
+
+ // add value
+ String newValues = "";
+ for(int i = 2; i < values.size(); i++) {
+ final EpgSearchTimeValue value = values.get(i);
+ if (newValues.length() > 0) {
+ newValues += ",";
+ }
+ newValues += value.toString();
+ }
+
+ // save new values
+ prefs.setEpgSearchTimes(context, newValues);
+ }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/data/Event.java b/vdrmanager/src/de/bjusystems/vdrmanager/data/Event.java
new file mode 100644
index 0000000..6fa192d
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/data/Event.java
@@ -0,0 +1,21 @@
+package de.bjusystems.vdrmanager.data;
+
+import java.util.Date;
+
+public interface Event {
+
+ public enum TimerState {
+ None,
+ Active,
+ Inactive,
+ Recording
+ }
+
+ String getChannelNumber();
+ String getChannelName();
+ String getTitle();
+ String getDescription();
+ Date getStart();
+ Date getStop();
+ TimerState getTimerState();
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/data/EventFormatter.java b/vdrmanager/src/de/bjusystems/vdrmanager/data/EventFormatter.java
new file mode 100644
index 0000000..430bca4
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/data/EventFormatter.java
@@ -0,0 +1,43 @@
+package de.bjusystems.vdrmanager.data;
+
+import de.bjusystems.vdrmanager.utils.date.DateFormatter;
+
+public class EventFormatter {
+
+ private String time;
+ private final String date;
+ private final String longDate;
+ private final String title;
+ private final String description;
+
+ public EventFormatter(final Event event) {
+ DateFormatter formatter = new DateFormatter(event.getStart());
+ this.date = formatter.getDateString();
+ this.longDate = formatter.getDailyHeader();
+ this.time = formatter.getTimeString();
+ formatter = new DateFormatter(event.getStop());
+ this.time += " - " + formatter.getTimeString();
+ this.title = event.getTitle().replace("|##", ":").replace("||#", "\n");
+ this.description = event.getDescription().replace("|##", ":").replace("||#", "\n");
+ }
+
+ public String getTime() {
+ return time;
+ }
+
+ public String getDate() {
+ return date;
+ }
+
+ public String getLongDate() {
+ return longDate;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/data/EventListItem.java b/vdrmanager/src/de/bjusystems/vdrmanager/data/EventListItem.java
new file mode 100644
index 0000000..b9370a1
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/data/EventListItem.java
@@ -0,0 +1,100 @@
+package de.bjusystems.vdrmanager.data;
+
+import java.util.Date;
+
+
+public class EventListItem implements Event {
+
+ private final Timer timer;
+ private final Epg epg;
+ private final String header;
+ private final Event event;
+
+ public EventListItem(final Timer timer) {
+ this.header = null;
+ this.timer = timer;
+ this.epg = null;
+ this.event = timer;
+ }
+
+ public EventListItem(final Epg epg) {
+ this.header = null;
+ this.timer = null;
+ this.epg = epg;
+ this.event = epg;
+ }
+
+ public EventListItem(final String header) {
+ this.header = header;
+ this.timer = null;
+ this.epg = null;
+ this.event = null;
+ }
+
+ public boolean isHeader() {
+ return header != null;
+ }
+
+ public boolean isTimer() {
+ return timer != null;
+ }
+
+ public Date getStart() {
+ return event != null ? event.getStart() : null;
+ }
+
+ public Date getStop() {
+ return event != null ? event.getStop() : null;
+ }
+
+ public String getChannelNumber() {
+ return event != null ? event.getChannelNumber() : null;
+ }
+
+ public String getChannelName() {
+ return event != null ? event.getChannelName() : null;
+ }
+
+ public String getTitle() {
+ return event != null ? event.getTitle() : null;
+ }
+
+ public String getDescription() {
+ return event != null ? event.getDescription() : null;
+ }
+
+ public String getHeader() {
+ return header;
+ }
+
+ public TimerState getTimerState() {
+ return event != null ? event.getTimerState() : TimerState.None;
+ }
+
+ public Timer getTimer() {
+ return timer;
+ }
+
+ public Epg getEpg() {
+ return epg;
+ }
+
+ public Event getEvent() {
+ return event;
+ }
+
+ @Override
+ public String toString() {
+ if (isHeader()) {
+ return "Header: " + header;
+ }
+
+ final EventFormatter formatter = new EventFormatter(event);
+ final StringBuilder text = new StringBuilder();
+ text.append(isTimer() ? "Timer: " : "Event: ");
+ text.append("Channel: ").append(event.getChannelNumber());
+ text.append(" (").append(event.getChannelName()).append("), ");
+ text.append("Zeit: ").append(formatter.getDate()).append(" ").append(formatter.getTime());
+ return text.toString();
+ }
+} \ No newline at end of file
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/data/MenuActionHandler.java b/vdrmanager/src/de/bjusystems/vdrmanager/data/MenuActionHandler.java
new file mode 100644
index 0000000..b1f1d2e
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/data/MenuActionHandler.java
@@ -0,0 +1,16 @@
+package de.bjusystems.vdrmanager.data;
+
+import android.content.Context;
+
+
+/**
+ * Handler for menu actions
+ * @author bju
+ */
+public interface MenuActionHandler {
+
+ /**
+ * Execute the action
+ */
+ void executeAction(Context context);
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/data/Preferences.java b/vdrmanager/src/de/bjusystems/vdrmanager/data/Preferences.java
new file mode 100644
index 0000000..3e1fc8a
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/data/Preferences.java
@@ -0,0 +1,301 @@
+package de.bjusystems.vdrmanager.data;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import de.bjusystems.vdrmanager.R;
+
+/**
+ * Class for all preferences
+ * @author bju
+ */
+public class Preferences {
+
+ private boolean ssl;
+ /** SVDRP host name or ip */
+ private String svdrpHost;
+ /** SVDRP port */
+ private int svdrpPort;
+ /** Password */
+ private String password;
+ /** should channels be filtered? */
+ private boolean filterChannels;
+ /** last channel to retrieve */
+ private String channels;
+ /** Enable remote wakeup */
+ private boolean wakeupEnabled;
+ /** URL of the wakeup script */
+ private String wakeupUrl;
+ /** User for wakeup */
+ private String wakeupUser;
+ /** Password for wakeup */
+ private String wakeupPassword;
+ /** Check for running VDR is enabled */
+ private boolean aliveCheckEnabled;
+ /** Intervall for alive test */
+ private int aliveCheckInterval;
+ /** Buffer before event */
+ private int timerPreMargin;
+ /** Buffer after event */
+ private int timerPostMargin;
+ /** Default priority */
+ private int timerDefaultPriority;
+ /** Default lifetime */
+ private int timerDefaultLifetime;
+ /** user defined epg search times */
+ private String epgSearchTimes;
+
+ /** Properties singleton */
+ private static Preferences thePrefs;
+
+ /**
+ * Checks for connect using SSL
+ * @return true, if use SSL connections
+ */
+ public boolean isSSL() {
+ return ssl;
+ }
+
+ /**
+ * Retrieves the channel filtering mode
+ * @return true, if channels will be filtered
+ */
+ public boolean isFilterChannels() {
+ return filterChannels;
+ }
+
+ /**
+ * Last channel to receive
+ * @return channel number
+ */
+ public String getChannels() {
+ return filterChannels ? channels : "";
+ }
+
+ /**
+ * Gets the SVDRP host or IP address
+ * @return SVDRP host
+ */
+ public String getSvdrpHost() {
+ return svdrpHost;
+ }
+
+ /**
+ * Gets the SVDRP port
+ * @return SVDRP port
+ */
+ public int getSvdrpPort() {
+ return svdrpPort;
+ }
+
+ /**
+ * Gets the SVDRP password
+ * @return SVDRO password
+ */
+ public String getPassword() {
+ return password;
+ }
+
+ /**
+ * Checks for enables remote wakeup
+ * @return true, if remote wakeup is enabled
+ */
+ public boolean isWakeupEnabled() {
+ return wakeupEnabled;
+ }
+
+ /**
+ * Gets the URL for the wakeup request
+ * @return wakeup url
+ */
+ public String getWakeupUrl() {
+ return wakeupUrl;
+ }
+
+ /**
+ * Gets the user for the wakeup url
+ * @return user name
+ */
+ public String getWakeupUser() {
+ return wakeupUser;
+ }
+
+ /**
+ * Gets the password for the wakeup url
+ * @return password
+ */
+ public String getWakeupPassword() {
+ return wakeupPassword;
+ }
+
+ /**
+ * Checks for enabled alive check
+ * @return true, if enabled
+ */
+ public boolean isAliveCheckEnabled() {
+ return aliveCheckEnabled;
+ }
+
+ /**
+ * Gets the time between alive checks
+ * @return time in seconds
+ */
+ public int getAliveCheckInterval() {
+ return aliveCheckInterval;
+ }
+
+ /**
+ * Gets the buffer before the event start
+ * @return pre event buffer
+ */
+ public int getTimerPreMargin() {
+ return timerPreMargin;
+ }
+
+ /**
+ * Gets the buffer after the event stop
+ * @return post event buffer
+ */
+ public int getTimerPostMargin() {
+ return timerPostMargin;
+ }
+
+ /**
+ * Gets the default priority
+ * @return default priority
+ */
+ public int getTimerDefaultPriority() {
+ return timerDefaultPriority;
+ }
+
+ /**
+ * Gets the default lifetime
+ * @return default lifetime
+ */
+ public int getTimerDefaultLifetime() {
+ return timerDefaultLifetime;
+ }
+
+ /**
+ * Gets the time values for the epg search
+ * @return
+ */
+ public String getEpgSearchTimes() {
+ return epgSearchTimes;
+ }
+
+ /**
+ * Sets the time values for the epg search
+ * @param epgSearchTimes new time values
+ */
+ public void setEpgSearchTimes(final Context context, final String epgSearchTimes) {
+
+ final SharedPreferences prefs = getSharedPreferences(context);
+ final SharedPreferences.Editor editor = prefs.edit();
+ editor.putString(context.getString(R.string.epg_search_times_key), epgSearchTimes);
+ editor.commit();
+
+ // reload
+ loadPreferences(context);
+ }
+
+ /**
+ * Gets the name for the file which preferences will be saved into
+ * @param context Context
+ * @return filename
+ */
+ public static String getPreferenceFile(final Context context) {
+ return context.getString(R.string.app_name);
+ }
+
+ /**
+ * Gets the previous loaded preferences
+ * @return preferences
+ */
+ public static Preferences getPreferences() {
+ return thePrefs;
+ }
+
+ /**
+ * Loads all preferences
+ * @param context Context
+ * @return Preferences
+ */
+ public static void loadPreferences(final Context context) {
+
+ final SharedPreferences sharedPrefs = getSharedPreferences(context);
+
+ final Preferences prefs = new Preferences();
+
+ prefs.svdrpHost = getString(context, sharedPrefs, R.string.vdr_host_key, "10.0.2.2");
+ prefs.svdrpPort = getInt(context, sharedPrefs, R.string.vdr_port_key, 6419);
+ prefs.password = getString(context, sharedPrefs, R.string.vdr_password_key, "");
+ prefs.ssl = getBoolean(context, sharedPrefs, R.string.vdr_ssl_key, false);
+
+ prefs.aliveCheckEnabled = getBoolean(context, sharedPrefs, R.string.alive_check_enabled_key, false);
+ prefs.aliveCheckInterval = getInt(context, sharedPrefs, R.string.alive_check_interval_key, 60);
+
+ prefs.channels = getString(context, sharedPrefs, R.string.channel_filter_last_key, "").replace(" ", "");
+ prefs.filterChannels = getBoolean(context, sharedPrefs, R.string.channel_filter_filter_key, false);
+
+ prefs.wakeupEnabled = getBoolean(context, sharedPrefs, R.string.wakeup_enabled_key, false);
+ prefs.wakeupUrl = getString(context, sharedPrefs, R.string.wakeup_url_key, "");
+ prefs.wakeupUser = getString(context, sharedPrefs, R.string.wakeup_user_key, "");
+ prefs.wakeupPassword = getString(context, sharedPrefs, R.string.wakeup_password_key, "");
+
+ prefs.timerPreMargin = getInt(context, sharedPrefs, R.string.timer_pre_start_buffer_key, 5);
+ prefs.timerPostMargin = getInt(context, sharedPrefs, R.string.timer_post_end_buffer_key, 30);
+ prefs.timerDefaultPriority = getInt(context, sharedPrefs, R.string.timer_default_priority_key, 99);
+ prefs.timerDefaultLifetime = getInt(context, sharedPrefs, R.string.timer_default_lifetime_key, 99);
+
+ prefs.epgSearchTimes = getString(context, sharedPrefs, R.string.epg_search_times_key, "");
+
+ thePrefs = prefs;
+ }
+
+ /**
+ * Gets the persistent preferences
+ * @param context Context
+ * @return preferences
+ */
+ private static SharedPreferences getSharedPreferences(final Context context) {
+
+ return context.getSharedPreferences(getPreferenceFile(context), Context.MODE_PRIVATE);
+ }
+
+ /**
+ * Helper for retrieving integer values from preferences
+ * @param context Context
+ * @param sharedPrefs Object for the preference file
+ * @param resId ressource id of the preferences name
+ * @param defValue default value
+ * @return value or the default value if not defined
+ */
+ private static int getInt(final Context context, final SharedPreferences sharedPrefs, final int resId, final int defValue) {
+ final String value = getString(context, sharedPrefs, resId, String.valueOf(defValue));
+ return Integer.parseInt(value);
+ }
+
+ /**
+ * Helper for retrieving boolean values from preferences
+ * @param context Context
+ * @param sharedPrefs Object for the preference file
+ * @param resId ressource id of the preferences name
+ * @param defValue default value
+ * @return value or the default value if not defined
+ */
+ private static boolean getBoolean(final Context context, final SharedPreferences sharedPrefs, final int resId, final boolean defValue) {
+ return sharedPrefs.getBoolean(context.getString(resId), defValue);
+ }
+
+ /**
+ * Helper for retrieving string values from preferences
+ * @param context Context
+ * @param sharedPrefs Object for the preference file
+ * @param resId ressource id of the preferences name
+ * @param defValue default value
+ * @return value or the default value if not defined
+ */
+ private static String getString(final Context context, final SharedPreferences sharedPrefs, final int resId, final String defValue) {
+ return sharedPrefs.getString(context.getString(resId), defValue);
+ }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/data/Timer.java b/vdrmanager/src/de/bjusystems/vdrmanager/data/Timer.java
new file mode 100644
index 0000000..8ce34d5
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/data/Timer.java
@@ -0,0 +1,186 @@
+package de.bjusystems.vdrmanager.data;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+
+/**
+ * Class for timer data
+ * @author bju
+ */
+public class Timer implements Event {
+
+ private static final int ENABLED = 1;
+ private static final int INSTANT = 2;
+ private static final int VPS = 4;
+ private static final int RECORDING = 8;
+
+ private final int number;
+ private int flags;
+ private String title;
+ private String description;
+ private Date start;
+ private Date stop;
+ private final String channelNumber;
+ private final String channelName;
+ private final int priority;
+ private final int lifetime;
+
+
+ /**
+ * Constructs a timer from SvdrpHelper result line
+ * @param timerData result line
+ * @param channels list of channels
+ */
+ public Timer(final String timerData) {
+
+ final String[] values = timerData.split(":");
+
+ // number
+ this.number = Integer.valueOf(values[0].substring(1));
+
+ // flags, channel number and channel name
+ this.flags = Integer.valueOf(values[1]);
+ this.channelNumber = values[2];
+ this.channelName = values[3];
+
+ // get start and stop
+ this.start = new Date(Long.parseLong(values[4]) * 1000);
+ this.stop = new Date(Long.parseLong(values[5]) * 1000);
+
+ // priority and lifetime
+ this.priority = Integer.valueOf(values[6]);
+ this.lifetime = Integer.valueOf(values[7]);
+
+ // title and description
+ this.title = values[8];
+ this.description = values.length > 9 ? values[9] : "";
+ }
+
+ public Timer(final Epg event) {
+
+ final Preferences prefs = Preferences.getPreferences();
+
+ this.number = 0;
+ this.flags = ENABLED;
+ this.channelNumber = event.getChannelNumber();
+ this.channelName = event.getChannelName();
+ this.priority = prefs.getTimerDefaultPriority();
+ this.lifetime = prefs.getTimerDefaultLifetime();
+
+ this.start = new Date(event.getStart().getTime() - prefs.getTimerPreMargin() * 60000);
+ this.stop = new Date(event.getStop().getTime() + prefs.getTimerPostMargin() * 60000);
+
+ this.title = event.getTitle();
+ this.description = event.getDescription();
+ }
+
+ public String toCommandLine() {
+
+ final StringBuilder line = new StringBuilder();
+
+ line.append(number).append(":");
+ line.append(flags).append(":");
+ line.append(channelNumber).append(":");
+
+ final Calendar cal = new GregorianCalendar();
+ cal.setTime(start);
+ line.append(String.format("%04d-%02d-%02d:", cal.get(Calendar.YEAR), cal.get(Calendar.MONTH)+1, cal.get(Calendar.DAY_OF_MONTH)));
+ line.append(String.format("%02d%02d:", cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE)));
+
+ cal.setTime(stop);
+ line.append(String.format("%02d%02d:", cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE)));
+
+ line.append(priority).append(":");
+ line.append(lifetime).append(":");
+ line.append(title).append(":");
+ line.append(description);
+
+ return line.toString();
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(final String description) {
+ this.description = description;
+ }
+
+ public int getNumber() {
+ return number;
+ }
+
+ public Date getStart() {
+ return start;
+ }
+
+ public Date getStop() {
+ return stop;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(final String title) {
+ this.title = title;
+ }
+
+ public String getChannelNumber() {
+ return channelNumber;
+ }
+
+ public String getChannelName() {
+ return channelName;
+ }
+
+ public int getPriority() {
+ return priority;
+ }
+
+ public int getLifetime() {
+ return lifetime;
+ }
+
+ public TimerState getTimerState() {
+ if (isEnabled()) {
+ if (isRecording()) {
+ return TimerState.Recording;
+ }
+ return TimerState.Active;
+ }
+ return TimerState.Inactive;
+ }
+
+ public boolean isEnabled() {
+ return (flags & ENABLED) == ENABLED;
+ }
+
+ public boolean isInstant() {
+ return (flags & INSTANT) == INSTANT;
+ }
+
+ public boolean isVps() {
+ return (flags & VPS) == VPS;
+ }
+ public boolean isRecording() {
+ return (flags & RECORDING) == RECORDING;
+ }
+
+ public void setStart(final Date start) {
+ this.start = start;
+ }
+
+ public void setStop(final Date stop) {
+ this.stop = stop;
+ }
+
+ public void setEnabled(final boolean enabled) {
+ if (enabled) {
+ flags = flags | ENABLED;
+ } else {
+ flags = flags & ~ENABLED;
+ }
+ }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/data/WakeupState.java b/vdrmanager/src/de/bjusystems/vdrmanager/data/WakeupState.java
new file mode 100644
index 0000000..f7917d8
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/data/WakeupState.java
@@ -0,0 +1,36 @@
+package de.bjusystems.vdrmanager.data;
+
+public class WakeupState {
+
+ public static WakeupState OK = new WakeupState(0);
+ public static WakeupState FAILED = new WakeupState(1);
+ public static WakeupState ERROR = new WakeupState(2);
+
+ private final int value;
+ private static WakeupState state;
+
+ private WakeupState(final int value) {
+ this.value = value;
+ }
+
+ public static WakeupState getState() {
+ return state;
+ }
+
+ public static void setState(final WakeupState state) {
+ WakeupState.state = state;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (!(o instanceof WakeupState)) {
+ return false;
+ }
+ return this.value == ((WakeupState)o).value;
+ }
+
+ @Override
+ public int hashCode() {
+ return Integer.valueOf(value).hashCode();
+ }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/gui/ChannelAdapter.java b/vdrmanager/src/de/bjusystems/vdrmanager/gui/ChannelAdapter.java
new file mode 100644
index 0000000..c609813
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/gui/ChannelAdapter.java
@@ -0,0 +1,75 @@
+package de.bjusystems.vdrmanager.gui;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import android.content.Context;
+import android.graphics.Color;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import android.widget.TextView;
+import de.bjusystems.vdrmanager.R;
+import de.bjusystems.vdrmanager.data.Channel;
+
+class ChannelAdapter extends ArrayAdapter<Channel> {
+
+ private final LayoutInflater inflater;
+ private final List<Channel> items;
+
+ public ChannelAdapter(final Context context) {
+ super(context, R.layout.channel_item);
+ inflater = LayoutInflater.from(context);
+ items = new ArrayList<Channel>();
+ }
+
+ @Override
+ public View getView(final int position, final View convertView, final ViewGroup parent) {
+
+ ChannelHolder itemHolder = new ChannelHolder();
+
+ // recycle view?
+ View view = convertView;
+ if (view == null) {
+ view = inflater.inflate(R.layout.channel_item, null);
+ itemHolder = new ChannelHolder();
+
+ itemHolder.name = (TextView) view.findViewById(R.id.channel_name);
+ itemHolder.type = (ImageView) view.findViewById(R.id.channel_type);
+
+ view.setTag(itemHolder);
+ } else {
+ itemHolder = (ChannelHolder) view.getTag();
+ }
+
+ // get item
+ final Channel item = getItem(position);
+
+ // fill item
+ if (item.isGroupSeparator()) {
+ view.setPadding(view.getPaddingLeft(), 0, view.getPaddingRight(), 0);
+ view.setBackgroundColor(Color.DKGRAY);
+ itemHolder.type.setVisibility(View.GONE);
+ itemHolder.name.setVisibility(View.VISIBLE);
+ itemHolder.name.setText(item.getName());
+ itemHolder.name.setPadding(0, 0, 0, 0);
+ } else {
+ view.setBackgroundColor(Color.BLACK);
+ itemHolder.type.setVisibility(View.VISIBLE);
+ itemHolder.type.setVisibility(View.VISIBLE);
+ itemHolder.name.setText(item.toString());
+ }
+
+ return view;
+ }
+
+ public void addItem(final Channel channel) {
+ items.add(channel);
+ }
+
+ public void clearItems() {
+ items.clear();
+ }
+} \ No newline at end of file
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/gui/ChannelHolder.java b/vdrmanager/src/de/bjusystems/vdrmanager/gui/ChannelHolder.java
new file mode 100644
index 0000000..ef09410
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/gui/ChannelHolder.java
@@ -0,0 +1,9 @@
+package de.bjusystems.vdrmanager.gui;
+
+import android.widget.ImageView;
+import android.widget.TextView;
+
+class ChannelHolder {
+ public ImageView type;
+ public TextView name;
+} \ No newline at end of file
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/gui/ChannelListActivity.java b/vdrmanager/src/de/bjusystems/vdrmanager/gui/ChannelListActivity.java
new file mode 100644
index 0000000..ac12efd
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/gui/ChannelListActivity.java
@@ -0,0 +1,187 @@
+package de.bjusystems.vdrmanager.gui;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.ContextMenu;
+import android.view.ContextMenu.ContextMenuInfo;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.ListView;
+import de.bjusystems.vdrmanager.R;
+import de.bjusystems.vdrmanager.app.VdrManagerApp;
+import de.bjusystems.vdrmanager.data.Channel;
+import de.bjusystems.vdrmanager.data.Preferences;
+import de.bjusystems.vdrmanager.utils.svdrp.ChannelClient;
+import de.bjusystems.vdrmanager.utils.svdrp.SvdrpAsyncListener;
+import de.bjusystems.vdrmanager.utils.svdrp.SvdrpAsyncTask;
+import de.bjusystems.vdrmanager.utils.svdrp.SvdrpClient;
+import de.bjusystems.vdrmanager.utils.svdrp.SvdrpEvent;
+import de.bjusystems.vdrmanager.utils.svdrp.SvdrpException;
+
+/**
+ * This class is used for showing what's
+ * current running on all channels
+ * @author bju
+ */
+public class ChannelListActivity extends Activity
+ implements OnItemClickListener, SvdrpAsyncListener<Channel> {
+
+ ChannelClient channelClient;
+ ChannelAdapter adapter;
+ Preferences prefs;
+ List<Channel> channels;
+ SvdrpProgressDialog progress;
+
+ @Override
+ protected void onCreate(final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Attach view
+ setContentView(R.layout.channel_list);
+
+ // Create adapter for ListView
+ adapter = new ChannelAdapter(this);
+ final ListView listView = (ListView) findViewById(R.id.channel_list);
+ listView.setAdapter(adapter);
+ // register context menu
+ registerForContextMenu(listView);
+
+
+ // create channel list
+ channels = new ArrayList<Channel>();
+
+ listView.setOnItemClickListener(this);
+ }
+
+ public void onItemClick(final AdapterView<?> parent, final View view, final int position, final long id) {
+
+ // find and remember item
+ final Channel channel = (Channel) parent.getAdapter().getItem(position);
+ final VdrManagerApp app = (VdrManagerApp) getApplication();
+ app.setCurrentChannel(channel);
+ app.setChannels(channels);
+
+ // show details
+ final Intent intent = new Intent();
+ intent.setClass(this, EpgListActivity.class);
+ startActivity(intent);
+ }
+
+
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ startChannelQuery();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ if (channelClient != null) {
+ channelClient.abort();
+ }
+ if (progress != null) {
+ progress.dismiss();
+ progress = null;
+ }
+ }
+
+ private void startChannelQuery() {
+
+ // get channel task
+ channelClient = new ChannelClient();
+
+ // create background task
+ final SvdrpAsyncTask<Channel, SvdrpClient<Channel>> task = new SvdrpAsyncTask<Channel, SvdrpClient<Channel>>(channelClient);
+
+ // create progress
+ progress = new SvdrpProgressDialog(this, channelClient);
+
+ // attach listener
+ task.addListener(this);
+
+ // start task
+ task.run();
+ }
+
+ public void svdrpEvent(final SvdrpEvent event, final Channel result) {
+
+ if (progress != null) {
+ progress.svdrpEvent(event);
+ }
+
+ switch (event) {
+ case CONNECTING:
+ adapter.clear();
+ channels.clear();
+ break;
+ case LOGIN_ERROR:
+ this.finish();
+ break;
+ case FINISHED:
+ channels.addAll(channelClient.getResults());
+ for(final Channel channel : channels) {
+ adapter.add(channel);
+ }
+ progress = null;
+ }
+ }
+
+ public void svdrpException(final SvdrpException exception) {
+ if (progress != null) {
+ progress.svdrpException(exception);
+ }
+ }
+
+ @Override
+ public void onCreateContextMenu(final ContextMenu menu, final View v, final ContextMenuInfo menuInfo) {
+ super.onCreateContextMenu(menu, v, menuInfo);
+
+ if (v.getId() == R.id.channel_list) {
+ final MenuInflater inflater = getMenuInflater();
+ final AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)menuInfo;
+
+ // set menu title
+ final Channel item = adapter.getItem(info.position);
+ menu.setHeaderTitle(item.getName());
+
+ inflater.inflate(R.menu.channel_list_item_menu, menu);
+ }
+ }
+
+
+
+ @Override
+ public boolean onContextItemSelected(final MenuItem item) {
+
+ final AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)item.getMenuInfo();
+ final Channel channel = adapter.getItem(info.position);
+
+ switch (item.getItemId()) {
+ case R.id.channel_item_menu_epg:
+ onItemClick(null, null, info.position, 0);
+ break;
+ case R.id.channel_item_menu_stream:
+ // show live stream
+ showStream(channel);
+ break;
+ }
+
+ return true;
+ }
+
+ private void showStream(final Channel channel) {
+ // show stream
+ final Intent intent = new Intent();
+ intent.setClass(this, VideoActivity.class);
+ startActivity(intent);
+ }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/gui/EpgDetailsActivity.java b/vdrmanager/src/de/bjusystems/vdrmanager/gui/EpgDetailsActivity.java
new file mode 100644
index 0000000..7932e86
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/gui/EpgDetailsActivity.java
@@ -0,0 +1,91 @@
+package de.bjusystems.vdrmanager.gui;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.TypedValue;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.TextView;
+import de.bjusystems.vdrmanager.R;
+import de.bjusystems.vdrmanager.app.VdrManagerApp;
+import de.bjusystems.vdrmanager.data.Epg;
+import de.bjusystems.vdrmanager.data.EventFormatter;
+import de.bjusystems.vdrmanager.data.Preferences;
+
+/**
+ * This class is used for showing what's
+ * current running on all channels
+ * @author bju
+ */
+public class EpgDetailsActivity extends Activity
+ implements OnClickListener {
+
+ Preferences prefs;
+
+ @Override
+ protected void onCreate(final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Attach view
+ setContentView(R.layout.epg_detail);
+
+
+ // current event
+ final VdrManagerApp app = (VdrManagerApp) getApplication();
+ final Epg event = app.getCurrentEvent();
+ final EventFormatter formatter = new EventFormatter(event);
+
+ final TextView title = (TextView)findViewById(R.id.epg_detail_title);
+ title.setText(formatter.getTitle());
+ title.setTextSize(TypedValue.COMPLEX_UNIT_PX, title.getTextSize()*(float)1.3);
+
+ ((TextView) findViewById(R.id.epg_detail_time)).setText(formatter.getTime());
+ ((TextView)findViewById(R.id.epg_detail_channel)).setText(event.getChannelName());
+ ((TextView)findViewById(R.id.epg_detail_date)).setText(formatter.getLongDate());
+ final TextView textView = (TextView)findViewById(R.id.epg_detail_description);
+ textView.setText(formatter.getDescription());
+
+ // copy color for separator lines
+ final int color = textView.getTextColors().getDefaultColor();
+ ((TextView)findViewById(R.id.epg_detail_separator_1)).setBackgroundColor(color);
+ ((TextView)findViewById(R.id.epg_detail_separator_2)).setBackgroundColor(color);
+
+ // register button handler
+ final Button timeButton = (Button) findViewById(R.id.epg_event_create_timer);
+ timeButton.setOnClickListener(this);
+
+ // set button text
+ if (event.getTimer() == null) {
+ timeButton.setText(R.string.epg_event_create_timer_text);
+ } else {
+ timeButton.setText(R.string.epg_event_modify_timer_text);
+ }
+
+ // clear list of activities to finish
+ app.clearActivitiesToFinish();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ }
+
+ public void onClick(final View v) {
+
+ // after timer creation/modification return to the epg list
+ final VdrManagerApp app = (VdrManagerApp) getApplication();
+ app.addActivityToFinish(this);
+
+ // show timer details
+ final Intent intent = new Intent();
+ intent.setClass(this, TimerDetailsActivity.class);
+ startActivity(intent);
+ }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/gui/EpgListActivity.java b/vdrmanager/src/de/bjusystems/vdrmanager/gui/EpgListActivity.java
new file mode 100644
index 0000000..34ec06a
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/gui/EpgListActivity.java
@@ -0,0 +1,408 @@
+package de.bjusystems.vdrmanager.gui;
+
+import java.util.List;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.ContextMenu;
+import android.view.ContextMenu.ContextMenuInfo;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.AdapterView.OnItemSelectedListener;
+import android.widget.ArrayAdapter;
+import android.widget.LinearLayout;
+import android.widget.ListView;
+import android.widget.Spinner;
+import android.widget.TextView;
+import de.bjusystems.vdrmanager.R;
+import de.bjusystems.vdrmanager.app.VdrManagerApp;
+import de.bjusystems.vdrmanager.data.Channel;
+import de.bjusystems.vdrmanager.data.Epg;
+import de.bjusystems.vdrmanager.data.EpgSearchParams;
+import de.bjusystems.vdrmanager.data.EpgSearchTimeValue;
+import de.bjusystems.vdrmanager.data.EpgSearchTimeValues;
+import de.bjusystems.vdrmanager.data.EventFormatter;
+import de.bjusystems.vdrmanager.data.EventListItem;
+import de.bjusystems.vdrmanager.data.Preferences;
+import de.bjusystems.vdrmanager.tasks.DeleteTimerTask;
+import de.bjusystems.vdrmanager.tasks.ToggleTimerTask;
+import de.bjusystems.vdrmanager.utils.svdrp.EpgClient;
+import de.bjusystems.vdrmanager.utils.svdrp.SvdrpAsyncListener;
+import de.bjusystems.vdrmanager.utils.svdrp.SvdrpAsyncTask;
+import de.bjusystems.vdrmanager.utils.svdrp.SvdrpClient;
+import de.bjusystems.vdrmanager.utils.svdrp.SvdrpEvent;
+import de.bjusystems.vdrmanager.utils.svdrp.SvdrpException;
+
+/**
+ * This class is used for showing what's
+ * current running on all channels
+ * @author bju
+ */
+public class EpgListActivity extends Activity
+ implements OnItemClickListener, OnItemSelectedListener, SvdrpAsyncListener<Epg> {
+
+ EpgClient epgClient;
+ EventAdapter adapter;
+ Preferences prefs;
+ Spinner timeSpinner;
+ Spinner channelSpinner;
+ ArrayAdapter<EpgSearchTimeValue> timeSpinnerAdapter;
+ ListView listView;
+ SvdrpProgressDialog progress;
+
+ @Override
+ protected void onCreate(final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // application object
+ final VdrManagerApp app = (VdrManagerApp)getApplication();
+ // get state
+ final Channel channel = ((VdrManagerApp) getApplication()).getCurrentChannel();
+ final List<Channel> channels = ((VdrManagerApp) getApplication()).getChannels();
+
+ // Attach view
+ setContentView(R.layout.epg_list);
+
+ // create adapter for time spinner
+ timeSpinnerAdapter = new ArrayAdapter<EpgSearchTimeValue>(this, android.R.layout.simple_spinner_item);
+ timeSpinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ timeSpinner = (Spinner) findViewById(R.id.epg_list_time_spinner);
+ timeSpinner.setAdapter(timeSpinnerAdapter);
+
+ // create adapter for channel spinner
+ final ArrayAdapter<Channel> channelSpinnerAdapter = new ArrayAdapter<Channel>(this, android.R.layout.simple_spinner_item);
+ channelSpinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ channelSpinner = (Spinner) findViewById(R.id.epg_list_channel_spinner);
+ channelSpinner.setAdapter(channelSpinnerAdapter);
+
+ // get search label
+ final TextView searchLabel = (TextView) findViewById(R.id.epg_list_search_label);
+
+ // fill spinners
+ if (channels != null) {
+ // add dummy timer
+ timeSpinnerAdapter.add(new EpgSearchTimeValue());
+ // add channel values
+ for(final Channel c : channels) {
+ channelSpinnerAdapter.add(c);
+ }
+ } else {
+ // add dummy channel
+ channelSpinnerAdapter.add(new Channel());
+ // add time values
+ fillTimeSpinnerValues();
+ }
+
+ // show needed items
+ final LinearLayout timeLayout = (LinearLayout) findViewById(R.id.whatson_time);
+
+ // update gui
+ switch (app.getEpgListState()) {
+ case EPG_TIME:
+ adapter = new EventAdapter(this, false);
+ timeLayout.setVisibility(View.VISIBLE);
+ channelSpinner.setVisibility(View.GONE);
+ searchLabel.setVisibility(View.GONE);
+ timeSpinner.setOnItemSelectedListener(this);
+ timeSpinner.setSelection(0);
+ break;
+ case EPG_CHANNEL:
+ adapter = new EventAdapter(this, true);
+ timeLayout.setVisibility(View.GONE);
+ channelSpinner.setVisibility(View.VISIBLE);
+ searchLabel.setVisibility(View.GONE);
+ channelSpinner.setOnItemSelectedListener(this);
+ channelSpinner.setSelection(channel.getNumber() - 1);
+ break;
+ case EPG_SEARCH:
+ adapter = new EventAdapter(this, true);
+ timeLayout.setVisibility(View.GONE);
+ channelSpinner.setVisibility(View.GONE);
+ searchLabel.setVisibility(View.VISIBLE);
+ startSearchEpgQuery(app.getCurrentSearch());
+ break;
+ }
+
+ // Create adapter for EPG list
+ listView = (ListView) findViewById(R.id.whatson_list);
+ listView.setAdapter(adapter);
+ registerForContextMenu(listView);
+
+ // register EPG item click
+ listView.setOnItemClickListener(this);
+
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ fillTimeSpinnerValues();
+
+ reloadIfNeeded();
+ }
+
+ private void reloadIfNeeded() {
+
+ final VdrManagerApp app = (VdrManagerApp) getApplication();
+ if (app.isReload()) {
+ app.setReload(false);
+ startEpgQuery(epgClient);
+ }
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ if (epgClient != null) {
+ epgClient.abort();
+ }
+ if (progress != null) {
+ progress.dismiss();
+ progress = null;
+ }
+ }
+
+ public void onItemClick(final AdapterView<?> parent, final View view, final int position, final long id) {
+
+ // find and remember item
+ final EventListItem item = adapter.getItem(position);
+
+ // prepare timer if we want to program
+ prepareTimer(item);
+
+ // show details
+ final Intent intent = new Intent();
+ intent.setClass(this, EpgDetailsActivity.class);
+ startActivity(intent);
+ }
+
+ public void onItemSelected(final AdapterView<?> parent, final View view, final int position, final long id) {
+
+ if (parent == timeSpinner) {
+ // get spinner value
+ final EpgSearchTimeValue selection = (EpgSearchTimeValue) timeSpinner.getSelectedItem();
+ // update search
+ startTimeEpgQuery(selection.getValue());
+ } else {
+ // get spinner value
+ final Channel channel = (Channel) channelSpinner.getSelectedItem();
+ // update search
+ startChannelEpgQuery(channel);
+ }
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(final Menu menu) {
+ super.onCreateOptionsMenu(menu);
+
+ final MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.epg_list_menu, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(final MenuItem item) {
+
+ Intent intent;
+
+ switch (item.getItemId())
+ {
+ case R.id.epg_menu_search:
+ intent = new Intent();
+ intent.setClass(this, EpgSearchActivity.class);
+ startActivity(intent);
+ break;
+ case R.id.epg_menu_times:
+ intent = new Intent();
+ intent.setClass(this, EpgSearchTimesListActivity.class);
+ startActivity(intent);
+ break;
+ }
+ return true;
+ }
+
+ @Override
+ public void onCreateContextMenu(final ContextMenu menu, final View v, final ContextMenuInfo menuInfo) {
+ super.onCreateContextMenu(menu, v, menuInfo);
+
+ if (v.getId() == R.id.whatson_list) {
+ final MenuInflater inflater = getMenuInflater();
+ final AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)menuInfo;
+
+ // set menu title
+ final EventListItem item = adapter.getItem(info.position);
+ final EventFormatter formatter = new EventFormatter(item);
+ menu.setHeaderTitle(formatter.getTitle());
+
+ inflater.inflate(R.menu.epg_list_item_menu, menu);
+
+ // remove unneeded menu items
+ if (item.getEpg().getTimer() != null) {
+ menu.findItem(R.id.epg_item_menu_timer_add).setVisible(false);
+ final MenuItem enableMenuItem = menu.findItem(R.id.epg_item_menu_timer_toggle);
+ enableMenuItem.setTitle(item.getEpg().getTimer().isEnabled() ? R.string.epg_item_menu_timer_disable : R.string.epg_item_menu_timer_enable);
+ } else {
+ menu.findItem(R.id.epg_item_menu_timer_modify).setVisible(false);
+ menu.findItem(R.id.epg_item_menu_timer_delete).setVisible(false);
+ }
+ }
+ }
+
+
+
+ @Override
+ public boolean onContextItemSelected(final MenuItem item) {
+
+ final AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)item.getMenuInfo();
+ final EventListItem event = adapter.getItem(info.position);
+
+ switch (item.getItemId()) {
+ case R.id.epg_item_menu_timer_add:
+ case R.id.epg_item_menu_timer_modify:
+ {
+ prepareTimer(event);
+
+ final Intent intent = new Intent();
+ intent.setClass(this, TimerDetailsActivity.class);
+ startActivity(intent);
+ break;
+ }
+ case R.id.epg_item_menu_timer_delete:
+ {
+ deleteTimer(event);
+ break;
+ }
+ case R.id.epg_item_menu_timer_toggle:
+ {
+ toggleTimer(event);
+ }
+ }
+
+ return true;
+ }
+
+ public void onNothingSelected(final AdapterView<?> arg0) {
+ //startTimeEpgQuery(((EpgTimeSpinnerValue)timeSpinner.getAdapter().getItem(0)).getValue());
+ }
+
+ private void startSearchEpgQuery(final EpgSearchParams search) {
+
+ epgClient = new EpgClient(search);
+ startEpgQuery(epgClient);
+ }
+
+ private void startTimeEpgQuery(final String time) {
+
+ epgClient = new EpgClient(time);
+ startEpgQuery(epgClient);
+ }
+
+ private void startChannelEpgQuery(final Channel channel) {
+
+ epgClient = new EpgClient(channel);
+ startEpgQuery(epgClient);
+ }
+
+ private void startEpgQuery(final EpgClient epgClient) {
+
+ // remove old listeners
+ epgClient.clearSvdrpListener();
+
+ // create background task
+ final SvdrpAsyncTask<Epg, SvdrpClient<Epg>> task = new SvdrpAsyncTask<Epg, SvdrpClient<Epg>>(epgClient);
+
+ // create progress
+ progress = new SvdrpProgressDialog(this, epgClient);
+
+ // attach listener
+ task.addListener(this);
+
+ // start task
+ task.run();
+ }
+
+ public void svdrpEvent(final SvdrpEvent event, final Epg result) {
+
+ if (progress != null) {
+ progress.svdrpEvent(event);
+ }
+
+ switch (event) {
+ case CONNECTING:
+ adapter.clearItems();
+ break;
+ case LOGIN_ERROR:
+ this.finish();
+ break;
+ case FINISHED:
+ epgClient.clearSvdrpListener();
+ for(final Epg epg : epgClient.getResults()) {
+ adapter.addItem(new EventListItem(epg));
+ }
+ adapter.sortItems();
+ listView.setSelectionAfterHeaderView();
+ progress = null;
+ break;
+ }
+ }
+
+ public void svdrpException(final SvdrpException exception) {
+ if (progress != null) {
+ progress.svdrpException(exception);
+ }
+ }
+
+ private void prepareTimer(final EventListItem item) {
+
+ final VdrManagerApp app = (VdrManagerApp) getApplication();
+
+ // remember event for details view and timer things
+ app.setCurrentEvent(item.getEpg());
+
+ // if we create or modify the attached timer we will return to a new epg list
+ app.clearActivitiesToFinish();
+ app.addActivityToFinish(this);
+ app.setNextActivity(EpgListActivity.class);
+ }
+
+ private void deleteTimer(final EventListItem item) {
+
+ final DeleteTimerTask task = new DeleteTimerTask(this, item.getEpg().getTimer()) {
+ @Override
+ public void finished() {
+ // refresh epg list after return
+ final VdrManagerApp app = (VdrManagerApp) getApplication();
+ app.setReload(true);
+ reloadIfNeeded();
+ }
+ };
+ task.start();
+ }
+
+ private void toggleTimer(final EventListItem item) {
+
+ final ToggleTimerTask task = new ToggleTimerTask(this, item.getEpg().getTimer()) {
+ @Override
+ public void finished() {
+ // refresh epg list after return
+ final VdrManagerApp app = (VdrManagerApp) getApplication();
+ app.setReload(true);
+ reloadIfNeeded();
+ }
+ };
+ task.start();
+ }
+
+ private void fillTimeSpinnerValues() {
+ final EpgSearchTimeValues values = new EpgSearchTimeValues(this);
+ timeSpinnerAdapter.clear();
+ for(final EpgSearchTimeValue value : values.getValues()) {
+ timeSpinnerAdapter.add(value);
+ }
+ }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/gui/EpgSearchActivity.java b/vdrmanager/src/de/bjusystems/vdrmanager/gui/EpgSearchActivity.java
new file mode 100644
index 0000000..90e8c00
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/gui/EpgSearchActivity.java
@@ -0,0 +1,63 @@
+package de.bjusystems.vdrmanager.gui;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.TextView;
+import de.bjusystems.vdrmanager.R;
+import de.bjusystems.vdrmanager.app.VdrManagerApp;
+import de.bjusystems.vdrmanager.data.EpgSearchParams;
+import de.bjusystems.vdrmanager.data.Preferences;
+
+/**
+ * This class is used for showing what's
+ * current running on all channels
+ * @author bju
+ */
+public class EpgSearchActivity extends Activity
+ implements OnClickListener {
+
+ Preferences prefs;
+ TextView text;
+
+ @Override
+ protected void onCreate(final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Attach view
+ setContentView(R.layout.epg_search);
+
+ // save fields
+ text = (TextView) findViewById(R.id.epg_search_text);
+
+ // register button
+ final Button button = (Button) findViewById(R.id.epg_search_button);
+ button.setOnClickListener(this);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ }
+
+ public void onClick(final View v) {
+
+ // Save search parameters
+ final EpgSearchParams search = new EpgSearchParams();
+ search.setTitle(text.getText().toString());
+ ((VdrManagerApp)getApplication()).setCurrentSearch(search);
+
+ // show timer details
+ final Intent intent = new Intent();
+ intent.setClass(this, EpgListActivity.class);
+ startActivity(intent);
+ }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/gui/EpgSearchTimesListActivity.java b/vdrmanager/src/de/bjusystems/vdrmanager/gui/EpgSearchTimesListActivity.java
new file mode 100644
index 0000000..891babf
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/gui/EpgSearchTimesListActivity.java
@@ -0,0 +1,130 @@
+package de.bjusystems.vdrmanager.gui;
+
+import java.util.List;
+
+import android.app.Activity;
+import android.app.TimePickerDialog;
+import android.app.TimePickerDialog.OnTimeSetListener;
+import android.os.Bundle;
+import android.view.ContextMenu;
+import android.view.ContextMenu.ContextMenuInfo;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.ListView;
+import android.widget.TimePicker;
+import de.bjusystems.vdrmanager.R;
+import de.bjusystems.vdrmanager.data.EpgSearchTimeValue;
+import de.bjusystems.vdrmanager.data.EpgSearchTimeValues;
+import de.bjusystems.vdrmanager.data.Preferences;
+
+/**
+ * This class is used for showing what's
+ * current running on all channels
+ * @author bju
+ */
+public class EpgSearchTimesListActivity extends Activity
+ implements OnClickListener, OnTimeSetListener {
+
+ ArrayAdapter<EpgSearchTimeValue> adapter;
+ List<EpgSearchTimeValue> values;
+ Preferences prefs;
+
+ @Override
+ protected void onCreate(final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Attach view
+ setContentView(R.layout.epg_search_times_list);
+
+ // Create adapter for ListView
+ adapter = new ArrayAdapter<EpgSearchTimeValue>(this, R.layout.epg_search_times_item);
+ final ListView listView = (ListView) findViewById(R.id.epg_search_times_list);
+ listView.setAdapter(adapter);
+ registerForContextMenu(listView);
+
+ // create channel list
+ updateList();
+
+ // button handler
+ final Button addButton = (Button) findViewById(R.id.epg_search_times_add);
+ addButton.setOnClickListener(this);
+ }
+
+ public void onClick(final View v) {
+
+ // show time selection
+ final TimePickerDialog dialog = new TimePickerDialog(this, this, 0, 0, true);
+ dialog.show();
+ }
+
+ public void onTimeSet(final TimePicker view, final int hourOfDay, final int minute) {
+
+ final EpgSearchTimeValue time = new EpgSearchTimeValue(values.size(), String.format("%02d:%02d", hourOfDay, minute));
+ values.add(time);
+ adapter.add(time);
+
+ save();
+
+ updateList();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ }
+
+ @Override
+ public void onCreateContextMenu(final ContextMenu menu, final View v, final ContextMenuInfo menuInfo) {
+ super.onCreateContextMenu(menu, v, menuInfo);
+
+ if (v.getId() == R.id.epg_search_times_list) {
+ final MenuInflater inflater = getMenuInflater();
+ final AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)menuInfo;
+ menu.setHeaderTitle(values.get(info.position+2).toString());
+
+ inflater.inflate(R.menu.epg_search_time_item_menu, menu);
+ }
+ }
+
+
+
+ @Override
+ public boolean onContextItemSelected(final MenuItem item) {
+
+ final AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)item.getMenuInfo();
+ final EpgSearchTimeValue time = values.get(info.position+2);
+
+ if (item.getItemId() == R.id.epg_search_time_delete) {
+ values.remove(time);
+ adapter.remove(time);
+
+ save();
+ }
+
+ return true;
+ }
+
+ private void updateList() {
+
+ // get values
+ values = new EpgSearchTimeValues(this).getValues();
+ adapter.clear();
+ for(int i = 2; i < values.size(); i++) {
+ adapter.add(values.get(i));
+ }
+ }
+
+ private void save() {
+ new EpgSearchTimeValues(this).saveValues(values);
+ }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/gui/EventAdapter.java b/vdrmanager/src/de/bjusystems/vdrmanager/gui/EventAdapter.java
new file mode 100644
index 0000000..0a97576
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/gui/EventAdapter.java
@@ -0,0 +1,171 @@
+package de.bjusystems.vdrmanager.gui;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Comparator;
+import java.util.GregorianCalendar;
+import java.util.List;
+
+import android.content.Context;
+import android.graphics.Color;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import android.widget.TextView;
+import de.bjusystems.vdrmanager.R;
+import de.bjusystems.vdrmanager.data.EventFormatter;
+import de.bjusystems.vdrmanager.data.EventListItem;
+import de.bjusystems.vdrmanager.utils.date.DateFormatter;
+
+class EventAdapter extends ArrayAdapter<EventListItem> {
+
+ private final LayoutInflater inflater;
+ private final List<EventListItem> items;
+ private final boolean sortByTime;
+
+ public EventAdapter(final Context context, final boolean sortByTime) {
+ super(context, R.layout.event_item);
+ inflater = LayoutInflater.from(context);
+ items = new ArrayList<EventListItem>();
+ this.sortByTime = sortByTime;
+ }
+
+ @Override
+ public View getView(final int position, final View convertView, final ViewGroup parent) {
+
+ EventListItemHolder itemHolder = new EventListItemHolder();
+
+ // recycle view?
+ View view = convertView;
+ if (view == null) {
+ view = inflater.inflate(R.layout.event_item, null);
+ itemHolder = new EventListItemHolder();
+
+ itemHolder.state = (ImageView) view.findViewById(R.id.timer_item_state);
+ itemHolder.time = (TextView) view.findViewById(R.id.timer_item_time);
+ itemHolder.channel = (TextView) view.findViewById(R.id.timer_item_channel);
+ itemHolder.title = (TextView) view.findViewById(R.id.timer_item_title);
+
+ view.setTag(itemHolder);
+ } else {
+ itemHolder = (EventListItemHolder) view.getTag();
+ }
+
+ // get item
+ final EventListItem item = getItem(position);
+
+ // fill item
+ if (item.isHeader()) {
+ view.setPadding(view.getPaddingLeft(), 0, view.getPaddingRight(), 0);
+ view.setBackgroundColor(Color.DKGRAY);
+ itemHolder.state.setVisibility(View.GONE);
+ itemHolder.channel.setVisibility(View.GONE);
+ itemHolder.title.setVisibility(View.GONE);
+ itemHolder.time.setText(item.getHeader());
+ } else {
+ view.setBackgroundColor(Color.BLACK);
+ itemHolder.channel.setVisibility(View.VISIBLE);
+ itemHolder.title.setVisibility(View.VISIBLE);
+ itemHolder.state.setVisibility(View.VISIBLE);
+ switch (item.getTimerState()) {
+ case Active:
+ itemHolder.state.setImageResource(R.drawable.timer_active);
+ break;
+ case Inactive:
+ itemHolder.state.setImageResource(R.drawable.timer_inactive);
+ break;
+ case Recording:
+ itemHolder.state.setImageResource(R.drawable.timer_recording);
+ break;
+ case None:
+ itemHolder.state.setImageResource(R.drawable.timer_none);
+ break;
+ }
+ final EventFormatter formatter = new EventFormatter(item.getEvent());
+ itemHolder.time.setText(formatter.getTime());
+ itemHolder.channel.setText(item.getChannelName());
+ itemHolder.title.setText(formatter.getTitle());
+ }
+
+ return view;
+ }
+
+ public void addItem(final EventListItem item) {
+ items.add(item);
+ }
+
+ public void sortItems() {
+ if (sortByTime) {
+ sortItemsByTime();
+ } else {
+ sortItemsByChannel();
+ }
+ }
+
+ private void sortItemsByTime() {
+
+ // sort by start time
+ final EventListItem[] unsortedItems = items.toArray(new EventListItem[0]);
+ final Comparator<EventListItem> comparator = new Comparator<EventListItem>() {
+
+ public int compare(final EventListItem item1, final EventListItem item2) {
+ return item1.getStart().compareTo(item2.getStart());
+ }
+ };
+ Arrays.sort(unsortedItems, comparator);
+
+ // insert daily headers
+ final List<EventListItem> sortedItems = new ArrayList<EventListItem>();
+ final GregorianCalendar itemCal = new GregorianCalendar();
+ final GregorianCalendar lastHeaderCal = new GregorianCalendar();
+ lastHeaderCal.set(Calendar.YEAR, 1970);
+
+ for(final EventListItem item : unsortedItems) {
+ itemCal.setTime(item.getStart());
+
+ if (itemCal.get(Calendar.DAY_OF_YEAR) != lastHeaderCal.get(Calendar.DAY_OF_YEAR) ||
+ itemCal.get(Calendar.YEAR) != lastHeaderCal.get(Calendar.YEAR)) {
+ lastHeaderCal.setTimeInMillis(itemCal.getTimeInMillis());
+ final DateFormatter dateFormatter = new DateFormatter(lastHeaderCal);
+ sortedItems.add(new EventListItem(dateFormatter.getDailyHeader()));
+ }
+
+ sortedItems.add(item);
+ }
+
+ // fill adapter
+ clear();
+ for(final EventListItem item : sortedItems) {
+ add(item);
+ }
+ }
+
+ private void sortItemsByChannel() {
+
+ final EventListItem[] sortedItems = items.toArray(new EventListItem[0]);
+ final Comparator<EventListItem> comparator = new Comparator<EventListItem>() {
+
+ public int compare(final EventListItem item1, final EventListItem item2) {
+ return Integer.valueOf(item1.getChannelNumber()).compareTo(Integer.valueOf(item2.getChannelNumber()));
+ }
+ };
+ Arrays.sort(sortedItems, comparator);
+
+ // fill adapter
+ clear();
+ if (sortedItems.length > 0) {
+ add(new EventListItem(new DateFormatter(sortedItems[0].getStart()).getDailyHeader()));
+ }
+ for(final EventListItem item : sortedItems) {
+ add(item);
+ }
+
+ }
+
+ public void clearItems() {
+ items.clear();
+ }
+} \ No newline at end of file
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/gui/EventListItemHolder.java b/vdrmanager/src/de/bjusystems/vdrmanager/gui/EventListItemHolder.java
new file mode 100644
index 0000000..bac6ebb
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/gui/EventListItemHolder.java
@@ -0,0 +1,12 @@
+package de.bjusystems.vdrmanager.gui;
+
+import android.widget.ImageView;
+import android.widget.TextView;
+
+class EventListItemHolder {
+ public ImageView state;
+ public TextView title;
+ public TextView date;
+ public TextView time;
+ public TextView channel;
+} \ No newline at end of file
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/gui/PreferencesActivity.java b/vdrmanager/src/de/bjusystems/vdrmanager/gui/PreferencesActivity.java
new file mode 100644
index 0000000..cb6e4d1
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/gui/PreferencesActivity.java
@@ -0,0 +1,34 @@
+package de.bjusystems.vdrmanager.gui;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.preference.PreferenceActivity;
+import de.bjusystems.vdrmanager.R;
+import de.bjusystems.vdrmanager.app.VdrManagerApp;
+import de.bjusystems.vdrmanager.data.Preferences;
+
+public class PreferencesActivity extends PreferenceActivity {
+
+ @Override
+ protected void onCreate(final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ this.getPreferenceManager().setSharedPreferencesName(Preferences.getPreferenceFile(this));
+ this.addPreferencesFromResource(R.xml.preferences);
+ }
+
+ @Override
+ public void onBackPressed() {
+
+ // finish this activity
+ final VdrManagerApp app = (VdrManagerApp) getApplication();
+ app.addActivityToFinish(this);
+ app.finishActivities();
+
+ // restart main activity because
+ // the buttons needs refreshing
+ final Intent intent = new Intent();
+ intent.setClass(this, VdrManagerActivity.class);
+ startActivity(intent);
+ }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/gui/SvdrpProgressDialog.java b/vdrmanager/src/de/bjusystems/vdrmanager/gui/SvdrpProgressDialog.java
new file mode 100644
index 0000000..e630ff9
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/gui/SvdrpProgressDialog.java
@@ -0,0 +1,72 @@
+package de.bjusystems.vdrmanager.gui;
+
+import android.app.Activity;
+import android.app.ProgressDialog;
+import android.widget.Toast;
+import de.bjusystems.vdrmanager.R;
+import de.bjusystems.vdrmanager.utils.svdrp.SvdrpClient;
+import de.bjusystems.vdrmanager.utils.svdrp.SvdrpEvent;
+import de.bjusystems.vdrmanager.utils.svdrp.SvdrpException;
+
+public class SvdrpProgressDialog extends ProgressDialog {
+
+ ProgressDialog progress;
+ Activity activity;
+ SvdrpClient<? extends Object> client;
+
+ public SvdrpProgressDialog(final Activity activity, final SvdrpClient<? extends Object> client) {
+ super(activity);
+ this.activity = activity;
+ this.client = client;
+ }
+
+ public void svdrpEvent(final SvdrpEvent event) {
+
+ switch (event) {
+ case CONNECTING:
+ progress = new ProgressDialog(activity);
+ progress.setProgressStyle(ProgressDialog.STYLE_SPINNER);
+ setMessage(R.string.progress_connect);
+ progress.show();
+ break;
+ case LOGGED_IN:
+ setMessage(R.string.progress_login);
+ break;
+ case LOGIN_ERROR:
+ progress.dismiss();
+ showToast(R.string.progress_login_error);
+ break;
+ case COMMAND_SENT:
+ setMessage(client.getProgressTextId());
+ break;
+ case RESULT_RECEIVED:
+ break;
+ case DISCONNECTING:
+ setMessage(R.string.progress_disconnect);
+ break;
+ case DISCONNECTED:
+ break;
+ case FINISHED:
+ progress.dismiss();
+ break;
+ }
+ }
+
+ public void svdrpException(final SvdrpException exception) {
+ showToast(R.string.vdr_error_text);
+ }
+
+ private void setMessage(final int resId) {
+ progress.setMessage(activity.getText(resId));
+ }
+
+ private void showToast(final int resId) {
+ progress.dismiss();
+
+ final CharSequence text = activity.getText(resId);
+ final int duration = Toast.LENGTH_LONG;
+ final Toast toast = Toast.makeText(activity, text, duration);
+ toast.show();
+ }
+}
+
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/gui/TimerDetailsActivity.java b/vdrmanager/src/de/bjusystems/vdrmanager/gui/TimerDetailsActivity.java
new file mode 100644
index 0000000..60db80c
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/gui/TimerDetailsActivity.java
@@ -0,0 +1,232 @@
+package de.bjusystems.vdrmanager.gui;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+
+import android.app.Activity;
+import android.app.DatePickerDialog;
+import android.app.DatePickerDialog.OnDateSetListener;
+import android.app.TimePickerDialog;
+import android.app.TimePickerDialog.OnTimeSetListener;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.DatePicker;
+import android.widget.TextView;
+import android.widget.TimePicker;
+import de.bjusystems.vdrmanager.R;
+import de.bjusystems.vdrmanager.app.VdrManagerApp;
+import de.bjusystems.vdrmanager.data.Preferences;
+import de.bjusystems.vdrmanager.data.Timer;
+import de.bjusystems.vdrmanager.utils.date.DateFormatter;
+import de.bjusystems.vdrmanager.utils.svdrp.SetTimerClient;
+import de.bjusystems.vdrmanager.utils.svdrp.SvdrpAsyncListener;
+import de.bjusystems.vdrmanager.utils.svdrp.SvdrpAsyncTask;
+import de.bjusystems.vdrmanager.utils.svdrp.SvdrpClient;
+import de.bjusystems.vdrmanager.utils.svdrp.SvdrpEvent;
+import de.bjusystems.vdrmanager.utils.svdrp.SvdrpException;
+
+/**
+ * This class is used for showing what's
+ * current running on all channels
+ * @author bju
+ */
+public class TimerDetailsActivity extends Activity
+ implements OnClickListener, OnDateSetListener, OnTimeSetListener, SvdrpAsyncListener<Timer> {
+
+ Preferences prefs;
+ TextView dateField;
+ TextView startField;
+ TextView endField;
+ boolean editStart;
+ Timer timer;
+ SvdrpProgressDialog progress;
+ SetTimerClient setTimerClient;
+
+ @Override
+ protected void onCreate(final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Attach view
+ setContentView(R.layout.timer_detail);
+
+ // timer
+ timer = ((VdrManagerApp)getApplication()).getCurrentTimer();
+
+ // update display
+ updateDisplay();
+
+ // register buttons
+ final Button saveButton = (Button) findViewById(R.id.timer_details_save);
+ saveButton.setOnClickListener(this);
+ if (timer.getNumber() > 0) {
+ saveButton.setText(R.string.timer_details_save_title);
+ } else {
+ saveButton.setText(R.string.timer_details_create_title);
+ }
+
+ // register text fields for editing
+ dateField.setOnClickListener(this);
+ startField.setOnClickListener(this);
+ endField.setOnClickListener(this);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ }
+
+ public void onClick(final View view) {
+ switch (view.getId()) {
+ case R.id.timer_detail_day:
+ {
+ final Calendar cal = new GregorianCalendar();
+ cal.setTime(timer.getStart());
+ final DatePickerDialog dialog = new DatePickerDialog(this, this, cal.get(Calendar.YEAR),
+ cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH));
+ dialog.show();
+ break;
+ }
+ case R.id.timer_detail_start:
+ {
+ final Calendar cal = new GregorianCalendar();
+ cal.setTime(timer.getStart());
+ editStart = true;
+ final TimePickerDialog dialog = new TimePickerDialog(this, this, cal.get(Calendar.HOUR_OF_DAY),
+ cal.get(Calendar.MINUTE), true);
+ dialog.show();
+ break;
+ }
+ case R.id.timer_detail_end:
+ {
+ final Calendar cal = new GregorianCalendar();
+ cal.setTime(timer.getStop());
+ editStart = false;
+ final TimePickerDialog dialog = new TimePickerDialog(this, this, cal.get(Calendar.HOUR_OF_DAY),
+ cal.get(Calendar.MINUTE), true);
+ dialog.show();
+ break;
+ }
+ case R.id.timer_details_save:
+ {
+ // collect values
+ timer.setTitle(((TextView)findViewById(R.id.timer_detail_title)).getText().toString());
+
+ // create client for saving the timer
+ setTimerClient = new SetTimerClient(timer, false);
+
+ // create backgound task
+ final SvdrpAsyncTask<Timer, SvdrpClient<Timer>> task = new SvdrpAsyncTask<Timer, SvdrpClient<Timer>>(setTimerClient);
+
+ // create progress
+ progress = new SvdrpProgressDialog(this, setTimerClient);
+
+ // attach listener
+ task.addListener(this);
+
+ // start task
+ task.run();
+ }
+ }
+ }
+
+ public void onTimeSet(final TimePicker view, final int hourOfDay, final int minute) {
+ if (editStart) {
+ timer.setStart(calculateTime(timer.getStart(), hourOfDay, minute, null));
+ } else {
+ timer.setStop(calculateTime(timer.getStop(), hourOfDay, minute, timer.getStart()));
+ }
+ updateDisplay();
+ }
+
+ public void onDateSet(final DatePicker view, final int year, final int monthOfYear, final int dayOfMonth) {
+ timer.setStart(calculateDate(timer.getStart(), year, monthOfYear, dayOfMonth));
+ updateDisplay();
+ }
+
+ private Date calculateDate(final Date oldDate, final int year, final int monthOfYear, final int dayOfMonth) {
+
+ final Calendar cal = new GregorianCalendar();
+ cal.setTime(oldDate);
+ cal.set(Calendar.YEAR, year);
+ cal.set(Calendar.MONTH, monthOfYear);
+ cal.set(Calendar.DAY_OF_MONTH, dayOfMonth);
+
+ return cal.getTime();
+ }
+
+ private Date calculateTime(final Date oldTime, final int hourOfDay, final int minute, final Date startTime) {
+
+ // set hour and minute
+ final Calendar cal = new GregorianCalendar();
+ cal.setTime(oldTime);
+ cal.set(Calendar.HOUR_OF_DAY, hourOfDay);
+ cal.set(Calendar.MINUTE, minute);
+
+ // go to the next day if end time before start time
+ if (startTime != null) {
+ if (cal.getTime().before(startTime)) {
+ cal.add(Calendar.DAY_OF_MONTH, 1);
+ }
+ }
+
+ return cal.getTime();
+
+ }
+
+ private void updateDisplay() {
+
+ ((TextView)findViewById(R.id.timer_detail_title)).setText(timer.getTitle());
+ ((TextView)findViewById(R.id.timer_detail_channel)).setText(timer.getChannelName());
+ dateField = (TextView)findViewById(R.id.timer_detail_day);
+ final DateFormatter dateFormatter = new DateFormatter(timer.getStart());
+ dateField.setText(dateFormatter.getDateString());
+ startField = (TextView)findViewById(R.id.timer_detail_start);
+ startField.setText(dateFormatter.getTimeString());
+ endField = (TextView)findViewById(R.id.timer_detail_end);
+ endField.setText(new DateFormatter(timer.getStop()).getTimeString());
+
+ final Button button = (Button) findViewById(R.id.timer_details_save);
+ if (timer.getNumber() > 0) {
+ // existing timer
+ button.setText(R.string.timer_details_save_title);
+ } else {
+ // new timer
+ button.setText(R.string.timer_details_create_title);
+ }
+ }
+
+ public void svdrpEvent(final SvdrpEvent event, final Timer result) {
+
+ progress.svdrpEvent(event);
+
+ switch (event) {
+ case FINISHED:
+ // remove this activity from stack
+ finish();
+
+ // finish previous activities
+ final VdrManagerApp app = (VdrManagerApp) getApplication();
+ app.finishActivities();
+
+ // refresh last view
+ app.setReload(true);
+
+ // free progress dialog
+ progress = null;
+
+ break;
+ }
+ }
+
+ public void svdrpException(final SvdrpException exception) {
+ progress.svdrpException(exception);
+ }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/gui/TimerListActivity.java b/vdrmanager/src/de/bjusystems/vdrmanager/gui/TimerListActivity.java
new file mode 100644
index 0000000..52fa1e0
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/gui/TimerListActivity.java
@@ -0,0 +1,238 @@
+package de.bjusystems.vdrmanager.gui;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.ContextMenu;
+import android.view.ContextMenu.ContextMenuInfo;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.ListView;
+import de.bjusystems.vdrmanager.R;
+import de.bjusystems.vdrmanager.app.VdrManagerApp;
+import de.bjusystems.vdrmanager.data.EventFormatter;
+import de.bjusystems.vdrmanager.data.EventListItem;
+import de.bjusystems.vdrmanager.data.Timer;
+import de.bjusystems.vdrmanager.tasks.DeleteTimerTask;
+import de.bjusystems.vdrmanager.tasks.ToggleTimerTask;
+import de.bjusystems.vdrmanager.utils.svdrp.SvdrpAsyncListener;
+import de.bjusystems.vdrmanager.utils.svdrp.SvdrpAsyncTask;
+import de.bjusystems.vdrmanager.utils.svdrp.SvdrpClient;
+import de.bjusystems.vdrmanager.utils.svdrp.SvdrpEvent;
+import de.bjusystems.vdrmanager.utils.svdrp.SvdrpException;
+import de.bjusystems.vdrmanager.utils.svdrp.TimerClient;
+
+/**
+ * This class is used for showing what's
+ * current running on all channels
+ * @author bju
+ */
+public class TimerListActivity extends Activity
+ implements OnItemClickListener, SvdrpAsyncListener<Timer> {
+
+ TimerClient timerClient;
+ EventAdapter adapter;
+ SvdrpProgressDialog progress;
+
+ @Override
+ protected void onCreate(final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Attach view
+ setContentView(R.layout.timer_list);
+
+ // create an adapter
+ adapter = new EventAdapter(this, true);
+
+ // attach adapter to ListView
+ final ListView listView = (ListView) findViewById(R.id.timer_list);
+ listView.setAdapter(adapter);
+
+ // set click listener
+ listView.setOnItemClickListener(this);
+
+ // context menu wanted
+ registerForContextMenu(listView);
+
+ // start query
+ startTimerQuery();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ reloadIfNeeded();
+ }
+
+ private void reloadIfNeeded() {
+
+ final VdrManagerApp app = (VdrManagerApp) getApplication();
+ if (app.isReload()) {
+ app.setReload(false);
+ startTimerQuery();
+ }
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ if (timerClient != null) {
+ timerClient.abort();
+ }
+ if (progress != null) {
+ progress.dismiss();
+ progress = null;
+ }
+ }
+
+ @Override
+ public void onCreateContextMenu(final ContextMenu menu, final View v, final ContextMenuInfo menuInfo) {
+ super.onCreateContextMenu(menu, v, menuInfo);
+
+ if (v.getId() == R.id.timer_list) {
+ final MenuInflater inflater = getMenuInflater();
+ final AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)menuInfo;
+
+ // set menu title
+ final EventListItem item = adapter.getItem(info.position);
+ final EventFormatter formatter = new EventFormatter(item);
+ menu.setHeaderTitle(formatter.getTitle());
+
+ inflater.inflate(R.menu.epg_list_item_menu, menu);
+
+ // remove unneeded menu items
+ menu.findItem(R.id.epg_item_menu_timer_add).setVisible(false);
+ final MenuItem enableMenuItem = menu.findItem(R.id.epg_item_menu_timer_toggle);
+ enableMenuItem.setTitle(item.getTimer().isEnabled() ? R.string.epg_item_menu_timer_disable : R.string.epg_item_menu_timer_enable);
+ }
+ }
+
+
+
+ @Override
+ public boolean onContextItemSelected(final MenuItem item) {
+
+ final AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)item.getMenuInfo();
+ final EventListItem event = adapter.getItem(info.position);
+
+ switch (item.getItemId()) {
+ case R.id.epg_item_menu_timer_modify:
+ {
+ onItemClick(null, null, info.position, 0);
+ break;
+ }
+ case R.id.epg_item_menu_timer_delete:
+ {
+ deleteTimer(event);
+ break;
+ }
+ case R.id.epg_item_menu_timer_toggle:
+ {
+ toggleTimer(event);
+ }
+ }
+
+ return true;
+ }
+
+ public void onItemClick(final AdapterView<?> parent, final View view, final int position, final long id) {
+
+ // save selected item
+ final Timer timer = adapter.getItem(position).getTimer();
+ if (timer == null) {
+ // header click
+ return;
+ }
+
+ final VdrManagerApp app = (VdrManagerApp) getApplication();
+ app.setCurrentTimer(timer);
+
+ // after timer editing return to the timer list
+ app.setNextActivity(TimerListActivity.class);
+ app.clearActivitiesToFinish();
+
+ // show timer details
+ final Intent intent = new Intent();
+ intent.setClass(this, TimerDetailsActivity.class);
+ startActivity(intent);
+ }
+
+ private void startTimerQuery() {
+
+ // get timer client
+ timerClient = new TimerClient();
+
+ // create backgound task
+ final SvdrpAsyncTask<Timer, SvdrpClient<Timer>> task = new SvdrpAsyncTask<Timer, SvdrpClient<Timer>>(timerClient);
+
+ // create progress dialog
+ progress = new SvdrpProgressDialog(this, timerClient);
+
+ // attach listener
+ task.addListener(this);
+
+ // start task
+ task.run();
+ }
+
+ public void svdrpEvent(final SvdrpEvent event, final Timer result) {
+
+ if (progress != null) {
+ progress.svdrpEvent(event);
+ }
+
+ switch (event) {
+ case CONNECTING:
+ adapter.clearItems();
+ break;
+ case LOGIN_ERROR:
+ this.finish();
+ break;
+ case FINISHED:
+ for(final Timer timer : timerClient.getResults()) {
+ adapter.addItem(new EventListItem(timer));
+ }
+ adapter.sortItems();
+ progress = null;
+ break;
+ }
+ }
+
+ public void svdrpException(final SvdrpException exception) {
+ if (progress != null) {
+ progress.svdrpException(exception);
+ }
+ }
+
+ private void deleteTimer(final EventListItem item) {
+
+ final DeleteTimerTask task = new DeleteTimerTask(this, item.getTimer()) {
+ @Override
+ public void finished() {
+ // refresh epg list after return
+ final VdrManagerApp app = (VdrManagerApp) getApplication();
+ app.setReload(true);
+ reloadIfNeeded();
+ }
+ };
+ task.start();
+ }
+
+ private void toggleTimer(final EventListItem item) {
+
+ final ToggleTimerTask task = new ToggleTimerTask(this, item.getTimer()) {
+ @Override
+ public void finished() {
+ // refresh epg list after return
+ final VdrManagerApp app = (VdrManagerApp) getApplication();
+ app.setReload(true);
+ reloadIfNeeded();
+ }
+ };
+ task.start();
+ }
+
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/gui/VdrManagerActivity.java b/vdrmanager/src/de/bjusystems/vdrmanager/gui/VdrManagerActivity.java
new file mode 100644
index 0000000..7543ad7
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/gui/VdrManagerActivity.java
@@ -0,0 +1,228 @@
+package de.bjusystems.vdrmanager.gui;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.AbsListView;
+import android.widget.ArrayAdapter;
+import android.widget.GridView;
+import android.widget.ImageButton;
+import android.widget.TextView;
+import de.bjusystems.vdrmanager.R;
+import de.bjusystems.vdrmanager.app.VdrManagerApp;
+import de.bjusystems.vdrmanager.data.MenuActionHandler;
+import de.bjusystems.vdrmanager.data.Preferences;
+import de.bjusystems.vdrmanager.utils.wakeup.AsyncWakeupTask;
+
+public class VdrManagerActivity extends Activity {
+
+ static class WakeupAction implements MenuActionHandler {
+ public void executeAction(final Context context) {
+ // create AsyncTask
+ final AsyncWakeupTask wakeupTask = new AsyncWakeupTask(context);
+ wakeupTask.execute();
+ }
+ }
+
+ @SuppressWarnings("rawtypes")
+ static class MenuActivity {
+ int iconId;
+ int textId;
+ Class handler;
+ boolean enabled;
+
+ public int getIconId() {
+ return iconId;
+ }
+ public int getTextId() {
+ return textId;
+ }
+
+ public Class getHandler() {
+ return handler;
+ }
+
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ public MenuActivity(final int iconId, final int textId, final Class handler) {
+ this.iconId = iconId;
+ this.textId = textId;
+ this.handler = handler;
+ this.enabled = true;
+ }
+
+ public void setEnabled(final boolean enabled) {
+ this.enabled = enabled;
+ }
+ }
+
+ class MenuAdapter extends ArrayAdapter<MenuActivity> implements OnClickListener {
+
+ private final LayoutInflater inflater;
+
+ public MenuAdapter(final Context context, final int viewId) {
+ super(context, viewId);
+ inflater = LayoutInflater.from(context);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public View getView(final int position, final View convertView, final ViewGroup parent) {
+
+ View view = convertView;
+ View itemView;
+ if (view == null) {
+ view = inflater.inflate(R.layout.vdrmanager_menu_item, null);
+ itemView = view.findViewById(R.id.vdrmanager_menu_item);
+ view.setTag(itemView);
+
+ // attach click listener
+ itemView.setOnClickListener(this);
+
+ } else {
+ itemView = (View) view.getTag();
+ }
+
+ // attach menu item
+ final MenuActivity menuItem = getItem(position);
+ if (itemView instanceof TextView) {
+ final TextView textView = (TextView) itemView;
+ textView.setText(menuItem.getTextId());
+ } else {
+ final ImageButton imageButton = (ImageButton) itemView;
+ imageButton.setImageResource(menuItem.getIconId());
+ }
+ itemView.setOnClickListener(this);
+ menuActivityMap.put(itemView, menuItem.getHandler());
+
+ return view;
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public void onClick(final View v) {
+
+ // refresh preferences
+ Preferences.loadPreferences(getContext());
+
+ // clear state
+ ((VdrManagerApp) getApplication()).clear();
+
+ // start activity
+ final Class actionClass = menuActivityMap.get(v);
+ if (Activity.class.isAssignableFrom(actionClass)) {
+ final Intent intent = new Intent();
+ intent.setClass(getContext(), actionClass);
+ startActivity(intent);
+ } else if (MenuActionHandler.class.isAssignableFrom(actionClass)) {
+ final Class<? extends MenuActionHandler> handlerClass = actionClass;
+ try {
+ final MenuActionHandler handler = handlerClass.newInstance();
+ handler.executeAction(getContext());
+ } catch (final InstantiationException e) {
+
+ } catch (final IllegalAccessException e) {
+
+ }
+ }
+ }
+ }
+
+ MenuActivity[] menuItems = new MenuActivity[] {
+ new MenuActivity(R.drawable.whatson, R.string.action_menu_epg, EpgListActivity.class),
+ new MenuActivity(0, R.string.action_menu_search, EpgSearchActivity.class),
+ new MenuActivity(R.drawable.timers, R.string.action_menu_timers, TimerListActivity.class),
+ new MenuActivity(R.drawable.channels, R.string.action_menu_channels, ChannelListActivity.class),
+ new MenuActivity(0, R.string.action_menu_wakeup, WakeupAction.class),
+ };
+ Map<View, Class<? extends Activity>> menuActivityMap = new HashMap<View, Class<? extends Activity>>();
+
+ @Override
+ protected void onCreate(final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // attach view
+ setContentView(R.layout.vdrmanager);
+
+ // add and register buttons
+ createButtons();
+ }
+
+ // add main menu buttons
+ private void createButtons() {
+
+ // refresh preferences
+ Preferences.loadPreferences(this);
+ final Preferences prefs = Preferences.getPreferences();
+
+ // get list
+ final AbsListView listView = (AbsListView) findViewById(R.id.vdrmanager_menu);
+ final MenuAdapter adapter = new MenuAdapter(this, R.layout.vdrmanager_menu_item);
+ listView.setAdapter(adapter);
+
+ // add menu items
+ for(final MenuActivity menuItem : menuItems) {
+ if (menuItem.getTextId() != R.string.action_menu_wakeup || prefs.isWakeupEnabled()) {
+ adapter.add(menuItem);
+ }
+ }
+
+ // set grid layout dimensions
+ if (listView instanceof GridView) {
+ final GridView grid = (GridView)listView;
+ if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
+ grid.setNumColumns(2);
+ } else {
+ grid.setNumColumns(menuItems.length);
+ }
+ }
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(final Menu menu) {
+ super.onCreateOptionsMenu(menu);
+
+ final MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.main_menu, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(final MenuItem item) {
+
+ switch (item.getItemId())
+ {
+ case R.id.main_menu_preferences:
+ // remember activity for finishing
+ final VdrManagerApp app = (VdrManagerApp) getApplication();
+ app.clearActivitiesToFinish();
+ app.addActivityToFinish(this);
+
+ final Intent intent = new Intent();
+ intent.setClass(this, PreferencesActivity.class);
+ startActivity(intent);
+ break;
+ case R.id.main_menu_exit:
+ finish();
+ break;
+ }
+ return true;
+ }
+
+ @Override
+ public void onBackPressed() {
+ }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/gui/VideoActivity.java b/vdrmanager/src/de/bjusystems/vdrmanager/gui/VideoActivity.java
new file mode 100644
index 0000000..6e17d15
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/gui/VideoActivity.java
@@ -0,0 +1,67 @@
+package de.bjusystems.vdrmanager.gui;
+
+import android.app.Activity;
+import android.net.Uri;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.MediaController;
+import android.widget.VideoView;
+import de.bjusystems.vdrmanager.R;
+import de.bjusystems.vdrmanager.data.Preferences;
+
+/**
+ * This class is used for showing what's
+ * current running on all channels
+ * @author bju
+ */
+public class VideoActivity extends Activity
+ implements OnClickListener {
+
+ Preferences prefs;
+
+ @Override
+ protected void onCreate(final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Attach view
+ setContentView(R.layout.video);
+
+ // set stream
+ final VideoView videoView = (VideoView) findViewById(R.id.video_video);
+ final MediaController mediaController = new MediaController(this);
+ mediaController.setAnchorView(videoView);
+ final Uri video = Uri.parse("http://192.168.178.20:3000/1");
+ videoView.setMediaController(mediaController);
+ videoView.setVideoURI(video);
+ videoView.start();
+
+ // register button
+ final Button button = (Button) findViewById(R.id.video_button);
+ button.setOnClickListener(this);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ }
+
+ public void onClick(final View v) {
+
+ // Save search parameters
+// final EpgSearchParams search = new EpgSearchParams();
+// search.setTitle(text.getText().toString());
+// ((VdrManagerApp)getApplication()).setCurrentSearch(search);
+
+ // show timer details
+// final Intent intent = new Intent();
+// intent.setClass(this, VdrManagerActivity.class);
+// startActivity(intent);
+ }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/tasks/AsyncProgressTask.java b/vdrmanager/src/de/bjusystems/vdrmanager/tasks/AsyncProgressTask.java
new file mode 100644
index 0000000..edd1367
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/tasks/AsyncProgressTask.java
@@ -0,0 +1,55 @@
+package de.bjusystems.vdrmanager.tasks;
+
+import android.app.Activity;
+import de.bjusystems.vdrmanager.gui.SvdrpProgressDialog;
+import de.bjusystems.vdrmanager.utils.svdrp.SvdrpAsyncListener;
+import de.bjusystems.vdrmanager.utils.svdrp.SvdrpAsyncTask;
+import de.bjusystems.vdrmanager.utils.svdrp.SvdrpClient;
+import de.bjusystems.vdrmanager.utils.svdrp.SvdrpEvent;
+
+public abstract class AsyncProgressTask<Result> {
+
+ class AsyncProgress extends SvdrpProgressDialog implements SvdrpAsyncListener<Result> {
+
+ public AsyncProgress(final Activity activity, final SvdrpClient<Result> client) {
+ super(activity, client);
+ }
+
+ public void svdrpEvent(final SvdrpEvent event, final Object result) {
+ svdrpEvent(event);
+
+ switch (event) {
+ case FINISHED:
+ AsyncProgressTask.this.finished();
+ break;
+ }
+ }
+ }
+
+ Activity activity;
+ SvdrpClient<Result> client;
+
+ public AsyncProgressTask(final Activity activity, final SvdrpClient<Result> client) {
+ this.activity = activity;
+ this.client = client;
+ }
+
+ public void start() {
+
+ // delete timer
+/*
+ final SetTimerClient client = new SetTimerClient(timer, true) {
+ @Override
+ public int getProgressTextId() {
+ return R.string.progress_timer_delete;
+ }
+ };
+*/
+ final SvdrpAsyncTask<Result, SvdrpClient<Result>> task = new SvdrpAsyncTask<Result, SvdrpClient<Result>>(client);
+ final AsyncProgress progress = new AsyncProgress(activity, client);
+ task.addListener(progress);
+ task.run();
+ }
+
+ public abstract void finished();
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/tasks/DeleteTimerTask.java b/vdrmanager/src/de/bjusystems/vdrmanager/tasks/DeleteTimerTask.java
new file mode 100644
index 0000000..48cdd23
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/tasks/DeleteTimerTask.java
@@ -0,0 +1,18 @@
+package de.bjusystems.vdrmanager.tasks;
+
+import android.app.Activity;
+import de.bjusystems.vdrmanager.R;
+import de.bjusystems.vdrmanager.data.Timer;
+import de.bjusystems.vdrmanager.utils.svdrp.SetTimerClient;
+
+public abstract class DeleteTimerTask extends AsyncProgressTask<Timer> {
+
+ public DeleteTimerTask(final Activity activity, final Timer timer) {
+ super(activity, new SetTimerClient(timer, true) {
+ @Override
+ public int getProgressTextId() {
+ return R.string.progress_timer_delete;
+ }
+ });
+ }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/tasks/ToggleTimerTask.java b/vdrmanager/src/de/bjusystems/vdrmanager/tasks/ToggleTimerTask.java
new file mode 100644
index 0000000..ee146e5
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/tasks/ToggleTimerTask.java
@@ -0,0 +1,25 @@
+package de.bjusystems.vdrmanager.tasks;
+
+import android.app.Activity;
+import de.bjusystems.vdrmanager.R;
+import de.bjusystems.vdrmanager.data.Timer;
+import de.bjusystems.vdrmanager.utils.svdrp.SetTimerClient;
+
+public abstract class ToggleTimerTask extends AsyncProgressTask<Timer> {
+
+ public ToggleTimerTask(final Activity activity, final Timer timer) {
+ super(activity, new SetTimerClient(timer, false) {
+ boolean enabled = timer.isEnabled();
+
+ @Override
+ public int getProgressTextId() {
+ if (enabled) {
+ return R.string.progress_timer_disable;
+ } else {
+ return R.string.progress_timer_enable;
+ }
+ }
+ });
+ timer.setEnabled(!timer.isEnabled());
+ }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/utils/date/DateFormatter.java b/vdrmanager/src/de/bjusystems/vdrmanager/utils/date/DateFormatter.java
new file mode 100644
index 0000000..30fd047
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/utils/date/DateFormatter.java
@@ -0,0 +1,43 @@
+package de.bjusystems.vdrmanager.utils.date;
+
+import java.text.DateFormat;
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * Class for formatting date and time values
+ * @author bju
+ *
+ */
+public class DateFormatter {
+
+ private final String timeString;
+ private final String dateString;
+ private final String dailyHeader;
+
+ public DateFormatter(final Date date) {
+ timeString = DateFormat.getTimeInstance(DateFormat.SHORT).format(date);
+ dateString = DateFormat.getDateInstance(DateFormat.SHORT).format(date);
+ dailyHeader = DateFormat.getDateInstance(DateFormat.FULL).format(date);
+ }
+
+ public DateFormatter(final long seconds) {
+ this(new Date(seconds * 1000));
+ }
+
+ public DateFormatter(final Calendar cal) {
+ this(cal.getTime());
+ }
+
+ public String getDateString() {
+ return dateString;
+ }
+
+ public String getTimeString() {
+ return timeString;
+ }
+
+ public String getDailyHeader() {
+ return dailyHeader;
+ }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/utils/http/HttpHelper.java b/vdrmanager/src/de/bjusystems/vdrmanager/utils/http/HttpHelper.java
new file mode 100644
index 0000000..0812f73
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/utils/http/HttpHelper.java
@@ -0,0 +1,263 @@
+package de.bjusystems.vdrmanager.utils.http;
+
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.zip.GZIPInputStream;
+
+import org.apache.http.Header;
+import org.apache.http.HeaderElement;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpException;
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpRequestInterceptor;
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpResponseInterceptor;
+import org.apache.http.HttpVersion;
+import org.apache.http.NameValuePair;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.ResponseHandler;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.methods.HttpRequestBase;
+import org.apache.http.conn.scheme.PlainSocketFactory;
+import org.apache.http.conn.scheme.Scheme;
+import org.apache.http.conn.scheme.SchemeRegistry;
+import org.apache.http.conn.ssl.SSLSocketFactory;
+import org.apache.http.entity.HttpEntityWrapper;
+import org.apache.http.impl.client.BasicResponseHandler;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.params.BasicHttpParams;
+import org.apache.http.params.CoreConnectionPNames;
+import org.apache.http.params.CoreProtocolPNames;
+import org.apache.http.params.HttpParams;
+import org.apache.http.protocol.HTTP;
+import org.apache.http.protocol.HttpContext;
+
+/**
+ * Apache HttpClient helper class for performing HTTP requests.
+ *
+ * This class is intentionally *not* bound to any Android classes so that it is easier
+ * to develop and test. Use calls to this class inside Android AsyncTask implementations
+ * (or manual Thread-Handlers) to make HTTP requests asynchronous and not block the UI Thread.
+ *
+ * TODO cookies
+ * TODO multi-part binary data
+ * TODO follow 302s?
+ * TODO shutdown connection mgr? - client.getConnectionManager().shutdown();
+ *
+ * @author ccollins
+ *
+ */
+public class HttpHelper {
+
+ private static final String CONTENT_TYPE = "Content-Type";
+ private static final int POST_TYPE = 1;
+ private static final int GET_TYPE = 2;
+ private static final String GZIP = "gzip";
+ private static final String ACCEPT_ENCODING = "Accept-Encoding";
+
+ public static final String MIME_FORM_ENCODED = "application/x-www-form-urlencoded";
+ public static final String MIME_TEXT_PLAIN = "text/plain";
+ public static final String HTTP_RESPONSE = "HTTP_RESPONSE";
+ public static final String HTTP_RESPONSE_ERROR = "HTTP_RESPONSE_ERROR";
+
+ private final DefaultHttpClient client;
+ private final ResponseHandler<String> responseHandler;
+
+ /**
+ * Constructor.
+ *
+ */
+ public HttpHelper() {
+
+ final HttpParams params = new BasicHttpParams();
+ params.setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
+ params.setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET, HTTP.UTF_8);
+ params.setParameter(CoreProtocolPNames.USER_AGENT, "Apache-HttpClient/Android");
+ params.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 15000);
+ params.setParameter(CoreConnectionPNames.STALE_CONNECTION_CHECK, false);
+ final SchemeRegistry schemeRegistry = new SchemeRegistry();
+ schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
+ schemeRegistry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));
+ final ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(params, schemeRegistry);
+ client = new DefaultHttpClient(cm, params);
+
+ // add gzip decompressor to handle gzipped content in responses
+ // (default we *do* always send accept encoding gzip header in request)
+ client.addResponseInterceptor(new HttpResponseInterceptor() {
+ public void process(final HttpResponse response, final HttpContext context) throws HttpException, IOException {
+ final HttpEntity entity = response.getEntity();
+ final Header contentEncodingHeader = entity.getContentEncoding();
+ if (contentEncodingHeader != null) {
+ final HeaderElement[] codecs = contentEncodingHeader.getElements();
+ for (int i = 0; i < codecs.length; i++) {
+ if (codecs[i].getName().equalsIgnoreCase(HttpHelper.GZIP)) {
+ response.setEntity(new GzipDecompressingEntity(response.getEntity()));
+ return;
+ }
+ }
+ }
+ }
+ });
+
+ responseHandler = new BasicResponseHandler();
+ }
+
+ /**
+ * Perform a simple HTTP GET operation.
+ *
+ */
+ public String performGet(final String url) {
+ return performRequest(null, url, null, null, null, null, HttpHelper.GET_TYPE);
+ }
+
+ /**
+ * Perform an HTTP GET operation with user/pass and headers.
+ *
+ */
+ public String performGet(final String url, final String user, final String pass,
+ final Map<String, String> additionalHeaders) {
+ return performRequest(null, url, user, pass, additionalHeaders, null, HttpHelper.GET_TYPE);
+ }
+
+ /**
+ * Perform a simplified HTTP POST operation.
+ *
+ */
+ public String performPost(final String url, final Map<String, String> params) {
+ return performRequest(HttpHelper.MIME_FORM_ENCODED, url, null, null, null, params, HttpHelper.POST_TYPE);
+ }
+
+ /**
+ * Perform an HTTP POST operation with user/pass, headers, request
+ parameters,
+ * and a default content-type of "application/x-www-form-urlencoded."
+ *
+ */
+ public String performPost(final String url, final String user, final String pass,
+ final Map<String, String> additionalHeaders, final Map<String, String> params) {
+ return performRequest(HttpHelper.MIME_FORM_ENCODED, url, user, pass, additionalHeaders, params,
+ HttpHelper.POST_TYPE);
+ }
+
+ /**
+ * Perform an HTTP POST operation with flexible parameters (the
+ complicated/flexible version of the method).
+ *
+ */
+ public String performPost(final String contentType, final String url, final String user, final String pass,
+ final Map<String, String> additionalHeaders, final Map<String, String> params) {
+ return performRequest(contentType, url, user, pass, additionalHeaders, params, HttpHelper.POST_TYPE);
+ }
+
+ //
+ // private methods
+ //
+ private String performRequest(final String contentType, final String url, final String user, final String pass,
+ final Map<String, String> headers, final Map<String, String> params, final int requestType) {
+
+ // add user and pass to client credentials if present
+ if ((user != null) && (pass != null)) {
+ client.getCredentialsProvider().setCredentials(AuthScope.ANY,
+ new UsernamePasswordCredentials(user, pass));
+ }
+
+ // process headers using request interceptor
+ final Map<String, String> sendHeaders = new HashMap<String, String>();
+ // add encoding header for gzip if not present
+ if (!sendHeaders.containsKey(HttpHelper.ACCEPT_ENCODING)) {
+ sendHeaders.put(HttpHelper.ACCEPT_ENCODING, HttpHelper.GZIP);
+ }
+ if ((headers != null) && (headers.size() > 0)) {
+ sendHeaders.putAll(headers);
+ }
+ if (requestType == HttpHelper.POST_TYPE) {
+ sendHeaders.put(HttpHelper.CONTENT_TYPE, contentType);
+ }
+ if (sendHeaders.size() > 0) {
+ client.addRequestInterceptor(new HttpRequestInterceptor() {
+ public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException {
+ for (final String key : sendHeaders.keySet()) {
+ if (!request.containsHeader(key)) {
+ request.addHeader(key, sendHeaders.get(key));
+ }
+ }
+ }
+ });
+ }
+
+ // handle POST or GET request respectively
+ HttpRequestBase method = null;
+ if (requestType == HttpHelper.POST_TYPE) {
+ method = new HttpPost(url);
+ // data - name/value params
+ List<NameValuePair> nvps = null;
+ if ((params != null) && (params.size() > 0)) {
+ nvps = new ArrayList<NameValuePair>();
+ for (final Map.Entry<String, String> entry : params.entrySet()) {
+ nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
+ }
+ }
+ if (nvps != null) {
+ try {
+ final HttpPost methodPost = (HttpPost) method;
+ methodPost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
+ } catch (final UnsupportedEncodingException e) {
+ throw new RuntimeException("Error peforming HTTP request: " + e.getMessage(), e);
+ }
+ }
+ } else if (requestType == HttpHelper.GET_TYPE) {
+ method = new HttpGet(url);
+ }
+
+
+ // execute request
+ return execute(method);
+ }
+
+ private synchronized String execute(final HttpRequestBase method) {
+ String response = null;
+ // execute method returns?!? (rather than async) - do it here sync, and wrap async elsewhere
+ try {
+ response = client.execute(method, responseHandler);
+ } catch (final ClientProtocolException e) {
+ response = HttpHelper.HTTP_RESPONSE_ERROR + " - " + e.getClass().getSimpleName() + " " + e.getMessage();
+ //e.printStackTrace();
+ } catch (final IOException e) {
+ response = HttpHelper.HTTP_RESPONSE_ERROR + " - " + e.getClass().getSimpleName() + " " + e.getMessage();
+ //e.printStackTrace();
+ }
+ return response;
+ }
+
+ static class GzipDecompressingEntity extends HttpEntityWrapper {
+ public GzipDecompressingEntity(final HttpEntity entity) {
+ super(entity);
+ }
+
+ @Override
+ public InputStream getContent() throws IOException, IllegalStateException {
+ // the wrapped entity's getContent() decides about repeatability
+ final InputStream wrappedin = wrappedEntity.getContent();
+ return new GZIPInputStream(wrappedin);
+ }
+
+ @Override
+ public long getContentLength() {
+ // length of ungzipped content is not known
+ return -1;
+ }
+ }
+}
+
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/AliveClient.java b/vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/AliveClient.java
new file mode 100644
index 0000000..f8372e9
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/AliveClient.java
@@ -0,0 +1,49 @@
+package de.bjusystems.vdrmanager.utils.svdrp;
+
+import de.bjusystems.vdrmanager.data.AliveState;
+
+/**
+ * Class for retrieving informations about the running program
+ * @author bju
+ *
+ */
+public class AliveClient extends SvdrpClient<AliveState> {
+
+ /**
+ * Constructor
+ * @param host host
+ * @param port port
+ * @param ssl use ssl
+ */
+ public AliveClient() {
+ super();
+ }
+
+ /**
+ * Starts the EPG request
+ * @param parameter parameter for lste
+ */
+ @Override
+ public void run() throws SvdrpException {
+ runCommand("aliv");
+ }
+
+ @Override
+ public AliveState parseAnswer(final String line) {
+
+ if (line.startsWith("200")) {
+ return AliveState.ALIVE;
+ }
+ if (line.startsWith("400")) {
+ return AliveState.DEAD;
+ }
+ return AliveState.UNKNOWN;
+ }
+
+ @Override
+ public int getProgressTextId() {
+ return 0;
+ }
+
+
+} \ No newline at end of file
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/ChannelClient.java b/vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/ChannelClient.java
new file mode 100644
index 0000000..c087358
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/ChannelClient.java
@@ -0,0 +1,44 @@
+package de.bjusystems.vdrmanager.utils.svdrp;
+
+import de.bjusystems.vdrmanager.R;
+import de.bjusystems.vdrmanager.data.Channel;
+import de.bjusystems.vdrmanager.data.Preferences;
+
+/**
+ * Class for retrieving informations about the running program
+ * @author bju
+ *
+ */
+public class ChannelClient extends SvdrpClient<Channel> {
+
+ /**
+ * Constructor
+ * @param host host
+ * @param port port
+ * @param ssl use ssl
+ */
+ public ChannelClient() {
+ super();
+ }
+
+ /**
+ * Starts the EPG request
+ * @param parameter parameter for lste
+ */
+ @Override
+ public void run() throws SvdrpException {
+ runCommand("channels " + Preferences.getPreferences().getChannels());
+ }
+
+ @Override
+ public Channel parseAnswer(final String line) {
+ return new Channel(line);
+ }
+
+ @Override
+ public int getProgressTextId() {
+ return R.string.progress_channels_loading;
+ }
+
+
+} \ No newline at end of file
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/EpgClient.java b/vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/EpgClient.java
new file mode 100644
index 0000000..df30055
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/EpgClient.java
@@ -0,0 +1,91 @@
+package de.bjusystems.vdrmanager.utils.svdrp;
+
+import de.bjusystems.vdrmanager.R;
+import de.bjusystems.vdrmanager.data.Channel;
+import de.bjusystems.vdrmanager.data.Epg;
+import de.bjusystems.vdrmanager.data.EpgSearchParams;
+import de.bjusystems.vdrmanager.data.Preferences;
+import de.bjusystems.vdrmanager.data.Timer;
+
+/**
+ * Class for retrieving informations about the running program
+ * @author bju
+ *
+ */
+public class EpgClient extends SvdrpClient<Epg> {
+
+ /** Time to retrieve EPG for */
+ private String time;
+ /** Channel to retrieve EPG for */
+ private Channel channel;
+ /** Search parameters to retrieve EPG for */
+ private EpgSearchParams search;
+ /** Last read EPG */
+ private Epg lastEpg;
+
+ /**
+ * Constructor
+ */
+ private EpgClient() {
+ super();
+ this.time = null;
+ this.channel = null;
+ this.search = null;
+ }
+
+ /**
+ * Constructor
+ * @param time time to search for epg events
+ */
+ public EpgClient(final String time) {
+ this();
+ this.time = time;
+ }
+
+ /**
+ * Constructor
+ * @param channel channel to search for epg events
+ */
+ public EpgClient(final Channel channel) {
+ this();
+ this.channel = channel;
+ }
+
+ public EpgClient(final EpgSearchParams search) {
+ this();
+ this.search = search;
+ }
+
+ /**
+ * Starts the EPG request
+ * @param parameter parameter for lste
+ */
+ @Override
+ public void run() throws SvdrpException {
+ if (time != null) {
+ runCommand(String.format("tevents %s %s", time, Preferences.getPreferences().getChannels()));
+ } else if (channel != null) {
+ runCommand(String.format("cevents %s", channel.getNumber()));
+ } else if (search != null) {
+ runCommand(String.format("search %s %s", Preferences.getPreferences().getChannels(), search.toCommandLine()));
+ }
+ }
+
+ @Override
+ public Epg parseAnswer(final String line) {
+
+ if (line.startsWith("E")) {
+ lastEpg = new Epg(line);
+ return lastEpg;
+ } else if (line.startsWith("T")) {
+ lastEpg.setTimer(new Timer(line));
+ }
+ return null;
+ }
+
+ @Override
+ public int getProgressTextId() {
+ return R.string.progress_whatson_loading;
+ }
+}
+
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/SetTimerClient.java b/vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/SetTimerClient.java
new file mode 100644
index 0000000..0863c6d
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/SetTimerClient.java
@@ -0,0 +1,59 @@
+package de.bjusystems.vdrmanager.utils.svdrp;
+
+import de.bjusystems.vdrmanager.R;
+import de.bjusystems.vdrmanager.data.Timer;
+
+/**
+ * Class for retrieving informations about the running program
+ * @author bju
+ *
+ */
+public class SetTimerClient extends SvdrpClient<Timer> {
+
+ /** channel names for timer */
+ Timer timer;
+ /** timer should be deleted */
+ boolean deleteTimer;
+
+ /**
+ * Constructor
+ * @param host host
+ * @param port port
+ * @param ssl use ssl
+ */
+ public SetTimerClient(final Timer timer, final boolean deleteTimer) {
+ super();
+ this.timer = timer;
+ this.deleteTimer = deleteTimer;
+ }
+
+ /**
+ * Starts the request
+ */
+ @Override
+ public void run() throws SvdrpException {
+
+ final StringBuilder command = new StringBuilder();
+
+ command.append("timer ");
+ if (deleteTimer) {
+ command.append("-");
+ }
+ command.append(timer.getNumber());
+ command.append(" ");
+ command.append(timer.toCommandLine());
+
+ runCommand(command.toString());
+ }
+
+ @Override
+ public Timer parseAnswer(final String line) {
+ return new Timer(line);
+ }
+
+ @Override
+ public int getProgressTextId() {
+ return R.string.progress_timer_save;
+ }
+}
+
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/SvdrpAsyncListener.java b/vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/SvdrpAsyncListener.java
new file mode 100644
index 0000000..fc388bf
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/SvdrpAsyncListener.java
@@ -0,0 +1,7 @@
+package de.bjusystems.vdrmanager.utils.svdrp;
+
+public interface SvdrpAsyncListener<Result> extends SvdrpListener<Result> {
+
+ void svdrpException(SvdrpException exception);
+
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/SvdrpAsyncTask.java b/vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/SvdrpAsyncTask.java
new file mode 100644
index 0000000..7dc0097
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/SvdrpAsyncTask.java
@@ -0,0 +1,61 @@
+package de.bjusystems.vdrmanager.utils.svdrp;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import android.os.AsyncTask;
+
+public class SvdrpAsyncTask<Result, Client extends SvdrpClient<Result>>
+ extends AsyncTask<Void, Object, Void>
+ implements SvdrpListener<Result> {
+
+ Client client;
+ List<SvdrpAsyncListener<Result>> listeners = new ArrayList<SvdrpAsyncListener<Result>>();
+
+ public SvdrpAsyncTask(final Client client) {
+ this.client = client;
+ client.addSvdrpListener(this);
+ }
+
+ public void addListener(final SvdrpAsyncListener<Result> listener) {
+ listeners.add(listener);
+ }
+
+ public void removeListener(final SvdrpAsyncListener<Result> listener) {
+ listeners.remove(listener);
+ }
+
+ public void run() {
+ execute();
+ }
+
+ @Override
+ protected Void doInBackground(final Void... params) {
+ try {
+ client.run();
+ } catch (final SvdrpException e) {
+ publishProgress(null, null, e);
+ }
+ return null;
+ }
+
+ public void svdrpEvent(final SvdrpEvent event, final Result result) {
+ publishProgress(event, result, null);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ protected void onProgressUpdate(final Object... values) {
+ super.onProgressUpdate(values);
+
+ if (values[2] == null) {
+ for(final SvdrpAsyncListener<Result> listener : listeners) {
+ listener.svdrpEvent((SvdrpEvent)values[0], (Result)values[1]);
+ }
+ } else {
+ for(final SvdrpAsyncListener<Result> listener : listeners) {
+ listener.svdrpException((SvdrpException)values[2]);
+ }
+ }
+ }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/SvdrpClient.java b/vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/SvdrpClient.java
new file mode 100644
index 0000000..ffb8b7b
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/SvdrpClient.java
@@ -0,0 +1,271 @@
+package de.bjusystems.vdrmanager.utils.svdrp;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.util.ArrayList;
+import java.util.List;
+
+import de.bjusystems.vdrmanager.data.Preferences;
+
+
+/**
+ * Class for SVDRP communication
+ * @author bju
+ *
+ */
+public abstract class SvdrpClient<Result> {
+
+ /** Socket for connection to SVDRP */
+ private Socket socket;
+ /** Output stream for sending commands */
+ private OutputStream outputStream;
+ /** Input stream for reading answer lines */
+ private InputStream inputStream;
+ /** flag for stopping the current request */
+ private boolean abort;
+ /** listener */
+ private final List<SvdrpListener<Result>> listeners = new ArrayList<SvdrpListener<Result>>();
+ /** list of results */
+ private final List<Result> results = new ArrayList<Result>();
+ /** should the listener be informed about each received result */
+ private boolean resultInfoEnabled = false;
+
+ /**
+ * Parse received answer line
+ * @param line line
+ * @return received data object or null if not completed yet
+ */
+ protected abstract Result parseAnswer(String line);
+
+ public abstract int getProgressTextId();
+
+ public abstract void run() throws SvdrpException;
+
+ /**
+ * Constructor
+ * @param prefs Preferences
+ */
+ protected SvdrpClient() {
+ results.clear();
+ }
+
+ /**
+ * Remove all listeners
+ */
+ public void clearSvdrpListener() {
+ listeners.clear();
+ }
+
+ /**
+ * Adds the listener to the list of listeners
+ * @param listener listener
+ */
+ public void addSvdrpListener(final SvdrpListener<Result> listener) {
+ listeners.add(listener);
+ }
+
+ /**
+ * Removes the listener from the list of listeners
+ * @param listener listener
+ */
+ public void removeSvdrpListener(final SvdrpListener<Result> listener) {
+ listeners.remove(listener);
+ }
+
+ /**
+ * Cancel the current request
+ */
+ public void abort() {
+ abort = true;
+ }
+
+ /**
+ * Gets the list of results
+ * @return results
+ */
+ public List<Result> getResults() {
+ return results;
+ }
+
+ /**
+ * Connect to SVDRP
+ * @param host host
+ * @param port port
+ * @param ssl use SSL
+ * @throws IOException on errors
+ */
+ protected boolean connect() throws IOException {
+
+ final Preferences prefs = Preferences.getPreferences();
+
+ try {
+ // connect
+ informListener(SvdrpEvent.CONNECTING, null);
+ socket = new Socket(prefs.getSvdrpHost(), prefs.getSvdrpPort());
+ informListener(SvdrpEvent.CONNECTED, null);
+ } catch (final IOException e) {
+ informListener(SvdrpEvent.CONNECT_ERROR, null);
+ return false;
+ }
+
+ // create streams
+ outputStream = socket.getOutputStream();
+ inputStream = socket.getInputStream();
+
+ // password needed?
+ informListener(SvdrpEvent.LOGIN, null);
+ writeLine("passwd " + prefs.getPassword());
+ if (!readLine().startsWith("!OK")) {
+ informListener(SvdrpEvent.LOGIN_ERROR, null);
+ disconnect();
+ return false;
+ } else {
+ informListener(SvdrpEvent.LOGGED_IN, null);
+ }
+
+ return true;
+ }
+
+ /**
+ * Disconnect from SVDRP if connected
+ * @throws IOException on errors
+ */
+ protected void disconnect() throws IOException {
+ informListener(SvdrpEvent.DISCONNECTING, null);
+ if (socket != null && socket.isConnected()) {
+ socket.close();
+ socket = null;
+ }
+ informListener(SvdrpEvent.DISCONNECTED, null);
+ }
+
+ /**
+ * Sends one line to SVDRP
+ * @param line line of text
+ * @throws IOException on errors
+ */
+ protected void writeLine(final String line) throws IOException {
+
+ final String command = line + "\r\n";
+ final byte[] bytes = command.getBytes();
+ outputStream.write(bytes);
+ outputStream.flush();
+ }
+
+ /**
+ * Reads one line from SVDRP
+ * @return line read
+ * @throws IOException on errors
+ */
+ protected String readLine() throws IOException {
+
+ // handle not gzipped input
+ final ByteArrayOutputStream lineBytes = new ByteArrayOutputStream();
+
+ for(;;) {
+
+ // read next char
+ final int d = inputStream.read();
+ if (d < 0) {
+ break;
+ }
+ final char c = (char)d;
+
+ // skip '\r'
+ if (c == '\r') {
+ continue;
+ }
+
+ // with '\n' the line is completed
+ if (c == '\n') {
+ break;
+ }
+
+ // remember char
+ lineBytes.write(c);
+ }
+
+ return lineBytes.toString();
+ }
+
+ public void runCommand(final String command) throws SvdrpException {
+
+ try {
+
+ // reset cancel flag
+ abort = false;
+
+ // clear results
+ results.clear();
+
+ // connect
+ final boolean connected = connect();
+ if (!connected) {
+ return;
+ }
+
+ // send command
+ informListener(SvdrpEvent.COMMAND_SENDING, null);
+ writeLine(command);
+ informListener(SvdrpEvent.COMMAND_SENT, null);
+
+ // read first line
+ String line = readLine();
+ if (!line.startsWith("START")) {
+ throw new IOException("Answer not wellformed");
+ }
+
+ // read answer lines
+ for(;!abort;) {
+
+ // get next line
+ line = readLine();
+ if (line.length() == 0) {
+ break;
+ }
+
+ // last line?
+ if (line.startsWith("END")) {
+ break;
+ }
+
+ // error?
+ if (line.startsWith("!ERROR")) {
+ informListener(SvdrpEvent.ERROR, null);
+ break;
+ }
+
+ // delegate analysis
+ final Result result = parseAnswer(line);
+ if (result != null) {
+ results.add(result);
+ if (resultInfoEnabled) {
+ informListener(SvdrpEvent.RESULT_RECEIVED, result);
+ }
+ }
+
+ }
+
+ // disconnect
+ disconnect();
+
+ } catch (final IOException e) {
+ throw new SvdrpException(e);
+ } finally {
+ informListener(SvdrpEvent.FINISHED, null);
+ }
+ }
+
+ public void setResultInfoEnabled(final boolean resultInfoEnabled) {
+ this.resultInfoEnabled = resultInfoEnabled;
+ }
+
+ private void informListener(final SvdrpEvent event, final Result result) {
+ for(final SvdrpListener<Result> listener : listeners) {
+ listener.svdrpEvent(event, result);
+ }
+ }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/SvdrpEvent.java b/vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/SvdrpEvent.java
new file mode 100644
index 0000000..a807659
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/SvdrpEvent.java
@@ -0,0 +1,17 @@
+package de.bjusystems.vdrmanager.utils.svdrp;
+
+public enum SvdrpEvent {
+ CONNECTING,
+ CONNECTED,
+ CONNECT_ERROR,
+ LOGIN,
+ LOGGED_IN,
+ LOGIN_ERROR,
+ COMMAND_SENDING,
+ COMMAND_SENT,
+ RESULT_RECEIVED,
+ DISCONNECTING,
+ DISCONNECTED,
+ FINISHED,
+ ERROR
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/SvdrpException.java b/vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/SvdrpException.java
new file mode 100644
index 0000000..9c6d5e0
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/SvdrpException.java
@@ -0,0 +1,22 @@
+package de.bjusystems.vdrmanager.utils.svdrp;
+
+/**
+ * Class for exception caused by SVDRP errors
+ * @author bju
+ *
+ */
+@SuppressWarnings("serial")
+public class SvdrpException extends Exception {
+
+ public SvdrpException(String text) {
+ super(text);
+ }
+
+ public SvdrpException(String text, Throwable cause) {
+ super(text, cause);
+ }
+
+ public SvdrpException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/SvdrpListener.java b/vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/SvdrpListener.java
new file mode 100644
index 0000000..df8762b
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/SvdrpListener.java
@@ -0,0 +1,7 @@
+package de.bjusystems.vdrmanager.utils.svdrp;
+
+
+public interface SvdrpListener<Result>{
+
+ void svdrpEvent(SvdrpEvent event, Result result);
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/TimerClient.java b/vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/TimerClient.java
new file mode 100644
index 0000000..9d75421
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/TimerClient.java
@@ -0,0 +1,50 @@
+package de.bjusystems.vdrmanager.utils.svdrp;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import de.bjusystems.vdrmanager.R;
+import de.bjusystems.vdrmanager.data.Channel;
+import de.bjusystems.vdrmanager.data.Timer;
+
+/**
+ * Class for retrieving informations about the running program
+ * @author bju
+ *
+ */
+public class TimerClient extends SvdrpClient<Timer> {
+
+ /** channel names for timer */
+ Map<String, Channel> channels;
+
+ /**
+ * Constructor
+ * @param host host
+ * @param port port
+ * @param ssl use ssl
+ */
+ public TimerClient() {
+ super();
+ this.channels = new HashMap<String, Channel>();
+ }
+
+ /**
+ * Starts the EPG request
+ * @param parameter parameter for lste
+ */
+ @Override
+ public void run() throws SvdrpException {
+ runCommand("timers");
+ }
+
+ @Override
+ public Timer parseAnswer(final String line) {
+ return new Timer(line);
+ }
+
+ @Override
+ public int getProgressTextId() {
+ return R.string.progress_timers_loading;
+ }
+}
+
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/WakeupClient.java b/vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/WakeupClient.java
new file mode 100644
index 0000000..072861c
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/WakeupClient.java
@@ -0,0 +1,51 @@
+package de.bjusystems.vdrmanager.utils.svdrp;
+
+import de.bjusystems.vdrmanager.data.WakeupState;
+
+/**
+ * Class for retrieving informations about the running program
+ * @author bju
+ *
+ */
+public class WakeupClient extends SvdrpClient<WakeupState> {
+
+ private WakeupState state;
+
+ /**
+ * Constructor
+ */
+ public WakeupClient() {
+ super();
+ }
+
+ /**
+ * Starts the wakeup request
+ */
+ @Override
+ public void run() throws SvdrpException {
+ runCommand("wake");
+ }
+
+ @Override
+ public WakeupState parseAnswer(final String line) {
+
+ if (line.startsWith("200")) {
+ state = WakeupState.OK;
+ } else if (line.startsWith("400")) {
+ state = WakeupState.FAILED;
+ } else {
+ state = WakeupState.ERROR;
+ }
+ return state;
+ }
+
+ @Override
+ public int getProgressTextId() {
+ return 0;
+ }
+
+ public WakeupState getState() {
+ return state;
+ }
+
+} \ No newline at end of file
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/utils/wakeup/AsyncWakeupTask.java b/vdrmanager/src/de/bjusystems/vdrmanager/utils/wakeup/AsyncWakeupTask.java
new file mode 100644
index 0000000..2586b5c
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/utils/wakeup/AsyncWakeupTask.java
@@ -0,0 +1,84 @@
+package de.bjusystems.vdrmanager.utils.wakeup;
+
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.os.AsyncTask;
+import android.widget.Toast;
+import de.bjusystems.vdrmanager.R;
+import de.bjusystems.vdrmanager.data.Preferences;
+import de.bjusystems.vdrmanager.utils.http.HttpHelper;
+
+public class AsyncWakeupTask extends AsyncTask<Object, WakeupProgress, Void> {
+
+ /** Context */
+ private final Context context;
+ /** Progress dialog */
+ private ProgressDialog progressDialog;
+
+ public AsyncWakeupTask(final Context context) {
+ this.context = context;
+ }
+
+ @Override
+ protected Void doInBackground(final Object... params) {
+
+ // open progress dialog
+ publishProgress(WakeupProgress.WAKEUP_STARTED);
+
+ // Preferences
+ final Preferences prefs = Preferences.getPreferences();
+
+ boolean ok = false;
+ try {
+
+ // wakeup by http request
+ final HttpHelper httpHelper = new HttpHelper();
+ httpHelper.performGet(prefs.getWakeupUrl(), prefs.getWakeupUser(), prefs.getWakeupPassword(), null);
+ // request sent
+ ok = true;
+
+ } catch (final Exception e) {
+ }
+
+ // close progress
+ publishProgress(WakeupProgress.WAKEUP_FINISHED);
+
+ if (ok) {
+ publishProgress(WakeupProgress.WAKEUP_OK);
+ } else {
+ publishProgress(WakeupProgress.WAKEUP_ERROR);
+ }
+
+ return null;
+ }
+
+ @Override
+ protected void onProgressUpdate(final WakeupProgress... values) {
+ super.onProgressUpdate(values);
+
+ switch (values[0]) {
+ case WAKEUP_STARTED:
+ final CharSequence message = context.getText(R.string.progress_wakeup_sending);
+ progressDialog = ProgressDialog.show(context, "", message);
+ break;
+ case WAKEUP_FINISHED:
+ progressDialog.dismiss();
+ break;
+ case WAKEUP_OK:
+ showToast(R.string.progress_wakeup_sent);
+ break;
+ case WAKEUP_ERROR:
+ showToast(R.string.progress_wakeup_error);
+ break;
+ }
+ }
+
+ private void showToast(final int textId) {
+
+ final CharSequence text = context.getText(textId);
+ final int duration = Toast.LENGTH_SHORT;
+ final Toast toast = Toast.makeText(context, text, duration);
+ toast.show();
+ }
+
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/utils/wakeup/WakeupProgress.java b/vdrmanager/src/de/bjusystems/vdrmanager/utils/wakeup/WakeupProgress.java
new file mode 100644
index 0000000..46838dc
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/utils/wakeup/WakeupProgress.java
@@ -0,0 +1,8 @@
+package de.bjusystems.vdrmanager.utils.wakeup;
+
+public enum WakeupProgress {
+ WAKEUP_STARTED,
+ WAKEUP_OK,
+ WAKEUP_ERROR,
+ WAKEUP_FINISHED
+}