Code

screen_chat: add an option to set the message prefix
[ncmpc.git] / src / screen_chat.c
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)
103         screen_text_paint(&text);
106 static void
107 process_message(struct mpd_message *message)
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();
123 static void
124 screen_chat_update(struct mpdclient *c)
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         }
142 static char *
143 screen_chat_get_prefix(void)
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;
160 static void
161 screen_chat_send_message(struct mpdclient *c, char *msg)
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);
172 static bool
173 screen_chat_cmd(struct mpdclient *c, command_t cmd)
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;
198 static const char *
199 screen_chat_title(G_GNUC_UNUSED char *s, G_GNUC_UNUSED size_t size)
201         return _("Chat");
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 };