summaryrefslogtreecommitdiff
path: root/browse.c
diff options
context:
space:
mode:
authorJoerg Bornkessel <hd_brummy@gentoo.org>2014-04-26 19:15:40 +0200
committerJoerg Bornkessel <hd_brummy@gentoo.org>2014-04-26 19:15:40 +0200
commitd45bc4bed686d1d0c2daff22a66dfa0394fde4fb (patch)
tree75b7a38c993c0c5761764a375fa822190729a402 /browse.c
parent99628e3cec79c4b5888056ce4be3b92a38eddf47 (diff)
downloadvdr-plugin-audiorecorder-d45bc4bed686d1d0c2daff22a66dfa0394fde4fb.tar.gz
vdr-plugin-audiorecorder-d45bc4bed686d1d0c2daff22a66dfa0394fde4fb.tar.bz2
initial commit
Diffstat (limited to 'browse.c')
-rw-r--r--browse.c638
1 files changed, 638 insertions, 0 deletions
diff --git a/browse.c b/browse.c
new file mode 100644
index 0000000..0e7bac3
--- /dev/null
+++ b/browse.c
@@ -0,0 +1,638 @@
+/*
+ * browse.c
+ */
+
+#include "browse.h"
+#include "cache.h"
+#include "external-player.h"
+#include "audiorecorder.h"
+#include "setup.h"
+
+#include <vdr/skins.h>
+#include <vdr/interface.h>
+#include <vdr/tools.h>
+
+#include <sstream>
+
+
+#define MAXCOLS 5
+#define TAB_LEN 3
+#define SERVICE "MP3-Play-v1"
+
+using namespace std;
+
+/* --- cBrowse -------------------------------------------------------------- */
+
+cBrowse::cBrowse(void)
+:cOsdMenu("")
+{
+ num_columns = MAXCOLS;
+ columns = NULL;
+ columns = new cColumn[num_columns + 1];
+
+ player = cPluginManager::CallFirstService(SERVICE);
+
+ string skin = Skins.Current()->Name();
+ width = DisplayMenu()->EditableWidth();
+
+ if (skin != "curses")
+ width /= 12;
+
+ dsyslog("[audiorecorder]: skin %s (width %d) detected (%s, %s())",
+ skin.c_str(), width, __FILE__, __func__);
+
+ set_view(SetupValues.default_view);
+}
+
+
+cBrowse::~cBrowse()
+{
+ delete[] columns;
+}
+
+
+eOSState cBrowse::ProcessKey(eKeys key)
+{
+ eOSState state = cOsdMenu::ProcessKey(key);
+
+ if (HasSubMenu()) {
+ process_submenu_states(state);
+
+ if (state == osBack || key == kBlue || key == kOk)
+ CloseSubMenu();
+
+ return osContinue;
+ }
+
+ set_status();
+ set_help_keys();
+
+ cBrowseItem *item = get_actual_item();
+
+ switch (key) {
+ case kRed:
+ if (! item)
+ break;
+
+ if (item->is_node())
+ AddSubMenu(new cBrowseAction(true,
+ get_category(item)));
+ else
+ AddSubMenu(new cBrowseAction(false,
+ get_trackname(item->get_track())));
+
+ break;
+ case kGreen:
+ if (help_green.empty())
+ break;
+
+ expand ? expand = false : expand = true;
+ set_view(view, false);
+
+ break;
+ case kYellow:
+ set_view(++view);
+
+ break;
+ case kBlue:
+ if (item && ! item->is_node())
+ AddSubMenu(new cBrowseInfo(item->get_track()));
+
+ break;
+ case kOk:
+ if (! item)
+ break;
+
+ if (! item->is_node())
+ play_file(item->get_track());
+ else if (item->is_closed()) {
+ item->toggle_node();
+ insert_items();
+ }
+ else {
+ item->toggle_node();
+ delete_items();
+ }
+ break;
+ default:
+ break;
+ }
+
+ return state;
+}
+
+
+void cBrowse::set_view(int _view, bool init)
+{
+ view = _view;
+
+ if (view == 1) {
+ /* view by artist */
+ num_columns = 2;
+
+ columns[0].set(colArtist, TAB_LEN);
+ columns[1].set(colTitle, width - TAB_LEN);
+ columns[2].set(colEnd);
+
+ if (init)
+ expand = false;
+
+ help_yellow = views[2];
+ }
+ else if (view == 2) {
+ /* view by channel */
+ num_columns = 3;
+
+ columns[0].set(colChannel, TAB_LEN);
+ columns[1].set(colEvent, TAB_LEN);
+ columns[2].set(colArtistTitle, width - 2 * TAB_LEN);
+ columns[3].set(colEnd);
+
+ if (init)
+ expand = false;
+
+ help_yellow = views[3];
+ }
+ else if (view == 3) {
+ /* view by date */
+ num_columns = 2;
+
+ columns[0].set(colDate, TAB_LEN);
+ columns[1].set(colTime, 6, true);
+ columns[2].set(colChannel, 11, true, true);
+ columns[3].set(colArtistTitle, width - TAB_LEN - 17);
+ columns[4].set(colEnd);
+
+ if (init)
+ expand = true;
+
+ help_yellow = views[0];
+ }
+ else {
+ /* all */
+ view = 0;
+ num_columns = 1;
+
+ columns[0].set(colArtistTitle, width);
+ columns[1].set(colEnd);
+
+ if (init)
+ expand = true;
+
+ help_yellow = views[1];
+ }
+
+ if (init) {
+ SetCols(columns[0].get_width(), columns[1].get_width(),
+ columns[2].get_width(), columns[3].get_width(),
+ columns[4].get_width());
+
+ Cache.sort(columns);
+ }
+
+ Clear();
+ insert_items();
+
+ set_status();
+ set_help_keys();
+ set_title();
+}
+
+
+void cBrowse::set_help_keys(void)
+{
+ /* green key */
+ if (view == 0)
+ help_green.erase();
+ else if (expand)
+ help_green = tr("collapse all");
+ else
+ help_green = tr("expand all");
+
+ cBrowseItem *item = get_actual_item();
+
+ SetHelp(tr("action"), (help_green.empty() ? NULL : help_green.c_str()) ,
+ help_yellow, (item && ! item->is_node() ? "info" : NULL));
+}
+
+
+void cBrowse::set_status(void)
+{
+ /* disable status for the skin sttng: */
+ if (strcmp(Skins.Current()->Name(), "sttng") == 0)
+ return;
+
+ string status(views[view]);
+
+ cBrowseItem *item = get_actual_item();
+
+ if (item && item->get_main_item()) {
+ status.append(" ");
+ status.append(get_category(item));
+ }
+
+ cut_string(status, width);
+ SetStatus(status.c_str());
+}
+
+
+void cBrowse::set_title(void)
+{
+ stringstream title;
+ title << tr("Audiorecorder") << ", " << tr("Browse tracks") << " (" << Cache.get_num_cached()
+ << ")";
+
+ SetTitle(title.str().c_str());
+}
+
+
+void cBrowse::process_submenu_states(eOSState &state)
+{
+ cBrowseItem *item = get_actual_item();
+
+ switch(state) {
+ case osUser1:
+ play_all_files(item);
+ state = osBack;
+
+ break;
+ case osUser6:
+ if (item)
+ play_file(item->get_track());
+
+ state = osBack;
+
+ break;
+ default:
+ break;
+ }
+}
+
+
+cBrowseItem *cBrowse::get_actual_item(void)
+{
+ if (Current() < 0)
+ return NULL;
+
+ return (cBrowseItem *)Get(Current());
+}
+
+
+void cBrowse::insert_items(void)
+{
+ int pos = Current();
+
+ /* clean up old states */
+ for (int c = 0; c < num_columns; ++c) {
+ columns[c].set_main_item(NULL);
+ columns[c].del_last_entry();
+ }
+
+ int column = 0;
+ cBrowseItem *item = get_actual_item();
+ if (item && item->is_node()) {
+ set_filter(item);
+ column = item->get_column();
+ columns[column].set_main_item(item);
+ ++column;
+ }
+
+ int depth;
+ if (expand)
+ depth = num_columns;
+ else
+ depth = column + 1;
+
+ for (const cTrackInfo *track = Cache.get_next_track(true); track;
+ track = Cache.get_next_track()) {
+
+ if (filter_track(track))
+ continue;
+
+ for (int c = column; c < depth; ++c) {
+ eItemType type;
+
+ string entry = get_value_of_column(track, c);
+
+ if (c == num_columns - 1)
+ type = itemTrack;
+ else if (expand)
+ type = itemNodeOpen;
+ else
+ type = itemNodeClose;
+
+ /* don't show double nodes: */
+ if (type != itemTrack &&
+ entry == columns[c].get_last_entry())
+ continue;
+
+ columns[c].set_last_entry(entry);
+ for (int i = c + 1; i < num_columns; ++i)
+ columns[i].del_last_entry();
+
+ if (type == itemNodeOpen)
+ entry.insert(0, "[-] ");
+ else if (type == itemNodeClose)
+ entry.insert(0, "[+] ");
+
+ string indent(c, '\t');
+ entry.insert(0, indent);
+
+ cBrowseItem *item, *main = NULL;
+ if (c > 0)
+ main = columns[c - 1].get_main_item();
+
+ item = new cBrowseItem(main, track, c, type);
+ item->SetText(entry.c_str());
+ columns[c].set_main_item(item);
+
+ Add(item, true, Get(Current()));
+ }
+ }
+
+ SetCurrent(Get(pos));
+ Display();
+}
+
+
+void cBrowse::delete_items(void)
+{
+ cBrowseItem *item = get_actual_item();
+ if (! item || ! item->is_node())
+ return;
+
+ for (int c = 0; c < item->get_items(); ++c)
+ Del(Current() + 1);
+
+ item->delete_items(item->get_items());
+
+ Display();
+}
+
+
+void cBrowse::set_filter(const cBrowseItem *item)
+{
+ for (int c = 0; c < num_columns; ++c) {
+ string filter("");
+ if (c <= item->get_column())
+ filter = get_value_of_column(item->get_track(), c);
+
+ columns[c].set_filter(filter);
+ }
+}
+
+
+bool cBrowse::filter_track(const cTrackInfo *track)
+{
+ for (int c = 0; c < num_columns; ++c) {
+
+ if (columns[c].get_filter().empty())
+ continue;
+
+ if (columns[c].get_filter() != get_value_of_column(track, c))
+ return true;
+ }
+
+ return false;
+}
+
+
+string cBrowse::get_category(const cBrowseItem *item)
+{
+ string category("");
+
+ if (item) {
+ int columns = item->get_column();
+
+ if (item->is_node())
+ ++columns;
+
+ for (int c = 0; c < columns; ++c) {
+ if (c != 0)
+ category.append("/");
+
+ category.append(get_value_of_column(item->get_track(),
+ c));
+ }
+ }
+
+ return category;
+}
+
+
+string cBrowse::get_trackname(const cTrackInfo *track)
+{
+ string trackstr("");
+
+ if (track) {
+ trackstr.append(track->get_artist());
+ trackstr.append(" - ");
+ trackstr.append(track->get_title());
+ }
+
+ return trackstr;
+}
+
+
+string cBrowse::get_value_of_column(const cTrackInfo *track, int c)
+{
+ string value("");
+ bool join = true;
+
+ while (join && columns[c].get_type() != colEnd) {
+ stringstream col_tmp;
+
+ switch (columns[c].get_type()) {
+ case colArtist:
+ col_tmp << track->get_artist();
+ break;
+ case colTitle:
+ col_tmp << track->get_title();
+ break;
+ case colArtistTitle:
+ col_tmp << track->get_artist() << " - "
+ << track->get_title();
+ break;
+ case colAlbum:
+ col_tmp << track->get_album();
+ break;
+ case colTrack:
+ col_tmp << track->get_track();
+ break;
+ case colYear:
+ col_tmp << track->get_year();
+ break;
+ case colGenre:
+ col_tmp << track->get_genre();
+ break;
+ case colChannel:
+ col_tmp << track->get_channel();
+ break;
+ case colEvent:
+ col_tmp << track->get_event();
+ break;
+ case colDate:
+ col_tmp << track->get_date();
+ break;
+ case colTime:
+ col_tmp << track->get_time();
+ break;
+ default:
+ break;
+ }
+
+ if (col_tmp.str().empty())
+ col_tmp << tr("unknown");
+
+ string col(col_tmp.str());
+
+ if (columns[c].get_cut())
+ cut_string(col, columns[c].get_width() - 1);
+
+ value.append(col);
+
+ join = columns[c].is_joined();
+ if (join)
+ value.append("\t");
+
+ ++c;
+ }
+
+ return value;
+}
+
+
+void cBrowse::play_all_files(const cBrowseItem *node)
+{
+ if (! player) {
+ Skins.Message(mtError, tr("No external player-plugin found"), 2);
+ return;
+ }
+
+ if (! node || ! node->is_node())
+ return;
+
+ set_filter(node);
+
+ string status = tr("Playing all tracks in ");
+ status.append(get_category(node));
+ cut_string(status, width);
+ SetStatus(status.c_str());
+
+ for (const cTrackInfo *track = Cache.get_next_track(true); track;
+ track = Cache.get_next_track()) {
+
+ if (! filter_track(track))
+ play_file(track, false);
+ }
+}
+
+
+void cBrowse::play_file(const cTrackInfo *track, bool set_status)
+{
+ if (! player) {
+ Skins.Message(mtError, tr("No external player-plugin found"), 2);
+ return;
+ }
+
+ MP3ServiceData data;
+ data.data.filename = track->get_path().c_str();
+ data.result = 0;
+
+#ifndef AUDIORECORDER_DEVEL
+ player->Service(SERVICE, &data);
+
+ if (data.result == 0) {
+ dsyslog("[audiorecorder]: plugin %s could not play the file "
+ "%s (%s, %s())", player->Name(),
+ track->get_path().c_str(), __FILE__, __func__);
+ return;
+ }
+#endif /* AUDIORECORDER_DEVEL */
+
+ if (set_status) {
+ string status = tr("Playing ");
+ status.append(get_trackname(track));
+ cut_string(status, width);
+ SetStatus(status.c_str());
+ }
+}
+
+
+void cBrowse::cut_string(string &cut, int length)
+{
+ if ((int)cut.length() > length) {
+ cut.erase(length - 1);
+ cut.append("~");
+ }
+}
+
+
+/* --- cBrowseAction -------------------------------------------------------- */
+
+cBrowseAction::cBrowseAction(bool node, const string &text)
+:cOsdMenu(tr("Audiorecorder, Action"))
+{
+ string status("");
+ if (node) {
+ status.append(tr("Category : "));
+ status.append(text);
+ Add(new cOsdItem(tr("Play all tracks"), osUser1));
+ Add(new cOsdItem(tr("More to come ..."), osUser7));
+ }
+ else {
+ status.append(tr("Track: "));
+ status.append(text);
+ Add(new cOsdItem(tr("Play track"), osUser6));
+ Add(new cOsdItem(tr("More to come ..."), osUser7));
+ }
+
+ SetStatus(status.c_str());
+ SetHelp(NULL, NULL, NULL, tr("back"));
+}
+
+
+/* --- cBrowseInfo ---------------------------------------------------------- */
+
+cBrowseInfo::cBrowseInfo(const cTrackInfo *track)
+:cOsdMenu(tr("Audiorecorder, Info"), 11)
+{
+ string path = track->get_path();
+ path.erase(0, cPluginAudiorecorder::get_recdir().length());
+ Add(add_item(tr("File"), path));
+
+ Add(add_item(tr("Artist"), track->get_artist()));
+ Add(add_item(tr("Title"), track->get_title()));
+ Add(add_item(tr("Album"), track->get_album()));
+ Add(add_item(tr("Genre"), track->get_genre()));
+
+ stringstream tmp;
+ tmp << track->get_track();
+ Add(add_item(tr("Track"), tmp.str()));
+
+ tmp.str("");
+ tmp.clear();
+ tmp << track->get_year();
+ Add(add_item(tr("Year"), tmp.str()));
+
+ Add(add_item(tr("Channel"), track->get_channel()));
+ Add(add_item(tr("Event"), track->get_event()));
+ Add(add_item(tr("Date"), track->get_date()));
+ Add(add_item(tr("Time"), track->get_time()));
+
+ SetHelp(NULL, NULL, NULL, tr("back"));
+}
+
+
+cOsdItem *cBrowseInfo::add_item(const char *type, const string &text)
+{
+ string txt = type;
+ txt.append(":\t");
+
+ if (text.empty() || text == "0")
+ txt.append(tr("unknown"));
+ else
+ txt.append(text);
+
+ return new cOsdItem(txt.c_str(), osUnknown, false);
+}