1 /* ncmpc (Ncurses MPD Client)
2 * (c) 2004-2012 The Music Player Daemon Project
3 * Project homepage: http://musicpd.org
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
20 #include "screen_chat.h"
22 #include "screen_interface.h"
23 #include "screen_utils.h"
24 #include "screen_status.h"
25 #include "screen_text.h"
26 #include "mpdclient.h"
27 #include "i18n.h"
28 #include "charset.h"
29 #include "options.h"
31 #include <glib.h>
32 #include <mpd/idle.h>
34 static struct screen_text text; /* rename? */
35 static const char chat_channel[] = "chat";
37 static bool
38 check_chat_support(struct mpdclient *c)
39 {
40 static unsigned last_connection_id = 0;
41 static bool was_supported = false;
43 /* if we're using the same connection as the last time
44 check_chat_support was called, we can use the cached information
45 about whether chat is supported */
46 if (c->connection_id == last_connection_id)
47 return was_supported;
49 last_connection_id = c->connection_id;
51 if (c->connection == NULL)
52 return (was_supported = false);
54 if (mpd_connection_cmp_server_version(c->connection, 0, 17, 0) == -1) {
55 const unsigned *version = mpd_connection_get_server_version(c->connection);
56 char *str;
58 str = g_strdup_printf(
59 _("connected to MPD %u.%u.%u (you need at least \n"
60 "version 0.17.0 to use the chat feature)"),
61 version[0], version[1], version[2]);
62 screen_text_append(&text, str);
63 g_free(str);
65 return (was_supported = false);
66 }
68 /* mpdclient_get_connection? */
69 if (!mpdclient_cmd_subscribe(c, chat_channel))
70 return (was_supported = false);
71 /* mpdclient_put_connection? */
73 return (was_supported = true);
74 }
76 static void
77 screen_chat_init(WINDOW *w, int cols, int rows)
78 {
79 screen_text_init(&text, w, cols, rows);
80 }
82 static void
83 screen_chat_exit(void)
84 {
85 screen_text_deinit(&text);
86 }
88 static void
89 screen_chat_open(struct mpdclient *c)
90 {
91 (void) check_chat_support(c);
92 }
94 static void
95 screen_chat_resize(int cols, int rows)
96 {
97 screen_text_resize(&text, cols, rows);
98 }
100 static void
101 screen_chat_paint(void)
102 {
103 screen_text_paint(&text);
104 }
106 static void
107 process_message(struct mpd_message *message)
108 {
109 char *message_text;
111 assert(message != NULL);
112 /* You'll have to move this out of screen_chat, if you want to use
113 client-to-client messages anywhere else */
114 assert(g_strcmp0(mpd_message_get_channel(message), chat_channel) == 0);
116 message_text = utf8_to_locale(mpd_message_get_text(message));
117 screen_text_append(&text, message_text);
118 g_free(message_text);
120 screen_chat_paint();
121 }
123 static void
124 screen_chat_update(struct mpdclient *c)
125 {
126 if (check_chat_support(c) && (c->events & MPD_IDLE_MESSAGE)) {
127 if (!mpdclient_send_read_messages(c))
128 return;
130 struct mpd_message *message;
131 while ((message = mpdclient_recv_message(c)) != NULL) {
132 process_message(message);
133 mpd_message_free(message);
134 }
136 mpdclient_finish_command(c);
138 c->events &= ~MPD_IDLE_MESSAGE;
139 }
140 }
142 static char *
143 screen_chat_get_prefix(void)
144 {
145 static char *prefix = NULL;
147 if (prefix)
148 return prefix;
150 prefix = g_strconcat("<", g_get_user_name(), "> ", NULL);
151 return prefix;
152 }
154 static void
155 screen_chat_send_message(struct mpdclient *c, char *msg)
156 {
157 char *utf8 = locale_to_utf8(msg);
158 char *prefix = screen_chat_get_prefix();
159 char *full_msg = g_strconcat(prefix, utf8, NULL);
160 g_free(utf8);
162 (void) mpdclient_cmd_send_message(c, chat_channel, full_msg);
163 g_free(full_msg);
164 }
166 static bool
167 screen_chat_cmd(struct mpdclient *c, command_t cmd)
168 {
169 if (screen_text_cmd(&text, c, cmd))
170 return true;
172 if (cmd == CMD_PLAY) {
173 char *message = screen_readln(_("Your message"), NULL, NULL, NULL);
175 /* the user entered an empty line */
176 if (message == NULL)
177 return true;
179 if (check_chat_support(c))
180 screen_chat_send_message(c, message);
181 else
182 screen_status_message(_("Message could not be sent"));
184 g_free(message);
186 return true;
187 }
189 return false;
190 }
192 static const char *
193 screen_chat_title(G_GNUC_UNUSED char *s, G_GNUC_UNUSED size_t size)
194 {
195 return _("Chat");
196 }
198 const struct screen_functions screen_chat = {
199 .init = screen_chat_init,
200 .exit = screen_chat_exit,
201 .open = screen_chat_open,
202 /* close */
203 .resize = screen_chat_resize,
204 .paint = screen_chat_paint,
205 .update = screen_chat_update,
206 .cmd = screen_chat_cmd,
207 .get_title = screen_chat_title,
208 };