Code

screen_chat: make it useful
authorJonathan Neuschäfer <j.neuschaefer@gmx.net>
Wed, 4 Jan 2012 17:33:31 +0000 (18:33 +0100)
committerJonathan Neuschäfer <j.neuschaefer@gmx.net>
Wed, 23 May 2012 01:50:50 +0000 (03:50 +0200)
This patch adds basic functionality to the chat screen.

NEWS
src/screen_chat.c
src/screen_help.c

diff --git a/NEWS b/NEWS
index 0af6a1bfc8d9428d77bd8e64187a73891ccb9bc3..804b6d2dec35dfaeb2168c676db66e98dfaac8b8 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,5 @@
 ncmpc 0.21 - not yet released
+* add a chat screen for communication with other clients on the same server
 
 
 ncmpc 0.20 - (02/05/2012)
index 94aee1dcebb8bddd111140bfbfb9c47c3d18f897..b4d3aaca89844e97aa36d6dd4513577657a8e313 100644 (file)
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+#include "screen_chat.h"
+
 #include "screen_interface.h"
+#include "screen_utils.h"
+#include "screen_status.h"
+#include "screen_text.h"
 #include "mpdclient.h"
+#include "i18n.h"
+#include "charset.h"
+
+#include <glib.h>
+#include <mpd/idle.h>
+
+static struct screen_text text; /* rename? */
+static const char chat_channel[] = "chat";
 
 static bool
-screen_chat_cmd(G_GNUC_UNUSED struct mpdclient *c,
-               G_GNUC_UNUSED command_t cmd)
+check_chat_support(struct mpdclient *c)
+{
+       static unsigned last_connection_id = 0;
+       static bool was_supported = false;
+
+       /* if we're using the same connection as the last time
+          check_chat_support was called, we can use the cached information
+          about whether chat is supported */
+       if (c->connection_id == last_connection_id)
+               return was_supported;
+
+       last_connection_id = c->connection_id;
+
+       if (c->connection == NULL)
+               return (was_supported = false);
+
+       if (mpd_connection_cmp_server_version(c->connection, 0, 17, 0) == -1) {
+               const unsigned *version = mpd_connection_get_server_version(c->connection);
+               char *str;
+
+               str = g_strdup_printf(
+                       _("connected to MPD %u.%u.%u (you need at least \n"
+                         "version 0.17.0 to use the chat feature)"),
+                       version[0], version[1], version[2]);
+               screen_text_append(&text, str);
+               g_free(str);
+
+               return (was_supported = false);
+       }
+
+       /* mpdclient_get_connection? */
+       if (!mpdclient_cmd_subscribe(c, chat_channel))
+               return (was_supported = false);
+       /* mpdclient_put_connection? */
+
+       return (was_supported = true);
+}
+
+static void
+screen_chat_init(WINDOW *w, int cols, int rows)
 {
+       screen_text_init(&text, w, cols, rows);
+}
+
+static void
+screen_chat_exit(void)
+{
+       screen_text_deinit(&text);
+}
+
+static void
+screen_chat_open(struct mpdclient *c)
+{
+       (void) check_chat_support(c);
+}
+
+static void
+screen_chat_resize(int cols, int rows)
+{
+       screen_text_resize(&text, cols, rows);
+}
+
+static void
+screen_chat_paint(void)
+{
+       screen_text_paint(&text);
+}
+
+static void
+process_message(struct mpd_message *message)
+{
+       char *message_text;
+
+       assert(message != NULL);
+       /* You'll have to move this out of screen_chat, if you want to use
+          client-to-client messages anywhere else */
+       assert(g_strcmp0(mpd_message_get_channel(message), chat_channel) == 0);
+
+       message_text = utf8_to_locale(mpd_message_get_text(message));
+       screen_text_append(&text, message_text);
+       g_free(message_text);
+
+       screen_chat_paint();
+}
+
+static void
+screen_chat_update(struct mpdclient *c)
+{
+       if (check_chat_support(c) && (c->events & MPD_IDLE_MESSAGE)) {
+               if (!mpdclient_send_read_messages(c))
+                       return;
+
+               struct mpd_message *message;
+               while ((message = mpdclient_recv_message(c)) != NULL) {
+                       process_message(message);
+                       mpd_message_free(message);
+               }
+
+               mpdclient_finish_command(c);
+
+               c->events &= ~MPD_IDLE_MESSAGE;
+       }
+}
+
+static void
+screen_chat_send_message(struct mpdclient *c, char *msg)
+{
+       char *utf8 = locale_to_utf8(msg);
+
+       (void) mpdclient_cmd_send_message(c, chat_channel, utf8);
+       g_free(utf8);
+}
+
+static bool
+screen_chat_cmd(struct mpdclient *c, command_t cmd)
+{
+       if (screen_text_cmd(&text, c, cmd))
+               return true;
+
+       if (cmd == CMD_PLAY) {
+               char *message = screen_readln(_("Your message"), NULL, NULL, NULL);
+
+               /* the user entered an empty line */
+               if (message == NULL)
+                       return true;
+
+               if (check_chat_support(c))
+                       screen_chat_send_message(c, message);
+               else
+                       screen_status_message(_("Message could not be sent"));
+
+               g_free(message);
+
+               return true;
+       }
+
        return false;
 }
 
+static const char *
+screen_chat_title(G_GNUC_UNUSED char *s, G_GNUC_UNUSED size_t size)
+{
+       return _("Chat");
+}
+
 const struct screen_functions screen_chat = {
+       .init = screen_chat_init,
+       .exit = screen_chat_exit,
+       .open = screen_chat_open,
+       /* close */
+       .resize = screen_chat_resize,
+       .paint = screen_chat_paint,
+       .update = screen_chat_update,
        .cmd = screen_chat_cmd,
+       .get_title = screen_chat_title,
 };
index ed4db1fc2f668d17411ab662a0efc0486aadadc5..913ab5fa80884521a2da31c0faf29a1777b95cd7 100644 (file)
@@ -181,7 +181,7 @@ static const struct help_text_row help_text[] = {
        { 0, CMD_NONE, NULL },
        { 1, CMD_NONE, N_("Chat screen") },
        { 2, CMD_NONE, NULL },
-       { 0, CMD_PLAY, N_("Write a message (not yet implemented)") },
+       { 0, CMD_PLAY, N_("Write a message") },
 #endif
 #ifdef ENABLE_KEYDEF_SCREEN
        { 0, CMD_NONE, NULL },