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 if (options.chat_prefix) {
151 /* Options are encoded in the "locale" charset */
152 prefix = locale_to_utf8(options.chat_prefix);
153 return prefix;
154 }
156 prefix = g_strconcat("<", g_get_user_name(), "> ", NULL);
157 return prefix;
158 }
160 static void
161 screen_chat_send_message(struct mpdclient *c, char *msg)
162 {
163 char *utf8 = locale_to_utf8(msg);
164 char *prefix = screen_chat_get_prefix();
165 char *full_msg = g_strconcat(prefix, utf8, NULL);
166 g_free(utf8);
168 (void) mpdclient_cmd_send_message(c, chat_channel, full_msg);
169 g_free(full_msg);
170 }
172 static bool
173 screen_chat_cmd(struct mpdclient *c, command_t cmd)
174 {
175 if (screen_text_cmd(&text, c, cmd))
176 return true;
178 if (cmd == CMD_PLAY) {
179 char *message = screen_readln(_("Your message"), NULL, NULL, NULL);
181 /* the user entered an empty line */
182 if (message == NULL)
183 return true;
185 if (check_chat_support(c))
186 screen_chat_send_message(c, message);
187 else
188 screen_status_message(_("Message could not be sent"));
190 g_free(message);
192 return true;
193 }
195 return false;
196 }
198 static const char *
199 screen_chat_title(G_GNUC_UNUSED char *s, G_GNUC_UNUSED size_t size)
200 {
201 return _("Chat");
202 }
204 const struct screen_functions screen_chat = {
205 .init = screen_chat_init,
206 .exit = screen_chat_exit,
207 .open = screen_chat_open,
208 /* close */
209 .resize = screen_chat_resize,
210 .paint = screen_chat_paint,
211 .update = screen_chat_update,
212 .cmd = screen_chat_cmd,
213 .get_title = screen_chat_title,
214 };