xaizek / pms (License: GPLv3+) (since 2018-12-07)
Older version of Practical Music Search written in C++.
Commit 21d968dfe5a3e92f44678110e43f70bd782fbde2

Whitespace: never use tabs.
Author: Kim Tore Jensen
Author date (UTC): 2014-09-28 14:28
Committer name: Kim Tore Jensen
Committer date (UTC): 2014-09-28 14:29
Parent(s): 6ca195c0e2246e4c70fb2e41e056d2f7a8bc1299
Signing key:
Tree: 20dda722993241e9e8d4bc35ea88491f9bce4014
File Lines added Lines deleted
src/console.c 85 85
src/console.h 5 5
src/curses.c 39 39
src/curses.h 7 7
src/input.c 9 9
src/input.h 1 1
src/pms.c 176 176
src/pms.h 3 3
src/topbar.c 1 1
src/topbar.h 1 1
src/window.c 23 23
src/window.h 7 7
File src/console.c changed (mode: 100644) (index 3431e0b..7fcf19c)
1 /* vi:set ts=4 sts=4 sw=4 noet:
1 /* vi:set ts=4 sts=4 sw=4 et:
2 2 * *
3 3 * Practical Music Search * Practical Music Search
4 4 * Copyright (c) 2006-2014 Kim Tore Jensen * Copyright (c) 2006-2014 Kim Tore Jensen
 
... ... pthread_mutex_t console_mutex = PTHREAD_MUTEX_INITIALIZER;
35 35 window_t * console_window = NULL; window_t * console_window = NULL;
36 36
37 37 void console_resize() { void console_resize() {
38 console_window->height = LINES - 2;
39 console_window->position = 0;
40 console_window->num_lines = 0;
38 console_window->height = LINES - 2;
39 console_window->position = 0;
40 console_window->num_lines = 0;
41 41 } }
42 42
43 43 void console_init(unsigned int max_lines) { void console_init(unsigned int max_lines) {
44 if (lines != NULL) {
45 lines = realloc(lines, max_lines * sizeof(logline_t *));
46 } else {
47 lines = malloc(max_lines * sizeof(logline_t *));
48 }
49 if (lines == NULL) {
50 fatal(PMS_EXIT_MEMORY, "out of memory\n");
51 }
52 if (console_window == NULL) {
53 console_window = malloc(sizeof(window_t));
54 if (console_window == NULL) {
55 fatal(PMS_EXIT_MEMORY, "out of memory\n");
56 }
57 console_resize();
58 }
59 memset(lines+line_limit, 0, (max_lines-line_limit)*sizeof(logline_t *));
60 line_limit = max_lines;
44 if (lines != NULL) {
45 lines = realloc(lines, max_lines * sizeof(logline_t *));
46 } else {
47 lines = malloc(max_lines * sizeof(logline_t *));
48 }
49 if (lines == NULL) {
50 fatal(PMS_EXIT_MEMORY, "out of memory\n");
51 }
52 if (console_window == NULL) {
53 console_window = malloc(sizeof(window_t));
54 if (console_window == NULL) {
55 fatal(PMS_EXIT_MEMORY, "out of memory\n");
56 }
57 console_resize();
58 }
59 memset(lines+line_limit, 0, (max_lines-line_limit)*sizeof(logline_t *));
60 line_limit = max_lines;
61 61 } }
62 62
63 63 void console(const char * format, ...) { void console(const char * format, ...) {
64 logline_t * line;
65 time_t t;
66 va_list ap;
64 logline_t * line;
65 time_t t;
66 va_list ap;
67 67
68 pthread_mutex_lock(&console_mutex);
68 pthread_mutex_lock(&console_mutex);
69 69
70 line = new_logline();
70 line = new_logline();
71 71
72 va_start(ap, format);
73 vsnprintf(line->str, 512, format, ap);
74 va_end(ap);
72 va_start(ap, format);
73 vsnprintf(line->str, 512, format, ap);
74 va_end(ap);
75 75
76 if (lines[line_cursor] != NULL) {
77 free_logline(lines[line_cursor]);
78 }
76 if (lines[line_cursor] != NULL) {
77 free_logline(lines[line_cursor]);
78 }
79 79
80 ++console_window->num_lines;
80 ++console_window->num_lines;
81 81
82 t = time(NULL);
83 localtime_r(&t, &line->timestamp);
84 strftime(line->ts, 9, "%H:%M:%S", &line->timestamp);
82 t = time(NULL);
83 localtime_r(&t, &line->timestamp);
84 strftime(line->ts, 9, "%H:%M:%S", &line->timestamp);
85 85
86 lines[line_cursor] = line;
86 lines[line_cursor] = line;
87 87
88 if (++line_cursor >= line_limit) {
89 console_init(line_limit*2);
90 }
88 if (++line_cursor >= line_limit) {
89 console_init(line_limit*2);
90 }
91 91
92 /* Scroll window if at bottom. */
93 if (console_window->num_lines < console_window->height || console_window->position + console_window->height + 1 >= console_window->num_lines) {
94 console_scroll(1);
95 }
92 /* Scroll window if at bottom. */
93 if (console_window->num_lines < console_window->height || console_window->position + console_window->height + 1 >= console_window->num_lines) {
94 console_scroll(1);
95 }
96 96
97 pthread_mutex_unlock(&console_mutex);
97 pthread_mutex_unlock(&console_mutex);
98 98 } }
99 99
100 100 void console_draw_lines(long start, long end) { void console_draw_lines(long start, long end) {
101 101
102 long s;
103 long ptr;
104 logline_t * line;
102 long s;
103 long ptr;
104 logline_t * line;
105 105
106 106 pms_curses_lock(); pms_curses_lock();
107 107
108 ptr = console_window->position + start;
109 for (s = start; s <= end; s++) {
110 if (ptr >= console_window->num_lines) {
111 break;
112 }
113 line = lines[ptr];
114 mvwprintw(window_main, s, 0, "%s: %s", line->ts, line->str);
115 ++ptr;
116 }
108 ptr = console_window->position + start;
109 for (s = start; s <= end; s++) {
110 if (ptr >= console_window->num_lines) {
111 break;
112 }
113 line = lines[ptr];
114 mvwprintw(window_main, s, 0, "%s: %s", line->ts, line->str);
115 ++ptr;
116 }
117 117
118 wrefresh(window_main);
118 wrefresh(window_main);
119 119
120 120 pms_curses_unlock(); pms_curses_unlock();
121 121 } }
122 122
123 123 int console_scroll(long delta) { int console_scroll(long delta) {
124 124
125 int changed = window_scroll(console_window, delta);
125 int changed = window_scroll(console_window, delta);
126 126
127 if (changed > 0) {
128 console_draw_lines(console_window->height - changed, console_window->height);
129 } else if (changed < 0) {
130 console_draw_lines(0, -changed - 1);
131 } else {
132 console_draw_lines(console_window->num_lines - 1, console_window->num_lines - 1);
133 }
127 if (changed > 0) {
128 console_draw_lines(console_window->height - changed, console_window->height);
129 } else if (changed < 0) {
130 console_draw_lines(0, -changed - 1);
131 } else {
132 console_draw_lines(console_window->num_lines - 1, console_window->num_lines - 1);
133 }
134 134
135 return changed;
135 return changed;
136 136 } }
137 137
138 138 int console_scroll_to(long position) { int console_scroll_to(long position) {
139 if (position < 0) {
140 position = console_window->num_lines+position;
141 }
142 position -= console_window->position;
143 console_scroll(position);
139 if (position < 0) {
140 position = console_window->num_lines+position;
141 }
142 position -= console_window->position;
143 console_scroll(position);
144 144 } }
145 145
146 146 logline_t * new_logline() { logline_t * new_logline() {
147 logline_t * line;
147 logline_t * line;
148 148
149 if ((line = malloc(sizeof(logline_t))) == NULL) {
150 fatal(PMS_EXIT_MEMORY, "Out of memory");
151 }
149 if ((line = malloc(sizeof(logline_t))) == NULL) {
150 fatal(PMS_EXIT_MEMORY, "Out of memory");
151 }
152 152
153 line->str = malloc(512);
154 line->ts = malloc(9);
153 line->str = malloc(512);
154 line->ts = malloc(9);
155 155
156 if (line->str == NULL || line->ts == NULL) {
157 fatal(PMS_EXIT_MEMORY, "Out of memory");
158 }
156 if (line->str == NULL || line->ts == NULL) {
157 fatal(PMS_EXIT_MEMORY, "Out of memory");
158 }
159 159
160 return line;
160 return line;
161 161 } }
162 162
163 163 void free_logline(logline_t * line) { void free_logline(logline_t * line) {
164 free(line->str);
165 free(line->ts);
166 free(line);
164 free(line->str);
165 free(line->ts);
166 free(line);
167 167 } }
File src/console.h changed (mode: 100644) (index 87f4645..b9a128b)
1 /* vi:set ts=4 sts=4 sw=4 noet:
1 /* vi:set ts=4 sts=4 sw=4 et:
2 2 * *
3 3 * Practical Music Search * Practical Music Search
4 4 * Copyright (c) 2006-2014 Kim Tore Jensen * Copyright (c) 2006-2014 Kim Tore Jensen
 
21 21 * Console log line data structure. * Console log line data structure.
22 22 */ */
23 23 typedef struct { typedef struct {
24 char * str;
25 char * ts;
26 int verbosity;
27 struct tm timestamp;
24 char * str;
25 char * ts;
26 int verbosity;
27 struct tm timestamp;
28 28 } logline_t; } logline_t;
29 29
30 30 /** /**
File src/curses.c changed (mode: 100644) (index 98e8c51..3f74f83)
1 /* vi:set ts=4 sts=4 sw=4 noet:
1 /* vi:set ts=4 sts=4 sw=4 et:
2 2 * *
3 3 * Practical Music Search * Practical Music Search
4 4 * Copyright (c) 2006-2014 Kim Tore Jensen * Copyright (c) 2006-2014 Kim Tore Jensen
 
... ... WINDOW * window_statusbar;
27 27 static pthread_mutex_t curses_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t curses_mutex = PTHREAD_MUTEX_INITIALIZER;
28 28
29 29 void curses_destroy_windows() { void curses_destroy_windows() {
30 if (window_topbar) {
31 delwin(window_topbar);
32 }
33 if (window_main) {
34 delwin(window_main);
35 }
36 if (window_statusbar) {
37 delwin(window_statusbar);
38 }
30 if (window_topbar) {
31 delwin(window_topbar);
32 }
33 if (window_main) {
34 delwin(window_main);
35 }
36 if (window_statusbar) {
37 delwin(window_statusbar);
38 }
39 39 } }
40 40
41 41 void curses_init_windows() { void curses_init_windows() {
42 window_topbar = newwin(1, COLS, 0, 0);
43 window_main = newwin(LINES - 2, COLS, 1, 0);
44 window_statusbar = newwin(1, COLS, LINES - 1, 0);
45 scrollok(window_main, true);
46 scrollok(window_topbar, false);
47 scrollok(window_statusbar, false);
48 keypad(window_statusbar, true);
42 window_topbar = newwin(1, COLS, 0, 0);
43 window_main = newwin(LINES - 2, COLS, 1, 0);
44 window_statusbar = newwin(1, COLS, LINES - 1, 0);
45 scrollok(window_main, true);
46 scrollok(window_topbar, false);
47 scrollok(window_statusbar, false);
48 keypad(window_statusbar, true);
49 49 } }
50 50
51 51 void curses_init() { void curses_init() {
52 if ((initscr()) == NULL) {
53 fatal(PMS_EXIT_NCURSES, "Unable to start ncurses, exiting.\n");
54 }
52 if ((initscr()) == NULL) {
53 fatal(PMS_EXIT_NCURSES, "Unable to start ncurses, exiting.\n");
54 }
55 55
56 curses_init_windows();
56 curses_init_windows();
57 57
58 noecho();
59 raw();
60 curs_set(0);
61 halfdelay(10);
58 noecho();
59 raw();
60 curs_set(0);
61 halfdelay(10);
62 62
63 63 #ifdef HAVE_CURSES_COLOR #ifdef HAVE_CURSES_COLOR
64 if (has_colors()) {
65 start_color();
66 use_default_colors();
67 }
64 if (has_colors()) {
65 start_color();
66 use_default_colors();
67 }
68 68 #endif #endif
69 69
70 wclear(window_topbar);
71 wclear(window_main);
72 wclear(window_statusbar);
73 wrefresh(window_topbar);
74 wrefresh(window_main);
75 wrefresh(window_statusbar);
70 wclear(window_topbar);
71 wclear(window_main);
72 wclear(window_statusbar);
73 wrefresh(window_topbar);
74 wrefresh(window_main);
75 wrefresh(window_statusbar);
76 76 } }
77 77
78 78 void curses_shutdown() { void curses_shutdown() {
79 endwin();
79 endwin();
80 80 } }
81 81
82 82 int curses_get_input() { int curses_get_input() {
83 return wgetch(window_statusbar);
83 return wgetch(window_statusbar);
84 84 } }
85 85
86 86 void pms_curses_lock() { void pms_curses_lock() {
87 pthread_mutex_lock(&curses_mutex);
87 pthread_mutex_lock(&curses_mutex);
88 88 } }
89 89
90 90 void pms_curses_unlock() { void pms_curses_unlock() {
91 pthread_mutex_unlock(&curses_mutex);
91 pthread_mutex_unlock(&curses_mutex);
92 92 } }
File src/curses.h changed (mode: 100644) (index 9cdaec7..10868f4)
1 /* vi:set ts=4 sts=4 sw=4 noet:
1 /* vi:set ts=4 sts=4 sw=4 et:
2 2 * *
3 3 * Practical Music Search * Practical Music Search
4 4 * Copyright (c) 2006-2014 Kim Tore Jensen * Copyright (c) 2006-2014 Kim Tore Jensen
 
20 20 #include "build.h" #include "build.h"
21 21
22 22 #if defined HAVE_NCURSESW_CURSES_H #if defined HAVE_NCURSESW_CURSES_H
23 #include <ncursesw/curses.h>
23 #include <ncursesw/curses.h>
24 24 #elif defined HAVE_NCURSESW_H #elif defined HAVE_NCURSESW_H
25 #include <ncursesw.h>
25 #include <ncursesw.h>
26 26 #elif defined HAVE_NCURSES_CURSES_H #elif defined HAVE_NCURSES_CURSES_H
27 #include <ncurses/curses.h>
27 #include <ncurses/curses.h>
28 28 #elif defined HAVE_NCURSES_H #elif defined HAVE_NCURSES_H
29 #include <ncurses.h>
29 #include <ncurses.h>
30 30 #elif defined HAVE_CURSES_H #elif defined HAVE_CURSES_H
31 #include <curses.h>
31 #include <curses.h>
32 32 #else #else
33 #error "SysV or X/Open-compatible Curses header file required"
33 #error "SysV or X/Open-compatible Curses header file required"
34 34 #endif #endif
35 35
36 36 void curses_init(); void curses_init();
File src/input.c changed (mode: 100644) (index f8a99aa..136cc5d)
1 /* vi:set ts=4 sts=4 sw=4 noet:
1 /* vi:set ts=4 sts=4 sw=4 et:
2 2 * *
3 3 * Practical Music Search * Practical Music Search
4 4 * Copyright (c) 2006-2014 Kim Tore Jensen * Copyright (c) 2006-2014 Kim Tore Jensen
 
... ... static int input_char_get_int(int ch) {
31 31 } }
32 32
33 33 static int input_char_get_movement(int ch) { static int input_char_get_movement(int ch) {
34 if (ch == KEY_UP || ch == 'k') {
34 if (ch == KEY_UP || ch == 'k') {
35 35 return INPUT_MOVEMENT_UP; return INPUT_MOVEMENT_UP;
36 } else if (ch == KEY_DOWN || ch == 'j') {
36 } else if (ch == KEY_DOWN || ch == 'j') {
37 37 return INPUT_MOVEMENT_DOWN; return INPUT_MOVEMENT_DOWN;
38 } else if (ch == 'G') {
38 } else if (ch == 'G') {
39 39 return INPUT_MOVEMENT_END; return INPUT_MOVEMENT_END;
40 40 } }
41 41 return INPUT_MOVEMENT_NONE; return INPUT_MOVEMENT_NONE;
42 42 } }
43 43
44 44 static int input_char_get_action(int ch) { static int input_char_get_action(int ch) {
45 if (ch == KEY_UP || ch == 'k') {
45 if (ch == KEY_UP || ch == 'k') {
46 46 return INPUT_ACTION_GO; return INPUT_ACTION_GO;
47 } else if (ch == KEY_DOWN || ch == 'j') {
47 } else if (ch == KEY_DOWN || ch == 'j') {
48 48 return INPUT_ACTION_GO; return INPUT_ACTION_GO;
49 49 } else if (ch == 'q') { } else if (ch == 'q') {
50 50 return INPUT_ACTION_QUIT; return INPUT_ACTION_QUIT;
 
... ... command_t * input_get() {
119 119 int input_handle(command_t * command) { int input_handle(command_t * command) {
120 120 console("input_handle(): multiplier=%d, movement=%d, action=%d", command->multiplier, command->movement, command->action); console("input_handle(): multiplier=%d, movement=%d, action=%d", command->multiplier, command->movement, command->action);
121 121 if (command->action == INPUT_ACTION_QUIT) { if (command->action == INPUT_ACTION_QUIT) {
122 shutdown();
122 shutdown();
123 123 return 0; return 0;
124 } else if (command->action == INPUT_ACTION_GO) {
124 } else if (command->action == INPUT_ACTION_GO) {
125 125 if (command->movement == INPUT_MOVEMENT_UP) { if (command->movement == INPUT_MOVEMENT_UP) {
126 126 console_scroll(-command->multiplier); console_scroll(-command->multiplier);
127 127 } else if (command->movement == INPUT_MOVEMENT_DOWN) { } else if (command->movement == INPUT_MOVEMENT_DOWN) {
 
... ... int input_handle(command_t * command) {
133 133 console_scroll_to(command->multiplier-1); // convert 1-indexed to 0-indexed console_scroll_to(command->multiplier-1); // convert 1-indexed to 0-indexed
134 134 return 0; return 0;
135 135 } }
136 } else {
136 } else {
137 137 return 0; return 0;
138 138 } }
139 139 return 1; return 1;
File src/input.h changed (mode: 100644) (index bb02bd8..a62eb20)
1 /* vi:set ts=4 sts=4 sw=4 noet:
1 /* vi:set ts=4 sts=4 sw=4 et:
2 2 * *
3 3 * Practical Music Search * Practical Music Search
4 4 * Copyright (c) 2006-2014 Kim Tore Jensen * Copyright (c) 2006-2014 Kim Tore Jensen
File src/pms.c changed (mode: 100644) (index c4c93bd..646d9a7)
1 /* vi:set ts=4 sts=4 sw=4 noet:
1 /* vi:set ts=4 sts=4 sw=4 et:
2 2 * *
3 3 * Practical Music Search * Practical Music Search
4 4 * Copyright (c) 2006-2014 Kim Tore Jensen * Copyright (c) 2006-2014 Kim Tore Jensen
 
... ... static pthread_mutex_t status_mutex = PTHREAD_MUTEX_INITIALIZER;
34 34
35 35 void reset_options() { void reset_options() {
36 36
37 if (options == NULL) {
38 options = malloc(sizeof(struct options_t));
39 }
37 if (options == NULL) {
38 options = malloc(sizeof(struct options_t));
39 }
40 40
41 if (options == NULL) {
42 perror("out of memory\n");
43 exit(PMS_EXIT_MEMORY);
44 }
41 if (options == NULL) {
42 perror("out of memory\n");
43 exit(PMS_EXIT_MEMORY);
44 }
45 45
46 options->server = "localhost";
47 options->port = 0;
48 options->timeout = 2000;
49 options->console_size = 1024;
46 options->server = "localhost";
47 options->port = 0;
48 options->timeout = 2000;
49 options->console_size = 1024;
50 50
51 51 } }
52 52
53 53 void fatal(int exitcode, const char * format, ...) { void fatal(int exitcode, const char * format, ...) {
54 va_list ap;
55 curses_shutdown();
56 va_start(ap, format);
57 vprintf(format, ap);
58 va_end(ap);
59 exit(exitcode);
54 va_list ap;
55 curses_shutdown();
56 va_start(ap, format);
57 vprintf(format, ap);
58 va_end(ap);
59 exit(exitcode);
60 60 } }
61 61
62 62 void shutdown() { void shutdown() {
63 console("Shutting down.");
64 pms_state->running = 0;
63 console("Shutting down.");
64 pms_state->running = 0;
65 65 } }
66 66
67 67 static struct mpd_connection * pms_mpd_connect() { static struct mpd_connection * pms_mpd_connect() {
68 68
69 enum mpd_error status;
70 const char * error_msg;
71 struct mpd_connection * connection;
72
73 console("Connecting to %s...", options->server);
74
75 connection = mpd_connection_new(options->server, options->port, options->timeout);
76 if (connection == NULL) {
77 fatal(PMS_EXIT_MEMORY, "mpd connect: out of memory\n");
78 }
79
80 status = mpd_connection_get_error(connection);
81 if (status == MPD_ERROR_SUCCESS) {
82 console("Connected to %s", options->server);
83 } else {
84 error_msg = mpd_connection_get_error_message(connection);
85 console("Error connecting to %s: error %d: %s", options->server, status, error_msg);
86 mpd_connection_free(connection);
87 connection = NULL;
88 }
89
90 return connection;
69 enum mpd_error status;
70 const char * error_msg;
71 struct mpd_connection * connection;
72
73 console("Connecting to %s...", options->server);
74
75 connection = mpd_connection_new(options->server, options->port, options->timeout);
76 if (connection == NULL) {
77 fatal(PMS_EXIT_MEMORY, "mpd connect: out of memory\n");
78 }
79
80 status = mpd_connection_get_error(connection);
81 if (status == MPD_ERROR_SUCCESS) {
82 console("Connected to %s", options->server);
83 } else {
84 error_msg = mpd_connection_get_error_message(connection);
85 console("Error connecting to %s: error %d: %s", options->server, status, error_msg);
86 mpd_connection_free(connection);
87 connection = NULL;
88 }
89
90 return connection;
91 91 } }
92 92
93 93 static void pms_get_mpd_state(struct mpd_connection * connection) { static void pms_get_mpd_state(struct mpd_connection * connection) {
94 94
95 pms_status_lock();
96 if (pms_state->status) {
97 mpd_status_free(pms_state->status);
98 }
99 pms_state->status = mpd_run_status(connection);
100 pms_status_unlock();
95 pms_status_lock();
96 if (pms_state->status) {
97 mpd_status_free(pms_state->status);
98 }
99 pms_state->status = mpd_run_status(connection);
100 pms_status_unlock();
101 101
102 102 } }
103 103
104 104 static void pms_handle_mpd_idle_update(struct mpd_connection * connection, enum mpd_idle flags) { static void pms_handle_mpd_idle_update(struct mpd_connection * connection, enum mpd_idle flags) {
105 105
106 console("pms_handle_mpd_idle_update %d", flags);
107
108 if (flags & MPD_IDLE_DATABASE) {
109 console("Database has been updated.");
110 }
111 if (flags & MPD_IDLE_STORED_PLAYLIST) {
112 console("Stored playlists have been updated.");
113 }
114 if (flags & MPD_IDLE_QUEUE) {
115 console("The queue has been updated.");
116 }
117 if (flags & MPD_IDLE_PLAYER) {
118 console("Player state has changed.");
119 }
120 if (flags & MPD_IDLE_MIXER) {
121 console("Mixer parameters have changed.");
122 }
123 if (flags & MPD_IDLE_OUTPUT) {
124 console("Outputs have changed.");
125 }
126 if (flags & MPD_IDLE_OPTIONS) {
127 console("Options have changed.");
128 }
129 if (flags & MPD_IDLE_UPDATE) {
130 console("Database update has started or finished.");
131 }
132
133 if (flags & (MPD_IDLE_QUEUE | MPD_IDLE_PLAYER | MPD_IDLE_MIXER | MPD_IDLE_OPTIONS)) {
134 pms_get_mpd_state(connection);
135 }
136
137 topbar_draw();
106 console("pms_handle_mpd_idle_update %d", flags);
107
108 if (flags & MPD_IDLE_DATABASE) {
109 console("Database has been updated.");
110 }
111 if (flags & MPD_IDLE_STORED_PLAYLIST) {
112 console("Stored playlists have been updated.");
113 }
114 if (flags & MPD_IDLE_QUEUE) {
115 console("The queue has been updated.");
116 }
117 if (flags & MPD_IDLE_PLAYER) {
118 console("Player state has changed.");
119 }
120 if (flags & MPD_IDLE_MIXER) {
121 console("Mixer parameters have changed.");
122 }
123 if (flags & MPD_IDLE_OUTPUT) {
124 console("Outputs have changed.");
125 }
126 if (flags & MPD_IDLE_OPTIONS) {
127 console("Options have changed.");
128 }
129 if (flags & MPD_IDLE_UPDATE) {
130 console("Database update has started or finished.");
131 }
132
133 if (flags & (MPD_IDLE_QUEUE | MPD_IDLE_PLAYER | MPD_IDLE_MIXER | MPD_IDLE_OPTIONS)) {
134 pms_get_mpd_state(connection);
135 }
136
137 topbar_draw();
138 138
139 139 } }
140 140
141 141 void signal_resize(int signal) { void signal_resize(int signal) {
142 console("Resized to %d x %d", LINES, COLS);
143 pms_curses_lock();
144 curses_destroy_windows();
145 curses_init_windows();
146 pms_curses_unlock();
142 console("Resized to %d x %d", LINES, COLS);
143 pms_curses_lock();
144 curses_destroy_windows();
145 curses_init_windows();
146 pms_curses_unlock();
147 147 } }
148 148
149 149 void signal_kill(int signal) { void signal_kill(int signal) {
150 fatal(PMS_EXIT_KILLED, "Killed by signal %d\n", signal);
150 fatal(PMS_EXIT_KILLED, "Killed by signal %d\n", signal);
151 151 } }
152 152
153 153 static void signal_init() { static void signal_init() {
154 if (signal(SIGWINCH, signal_resize) == SIG_ERR) {
155 console("Error in signal_init(): window resizing will not work!");
156 }
157 signal(SIGTERM, signal_kill);
154 if (signal(SIGWINCH, signal_resize) == SIG_ERR) {
155 console("Error in signal_init(): window resizing will not work!");
156 }
157 signal(SIGTERM, signal_kill);
158 158 } }
159 159
160 160 int pms_get_pending_input_flags(struct mpd_connection * connection) { int pms_get_pending_input_flags(struct mpd_connection * connection) {
161 struct timeval tv;
162 int mpd_fd = 0;
163 int retval;
164 int flags = 0;
165 fd_set fds;
166
167 tv.tv_sec = 1;
168 tv.tv_usec = 0;
169
170 if (connection) {
171 mpd_fd = mpd_connection_get_fd(connection);
172 }
173
174 FD_ZERO(&fds);
175 FD_SET(STDIN_FILENO, &fds);
176 FD_SET(mpd_fd, &fds);
177
178 retval = select(mpd_fd+1, &fds, NULL, NULL, &tv);
179
180 if (retval == -1) {
181 console("Error %d in select(): %s", errno, strerror(errno));
182
183 } else if (retval > 0) {
184 if (mpd_fd != 0 && FD_ISSET(mpd_fd, &fds)) {
185 flags |= PMS_HAS_INPUT_MPD;
186 }
187 if (FD_ISSET(STDIN_FILENO, &fds)) {
188 flags |= PMS_HAS_INPUT_STDIN;
189 }
190 }
191
192 return flags;
161 struct timeval tv;
162 int mpd_fd = 0;
163 int retval;
164 int flags = 0;
165 fd_set fds;
166
167 tv.tv_sec = 1;
168 tv.tv_usec = 0;
169
170 if (connection) {
171 mpd_fd = mpd_connection_get_fd(connection);
172 }
173
174 FD_ZERO(&fds);
175 FD_SET(STDIN_FILENO, &fds);
176 FD_SET(mpd_fd, &fds);
177
178 retval = select(mpd_fd+1, &fds, NULL, NULL, &tv);
179
180 if (retval == -1) {
181 console("Error %d in select(): %s", errno, strerror(errno));
182
183 } else if (retval > 0) {
184 if (mpd_fd != 0 && FD_ISSET(mpd_fd, &fds)) {
185 flags |= PMS_HAS_INPUT_MPD;
186 }
187 if (FD_ISSET(STDIN_FILENO, &fds)) {
188 flags |= PMS_HAS_INPUT_STDIN;
189 }
190 }
191
192 return flags;
193 193 } }
194 194
195 195 int main(int argc, char** argv) { int main(int argc, char** argv) {
196 196
197 command_t * command = NULL;
198 struct mpd_connection * connection = NULL;
199 bool is_idle = false;
200 enum mpd_idle flags = -1;
201 int input_flags = 0;
202
203 reset_options();
204 pms_state = malloc(sizeof(struct pms_state_t));
205 memset(pms_state, 0, sizeof(struct pms_state_t));
206 pms_state->running = true;
207
208 curses_init();
209 console_init(options->console_size);
210 signal_init();
211 input_reset();
212 console("%s %s (c) 2006-2014 Kim Tore Jensen <%s>", PACKAGE_NAME, PACKAGE_VERSION, PACKAGE_BUGREPORT);
213
214 while(pms_state->running) {
215
216 if (!connection) {
217 if (connection = pms_mpd_connect()) {
218 pms_handle_mpd_idle_update(connection, -1);
219 }
220 }
221
222 if (connection && !is_idle) {
223 mpd_send_idle(connection);
224 is_idle = true;
225 }
226
227 input_flags = pms_get_pending_input_flags(connection);
228
229 if (input_flags & PMS_HAS_INPUT_MPD) {
230 flags = mpd_recv_idle(connection, true);
231 is_idle = false;
232 pms_handle_mpd_idle_update(connection, flags);
233 }
234
235 if (input_flags & PMS_HAS_INPUT_STDIN) {
236 if ((command = input_get()) != NULL) {
237 while(command->multiplier > 0 && input_handle(command)) {
238 --command->multiplier;
239 }
240 input_reset();
241 }
242 }
243
244 }
245
246 curses_shutdown();
247
248 return PMS_EXIT_SUCCESS;
197 command_t * command = NULL;
198 struct mpd_connection * connection = NULL;
199 bool is_idle = false;
200 enum mpd_idle flags = -1;
201 int input_flags = 0;
202
203 reset_options();
204 pms_state = malloc(sizeof(struct pms_state_t));
205 memset(pms_state, 0, sizeof(struct pms_state_t));
206 pms_state->running = true;
207
208 curses_init();
209 console_init(options->console_size);
210 signal_init();
211 input_reset();
212 console("%s %s (c) 2006-2014 Kim Tore Jensen <%s>", PACKAGE_NAME, PACKAGE_VERSION, PACKAGE_BUGREPORT);
213
214 while(pms_state->running) {
215
216 if (!connection) {
217 if (connection = pms_mpd_connect()) {
218 pms_handle_mpd_idle_update(connection, -1);
219 }
220 }
221
222 if (connection && !is_idle) {
223 mpd_send_idle(connection);
224 is_idle = true;
225 }
226
227 input_flags = pms_get_pending_input_flags(connection);
228
229 if (input_flags & PMS_HAS_INPUT_MPD) {
230 flags = mpd_recv_idle(connection, true);
231 is_idle = false;
232 pms_handle_mpd_idle_update(connection, flags);
233 }
234
235 if (input_flags & PMS_HAS_INPUT_STDIN) {
236 if ((command = input_get()) != NULL) {
237 while(command->multiplier > 0 && input_handle(command)) {
238 --command->multiplier;
239 }
240 input_reset();
241 }
242 }
243
244 }
245
246 curses_shutdown();
247
248 return PMS_EXIT_SUCCESS;
249 249 } }
250 250
251 251 void pms_status_lock() { void pms_status_lock() {
252 pthread_mutex_lock(&status_mutex);
252 pthread_mutex_lock(&status_mutex);
253 253 } }
254 254
255 255 void pms_status_unlock() { void pms_status_unlock() {
256 pthread_mutex_unlock(&status_mutex);
256 pthread_mutex_unlock(&status_mutex);
257 257 } }
File src/pms.h changed (mode: 100644) (index abfde64..516900f)
1 /* vi:set ts=4 sts=4 sw=4 noet:
1 /* vi:set ts=4 sts=4 sw=4 et:
2 2 * *
3 3 * Practical Music Search * Practical Music Search
4 4 * Copyright (c) 2006-2014 Kim Tore Jensen * Copyright (c) 2006-2014 Kim Tore Jensen
 
20 20 #include "build.h" #include "build.h"
21 21
22 22 #ifndef HAVE_PTHREAD #ifndef HAVE_PTHREAD
23 #error "POSIX thread library required."
23 #error "POSIX thread library required."
24 24 #endif #endif
25 25
26 26 #include <pthread.h> #include <pthread.h>
 
... ... struct options_t {
53 53 struct pms_state_t { struct pms_state_t {
54 54 /* Set to false when shutting down. */ /* Set to false when shutting down. */
55 55 int running; int running;
56 struct mpd_status * status;
56 struct mpd_status * status;
57 57 }; };
58 58
59 59 /** /**
File src/topbar.c changed (mode: 100644) (index 23b6366..feec7f2)
1 /* vi:set ts=4 sts=4 sw=4 noet:
1 /* vi:set ts=4 sts=4 sw=4 et:
2 2 * *
3 3 * Practical Music Search * Practical Music Search
4 4 * Copyright (c) 2006-2014 Kim Tore Jensen * Copyright (c) 2006-2014 Kim Tore Jensen
File src/topbar.h changed (mode: 100644) (index 798c435..386bb3b)
1 /* vi:set ts=4 sts=4 sw=4 noet:
1 /* vi:set ts=4 sts=4 sw=4 et:
2 2 * *
3 3 * Practical Music Search * Practical Music Search
4 4 * Copyright (c) 2006-2014 Kim Tore Jensen * Copyright (c) 2006-2014 Kim Tore Jensen
File src/window.c changed (mode: 100644) (index 6639af6..5ca9b33)
1 /* vi:set ts=4 sts=4 sw=4 noet:
1 /* vi:set ts=4 sts=4 sw=4 et:
2 2 * *
3 3 * Practical Music Search * Practical Music Search
4 4 * Copyright (c) 2006-2014 Kim Tore Jensen * Copyright (c) 2006-2014 Kim Tore Jensen
 
... ... extern WINDOW * window_main;
23 23
24 24 int window_scroll(window_t * window, long delta) { int window_scroll(window_t * window, long delta) {
25 25
26 long npos;
26 long npos;
27 27
28 if (window->num_lines <= window->height) {
29 return 0;
30 }
28 if (window->num_lines <= window->height) {
29 return 0;
30 }
31 31
32 32 pms_curses_lock(); pms_curses_lock();
33 33
34 if (delta > 0) {
35 npos = window->position + delta;
36 if (npos + window->height > window->num_lines) {
37 delta = window->num_lines - window->height - window->position;
38 // TODO: beep?
39 }
40 } else if (delta < 0) {
41 npos = window->position + delta - 1;
42 if (npos < 0) {
43 delta = -window->position;
44 // TODO: beep?
45 }
46 }
47
48 window->position += delta;
49 wscrl(window_main, delta);
50 wrefresh(window_main);
34 if (delta > 0) {
35 npos = window->position + delta;
36 if (npos + window->height > window->num_lines) {
37 delta = window->num_lines - window->height - window->position;
38 // TODO: beep?
39 }
40 } else if (delta < 0) {
41 npos = window->position + delta - 1;
42 if (npos < 0) {
43 delta = -window->position;
44 // TODO: beep?
45 }
46 }
47
48 window->position += delta;
49 wscrl(window_main, delta);
50 wrefresh(window_main);
51 51
52 52 pms_curses_unlock(); pms_curses_unlock();
53 53
54 return delta;
54 return delta;
55 55
56 56 } }
File src/window.h changed (mode: 100644) (index 5f989f5..71bd388)
1 /* vi:set ts=4 sts=4 sw=4 noet:
1 /* vi:set ts=4 sts=4 sw=4 et:
2 2 * *
3 3 * Practical Music Search * Practical Music Search
4 4 * Copyright (c) 2006-2014 Kim Tore Jensen * Copyright (c) 2006-2014 Kim Tore Jensen
 
22 22 */ */
23 23 typedef struct { typedef struct {
24 24
25 /* Scroll position - top item */
26 long position;
25 /* Scroll position - top item */
26 long position;
27 27
28 /* Cursor position */
29 long cursor;
28 /* Cursor position */
29 long cursor;
30 30
31 /* Height in lines */
32 int height;
31 /* Height in lines */
32 int height;
33 33
34 34 /* Number of lines in list */ /* Number of lines in list */
35 35 int num_lines; int num_lines;
Hints

Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://code.reversed.top/user/xaizek/pms

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/pms

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a pull request:
... clone the repository ...
... make some changes and some commits ...
git push origin master