# HG changeset patch # User Cristi Magherusan # Date 1186938223 -10800 # Node ID 3a77e835874f6888897f2f4b4524cb293e4c128d # Parent c8d0d7bf26d4f3dac6ed871a2fadff8ef7eb3565# Parent 3da640de0e991082feec4f4bfc73864db889653a merge diff -r c8d0d7bf26d4 -r 3a77e835874f src/audacious/Makefile --- a/src/audacious/Makefile Sat Aug 11 01:49:26 2007 +0300 +++ b/src/audacious/Makefile Sun Aug 12 20:03:43 2007 +0300 @@ -36,6 +36,7 @@ HEADERS = \ auddrct.h \ configdb.h \ + custom_uri.h \ dbus.h \ discovery.h \ eventqueue.h \ @@ -68,6 +69,7 @@ auddrct.c \ build_stamp.c \ configdb.c \ + custom_uri.c \ discovery.c \ dnd.c \ dock.c \ diff -r c8d0d7bf26d4 -r 3a77e835874f src/audacious/custom_uri.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/audacious/custom_uri.c Sun Aug 12 20:03:43 2007 +0300 @@ -0,0 +1,59 @@ +/* + * Audacious + * Copyright (c) 2007 William Pitcock + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; under version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#include "custom_uri.h" + +mowgli_dictionary_t *uri_type_dict = NULL; + +void uri_set_plugin(const gchar *uri, InputPlugin *ip) +{ + g_return_if_fail(uri != NULL); + g_return_if_fail(ip != NULL); + + if (uri_type_dict == NULL) + uri_type_dict = mowgli_dictionary_create(strcasecmp); + else if (mowgli_dictionary_find(uri_type_dict, uri)) + mowgli_dictionary_delete(uri_type_dict, uri); + mowgli_dictionary_add(uri_type_dict, uri, ip); +} + +InputPlugin *uri_get_plugin(const gchar *filename) +{ + gchar *uri, *pos; + InputPlugin *ip; + + if (filename == NULL) + return NULL; + + if (uri_type_dict == NULL) + return NULL; + + pos = strstr(filename, "://"); + if (pos) + uri = g_strndup(filename, pos - filename + 3); + else + return NULL; + + ip = mowgli_dictionary_retrieve(uri_type_dict, uri); + + g_free(uri); + + return ip; +} diff -r c8d0d7bf26d4 -r 3a77e835874f src/audacious/custom_uri.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/audacious/custom_uri.h Sun Aug 12 20:03:43 2007 +0300 @@ -0,0 +1,36 @@ +/* + * Audacious + * Copyright (c) 2007 William Pitcock + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; under version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#include +#include + +#include + +#ifndef __AUDACIOUS_CUSTOM_URI_H__ +#define __AUDACIOUS_CUSTOM_URI_H__ + +G_BEGIN_DECLS + +InputPlugin *uri_get_plugin(const gchar *filename); +void uri_set_plugin(const gchar *uri, InputPlugin *ip); + +G_END_DECLS + +#endif diff -r c8d0d7bf26d4 -r 3a77e835874f src/audacious/dbus-service.h --- a/src/audacious/dbus-service.h Sat Aug 11 01:49:26 2007 +0300 +++ b/src/audacious/dbus-service.h Sun Aug 12 20:03:43 2007 +0300 @@ -53,7 +53,6 @@ gboolean mpris_player_play(MprisPlayer *obj, GError **error); gboolean mpris_player_repeat(MprisPlayer *obj, gboolean rpt, GError **error); gboolean mpris_player_quit(MprisPlayer *obj, GError **error); -gboolean mpris_player_disconnect(MprisPlayer *obj, GError **error); gboolean mpris_player_get_status(MprisPlayer *obj, gint *status, GError **error); gboolean mpris_player_get_metadata(MprisTrackList *obj, gint pos, @@ -70,13 +69,11 @@ TRACK_CHANGE_SIG, STATUS_CHANGE_SIG, CAPS_CHANGE_SIG, - DISCONNECTED, LAST_SIG }; gboolean mpris_player_emit_track_change(MprisPlayer *obj, GError **error); gboolean mpris_player_emit_status_change(MprisPlayer *obj, GError **error); gboolean mpris_player_emit_caps_change(MprisPlayer *obj, GError **error); -gboolean mpris_player_emit_disconnected(MprisPlayer *obj, GError **error); // MPRIS /TrackList gboolean mpris_tracklist_get_metadata(MprisTrackList *obj, gint pos, diff -r c8d0d7bf26d4 -r 3a77e835874f src/audacious/dbus.c --- a/src/audacious/dbus.c Sat Aug 11 01:49:26 2007 +0300 +++ b/src/audacious/dbus.c Sun Aug 12 20:03:43 2007 +0300 @@ -208,13 +208,9 @@ return TRUE; } gboolean mpris_player_quit(MprisPlayer *obj, GError **error) { - // TODO: emit disconnected signal mainwin_quit_cb(); return TRUE; } -gboolean mpris_player_disconnect(MprisPlayer *obj, GError **error) { - return FALSE; -} gboolean mpris_player_get_status(MprisPlayer *obj, gint *status, GError **error) { return FALSE; @@ -258,11 +254,6 @@ return TRUE; } -gboolean mpris_player_emit_disconnected(MprisPlayer *obj, GError **error) { - g_signal_emit(obj, signals[DISCONNECTED], 0, NULL); - return TRUE; -} - // MPRIS /TrackList gboolean mpris_tracklist_get_metadata(MprisTrackList *obj, gint pos, GHashTable *metadata, GError **error) { diff -r c8d0d7bf26d4 -r 3a77e835874f src/audacious/input.c --- a/src/audacious/input.c Sat Aug 11 01:49:26 2007 +0300 +++ b/src/audacious/input.c Sun Aug 12 20:03:43 2007 +0300 @@ -369,6 +369,26 @@ if (tmp != NULL && g_ascii_isdigit(*(tmp + 1))) *tmp = '\0'; + /* Check for plugins with custom URI:// strings */ + /* cue:// cdda:// tone:// tact:// */ + if ((ip = uri_get_plugin(filename)) != NULL && + input_is_enabled(ip->filename) == TRUE) + { + if (ip->is_our_file != NULL) + ret = ip->is_our_file(filename_proxy); + else + ret = 0; + if (ret > 0) + { + g_free(filename_proxy); + pr = g_new0(ProbeResult, 1); + pr->ip = ip; + return pr; + } + g_free(filename_proxy); + return NULL; + } + /* CD-Audio uses cdda:// dummy paths, no filedescriptor handling for it */ /* also cuesheet uses cue:// */ if (!g_strncasecmp(filename, "cdda://", 7) || @@ -609,7 +629,7 @@ tuple_associate_string(tuple, "file-path", g_path_get_dirname(tmp)); - tmp = tuple_formatter_process_string(tuple, cfg.gentitle_format); + tmp = tuple_formatter_process_string(tuple, get_gentitle_format()); if (tmp != NULL && *tmp != '\0') { (*title) = str_to_utf8(tmp); g_free(tmp); diff -r c8d0d7bf26d4 -r 3a77e835874f src/audacious/main.c --- a/src/audacious/main.c Sat Aug 11 01:49:26 2007 +0300 +++ b/src/audacious/main.c Sun Aug 12 20:03:43 2007 +0300 @@ -453,7 +453,7 @@ } const gchar * -xmms_get_gentitle_format(void) +get_gentitle_format(void) { guint titlestring_preset = cfg.titlestring_preset; diff -r c8d0d7bf26d4 -r 3a77e835874f src/audacious/mpris_player.xml --- a/src/audacious/mpris_player.xml Sat Aug 11 01:49:26 2007 +0300 +++ b/src/audacious/mpris_player.xml Sun Aug 12 20:03:43 2007 +0300 @@ -42,9 +42,6 @@ - - - @@ -78,6 +75,5 @@ - diff -r c8d0d7bf26d4 -r 3a77e835874f src/audacious/playback.c --- a/src/audacious/playback.c Sat Aug 11 01:49:26 2007 +0300 +++ b/src/audacious/playback.c Sun Aug 12 20:03:43 2007 +0300 @@ -224,7 +224,10 @@ playback->plugin->stop(playback); if (playback->thread != NULL) + { g_thread_join(playback->thread); + playback->thread = NULL; + } free_vis_data(); ip_data.paused = FALSE; @@ -334,7 +337,6 @@ playback->plugin = entry->decoder; playback->output = &psuedo_output_plugin; playback->filename = g_strdup(entry->filename); - playback->thread = g_thread_self(); playback->pb_ready_mutex = g_mutex_new(); playback->pb_ready_cond = g_cond_new(); playback->pb_ready_val = 0; @@ -342,7 +344,7 @@ set_current_input_playback(playback); - g_thread_create(playback_monitor_thread, playback, TRUE, NULL); + playback->thread = g_thread_create(playback_monitor_thread, playback, TRUE, NULL); return TRUE; } diff -r c8d0d7bf26d4 -r 3a77e835874f src/audacious/playlist.c --- a/src/audacious/playlist.c Sat Aug 11 01:49:26 2007 +0300 +++ b/src/audacious/playlist.c Sun Aug 12 20:03:43 2007 +0300 @@ -238,7 +238,8 @@ /* entry is still around */ formatter = tuple_get_string(tuple, "formatter"); - entry->title = tuple_formatter_process_string(tuple, formatter ? formatter : cfg.gentitle_format); + entry->title = tuple_formatter_process_string(tuple, formatter ? + formatter : get_gentitle_format()); entry->length = tuple_get_int(tuple, "length"); entry->tuple = tuple; @@ -674,7 +675,8 @@ PLAYLIST_UNLOCK( playlist->mutex ); if (tuple != NULL) { const gchar *formatter = tuple_get_string(tuple, "formatter"); - entry->title = tuple_formatter_process_string(tuple, formatter ? formatter : cfg.gentitle_format); + entry->title = tuple_formatter_process_string(tuple, formatter ? + formatter : get_gentitle_format()); entry->length = tuple_get_int(tuple, "length"); entry->tuple = tuple; } @@ -919,7 +921,10 @@ guint playlist_add_url(Playlist * playlist, const gchar * url) { - return playlist_ins_url(playlist, url, -1); + guint entries; + entries = playlist_ins_url(playlist, url, -1); +// printf("playlist_add_url: entries = %d\n", entries); + return entries; } guint @@ -965,19 +970,17 @@ gint pos) { gchar *tmp; - gint i = 1, entries = 0; - gboolean first = TRUE; - guint firstpos = 0; - gboolean success = FALSE; + gint entries = 0; gchar *decoded = NULL; g_return_val_if_fail(playlist != NULL, 0); g_return_val_if_fail(string != NULL, 0); - playlistwin_update_list(playlist); +// playlistwin_update_list(playlist); // is this necessary? --yaz while (*string) { GList *node; + guint i = 0; tmp = strchr(string, '\n'); if (tmp) { if (*(tmp - 1) == '\r') @@ -994,8 +997,7 @@ if (is_playlist_name(decoded)) { i = playlist_load_ins(playlist, decoded, pos); } - else { - success = playlist_ins(playlist, decoded, pos); + else if (playlist_ins(playlist, decoded, pos)) { i = 1; } } @@ -1008,11 +1010,6 @@ entries += i; - if (first) { - first = FALSE; - firstpos = pos; - } - if (pos >= 0) pos += i; if (!tmp) @@ -1601,14 +1598,14 @@ gboolean playlist_load(Playlist * playlist, const gchar * filename) { - gboolean ret = FALSE; + guint ret = 0; g_return_val_if_fail(playlist != NULL, FALSE); playlist->loading_playlist = TRUE; ret = playlist_load_ins(playlist, filename, -1); playlist->loading_playlist = FALSE; - return ret; + return ret ? TRUE : FALSE; } void @@ -1751,7 +1748,8 @@ { PlaylistContainer *plc; gchar *ext; - + gint old_len, new_len; + g_return_val_if_fail(playlist != NULL, 0); g_return_val_if_fail(filename != NULL, 0); @@ -1761,12 +1759,14 @@ g_return_val_if_fail(plc != NULL, 0); g_return_val_if_fail(plc->plc_read != NULL, 0); + old_len = playlist_get_length(playlist); plc->plc_read(filename, pos); + new_len = playlist_get_length(playlist); playlist_generate_shuffle_list(playlist); playlistwin_update_list(playlist); - return 1; + return new_len - old_len; } GList * diff -r c8d0d7bf26d4 -r 3a77e835874f src/audacious/plugin.h --- a/src/audacious/plugin.h Sat Aug 11 01:49:26 2007 +0300 +++ b/src/audacious/plugin.h Sun Aug 12 20:03:43 2007 +0300 @@ -319,7 +319,7 @@ G_BEGIN_DECLS /* So that input plugins can get the title formatting information */ -G_CONST_RETURN gchar * xmms_get_gentitle_format(void); +G_CONST_RETURN gchar * get_gentitle_format(void); /* So that output plugins can communicate with effect plugins */ EffectPlugin *get_current_effect_plugin(void); @@ -329,5 +329,6 @@ G_END_DECLS #include "audacious/mime.h" +#include "audacious/custom_uri.h" #endif diff -r c8d0d7bf26d4 -r 3a77e835874f src/audacious/tuple.c --- a/src/audacious/tuple.c Sat Aug 11 01:49:26 2007 +0300 +++ b/src/audacious/tuple.c Sun Aug 12 20:03:43 2007 +0300 @@ -123,11 +123,13 @@ g_return_val_if_fail(tuple != NULL, FALSE); g_return_val_if_fail(field != NULL, FALSE); - g_return_val_if_fail(string != NULL, FALSE); if (mowgli_dictionary_find(tuple->dict, field)) tuple_disassociate(tuple, field); + if (string == NULL) + return TRUE; + value = mowgli_heap_alloc(tuple_value_heap); value->type = TUPLE_STRING; value->value.string = g_strdup(string); diff -r c8d0d7bf26d4 -r 3a77e835874f src/audacious/tuple.h --- a/src/audacious/tuple.h Sat Aug 11 01:49:26 2007 +0300 +++ b/src/audacious/tuple.h Sun Aug 12 20:03:43 2007 +0300 @@ -41,5 +41,6 @@ TupleValueType tuple_get_value_type(Tuple *tuple, const gchar *field); const gchar *tuple_get_string(Tuple *tuple, const gchar *field); int tuple_get_int(Tuple *tuple, const gchar *field); +#define tuple_free(x) mowgli_object_unref(x); #endif diff -r c8d0d7bf26d4 -r 3a77e835874f src/audacious/tuple_formatter.c --- a/src/audacious/tuple_formatter.c Sat Aug 11 01:49:26 2007 +0300 +++ b/src/audacious/tuple_formatter.c Sun Aug 12 20:03:43 2007 +0300 @@ -25,6 +25,14 @@ #include "tuple.h" #include "tuple_formatter.h" +#define _DEBUG + +#ifdef _DEBUG +# define _TRACE(fmt, ...) g_print("[tuple-fmt] %s(%d) " fmt "\n", __FILE__, __LINE__, __VA_ARGS__); +#else +# define _TRACE(fmt, ...) +#endif + /* * the tuple formatter: * @@ -72,14 +80,19 @@ ctx = g_new0(TupleFormatterContext, 1); ctx->str = g_string_new(""); + _TRACE("parsing <%s>", string); + /* parsers are ugly */ for (iter = string; *iter != '\0'; iter++) { /* if it's raw text, just copy the byte */ - if (*iter != '$' && *iter != '%' && (*iter != '}' || (*iter == '}' && level > 0))) + if (*iter != '$' && *iter != '%' && *iter != '}' ) + { + g_string_append_c(ctx->str, *iter); + } + else if (*iter == '}' && level > 0) { level--; - g_string_append_c(ctx->str, *iter); } else if (g_str_has_prefix(iter, "${") == TRUE) { @@ -87,13 +100,12 @@ GString *argument = g_string_new(""); GString *sel = expression; gchar *result; - gboolean rewind = FALSE; + level++; for (iter += 2; *iter != '\0'; iter++) { if (*iter == ':') { - level++; if (sel != argument) { sel = argument; @@ -115,12 +127,10 @@ else if (*iter == '}' && (sel == argument)) { level--; - if (level + 1 > 0) - { - iter++; - rewind = *(iter - 1) == '}' && *iter != '}'; - break; - } + if (level == 0) + break; + else + g_string_append_c(sel, *iter); } else if (*iter == '}' && ((sel != argument))) break; @@ -147,9 +157,6 @@ if (*iter == '\0') break; - - if (rewind) - iter--; } else if (g_str_has_prefix(iter, "%{") == TRUE) { @@ -157,14 +164,19 @@ GString *argument = g_string_new(""); GString *sel = expression; gchar *result; - gboolean rewind = FALSE; + level++; for (iter += 2; *iter != '\0'; iter++) { if (*iter == ':') { - level++; - sel = argument; + if (sel != argument) + { + sel = argument; + continue; + } + else + g_string_append_c(sel, *iter); continue; } @@ -179,12 +191,10 @@ else if (*iter == '}' && (sel == argument)) { level--; - if (level + 1 > 0) - { - iter++; - rewind = *(iter - 1) == '}' && *iter != '}'; - break; - } + if (level == 0) + break; + else + g_string_append_c(sel, *iter); } else if (*iter == '}' && ((sel != argument))) break; @@ -211,9 +221,6 @@ if (*iter == '\0') break; - - if (rewind) - iter--; } } @@ -221,6 +228,8 @@ g_string_free(ctx->str, TRUE); g_free(ctx); + _TRACE("parsed <%s> as <%s>", string, out); + return out; } @@ -371,35 +380,64 @@ return (tuple_get_value_type(tuple, expression) != TUPLE_UNKNOWN) ? TRUE : FALSE; } -/* builtin-keyword: ${==arg1,arg2}, returns TRUE if and match. */ +/* builtin-keyword: ${==arg1,arg2}, returns TRUE if and match. + and can also be raw text, which should be enclosed in "double quotes". */ static gboolean tuple_formatter_expression_match(Tuple *tuple, const gchar *expression) { gchar **args = g_strsplit(expression, ",", 2); - gchar *arg1, *arg2; + gchar *arg1 = NULL, *arg2 = NULL; gint ret; - if (tuple_get_value_type(tuple, args[0]) == TUPLE_UNKNOWN) + if (args[0][0] == '\"') /* check if arg1 is "raw text" */ + { + if ( strlen(args[0]) > 1 ) + { + args[0][strlen(args[0]) - 1] = '\0'; + arg1 = g_strdup(&(args[0][1])); + args[0][strlen(args[0]) - 1] = '\"'; + } + else /* bad formatted arg */ + return FALSE; + } + else if (tuple_get_value_type(tuple, args[0]) == TUPLE_UNKNOWN) + { + g_strfreev(args); + return FALSE; + } + + if (args[1][0] == '\"') /* check if arg2 is "raw text" */ + { + if ( strlen(args[1]) > 1 ) + { + args[1][strlen(args[1]) - 1] = '\0'; + arg2 = g_strdup(&(args[1][1])); + args[1][strlen(args[1]) - 1] = '\"'; + } + else /* bad formatted arg */ + return FALSE; + } + else if (tuple_get_value_type(tuple, args[1]) == TUPLE_UNKNOWN) { g_strfreev(args); return FALSE; } - if (tuple_get_value_type(tuple, args[1]) == TUPLE_UNKNOWN) + if (!arg1) /* if arg1 is not "raw text", get the tuple value */ { - g_strfreev(args); - return FALSE; + if (tuple_get_value_type(tuple, args[0]) == TUPLE_STRING) + arg1 = g_strdup(tuple_get_string(tuple, args[0])); + else + arg1 = g_strdup_printf("%d", tuple_get_int(tuple, args[0])); } - if (tuple_get_value_type(tuple, args[0]) == TUPLE_STRING) - arg1 = g_strdup(tuple_get_string(tuple, args[0])); - else - arg1 = g_strdup_printf("%d", tuple_get_int(tuple, args[0])); - - if (tuple_get_value_type(tuple, args[1]) == TUPLE_STRING) - arg2 = g_strdup(tuple_get_string(tuple, args[1])); - else - arg2 = g_strdup_printf("%d", tuple_get_int(tuple, args[1])); + if (!arg2) /* if arg2 is not "raw text", get the tuple value */ + { + if (tuple_get_value_type(tuple, args[1]) == TUPLE_STRING) + arg2 = g_strdup(tuple_get_string(tuple, args[1])); + else + arg2 = g_strdup_printf("%d", tuple_get_int(tuple, args[1])); + } ret = g_ascii_strcasecmp(arg1, arg2); g_free(arg1); @@ -409,7 +447,8 @@ return ret ? FALSE : TRUE; } -/* builtin-keyword: ${!=arg1,arg2}. returns TRUE if and don't match. */ +/* builtin-keyword: ${!=arg1,arg2}. returns TRUE if and don't match. + and can also be raw text, which should be enclosed in "double quotes". */ static gboolean tuple_formatter_expression_nonmatch(Tuple *tuple, const gchar *expression) { diff -r c8d0d7bf26d4 -r 3a77e835874f src/audacious/ui_skinned_horizontal_slider.c --- a/src/audacious/ui_skinned_horizontal_slider.c Sat Aug 11 01:49:26 2007 +0300 +++ b/src/audacious/ui_skinned_horizontal_slider.c Sun Aug 12 20:03:43 2007 +0300 @@ -219,10 +219,11 @@ widget->allocation = *allocation; widget->allocation.x *= (1+priv->double_size); widget->allocation.y *= (1+priv->double_size); + if (priv->knob_height == priv->height) - priv->knob_height = allocation->height; - priv->width = allocation->width; - priv->height = allocation->height; + priv->knob_height = allocation->height/(priv->double_size ? 2 : 1); + priv->width = allocation->width/(priv->double_size ? 2 : 1); + priv->height = allocation->height/(priv->double_size ? 2 : 1); if (GTK_WIDGET_REALIZED (widget)) gdk_window_move_resize(widget->window, widget->allocation.x, widget->allocation.y, allocation->width, allocation->height); diff -r c8d0d7bf26d4 -r 3a77e835874f src/audacious/ui_skinned_playlist.c --- a/src/audacious/ui_skinned_playlist.c Sat Aug 11 01:49:26 2007 +0300 +++ b/src/audacious/ui_skinned_playlist.c Sun Aug 12 20:03:43 2007 +0300 @@ -923,7 +923,7 @@ playlistwin_update_list(playlist_get_active()); } priv->drag_pos = nr; - } else { + } else if (cfg.show_filepopup_for_tuple) { gint pos = ui_skinned_playlist_get_position(widget, event->x, event->y); gint cur_pos = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "popup_position")); if (pos != cur_pos) { diff -r c8d0d7bf26d4 -r 3a77e835874f src/tests/tuple_formatter_test.c --- a/src/tests/tuple_formatter_test.c Sat Aug 11 01:49:26 2007 +0300 +++ b/src/tests/tuple_formatter_test.c Sun Aug 12 20:03:43 2007 +0300 @@ -130,6 +130,56 @@ } g_free(tstr); + tuple_associate_string(tuple, "sheep", ""); + + tstr = tuple_formatter_process_string(tuple, "${?splork:${splork} - }${?sheep:${sheep} - }${splork}"); + if (g_ascii_strcasecmp(tstr, "moo - - moo")) + { + g_print("fail 13: '%s'\n", tstr); + return EXIT_FAILURE; + } + g_free(tstr); + + tstr = tuple_formatter_process_string(tuple, "${?splork:${splork} - }${?sheep:${sheep} - }${splork}"); + if (g_ascii_strcasecmp(tstr, "moo - - moo")) + { + g_print("fail 14: '%s'\n", tstr); + return EXIT_FAILURE; + } + g_free(tstr); + + tstr = tuple_formatter_process_string(tuple, "${==splork,\"moo\":const text field matches}"); + if (g_ascii_strcasecmp(tstr, "const text field matches")) + { + g_print("fail 15: '%s'\n", tstr); + return EXIT_FAILURE; + } + g_free(tstr); + + tstr = tuple_formatter_process_string(tuple, "${==\"moo\",\"moo\":const text fields match}"); + if (g_ascii_strcasecmp(tstr, "const text fields match")) + { + g_print("fail 16: '%s'\n", tstr); + return EXIT_FAILURE; + } + g_free(tstr); + + tstr = tuple_formatter_process_string(tuple, "${!=splork,\"muu\":const text field doesn't match}"); + if (g_ascii_strcasecmp(tstr, "const text field doesn't match")) + { + g_print("fail 17: '%s'\n", tstr); + return EXIT_FAILURE; + } + g_free(tstr); + + tstr = tuple_formatter_process_string(tuple, "${!=\"moo\",\"muu\":const text fields do not match}"); + if (g_ascii_strcasecmp(tstr, "const text fields do not match")) + { + g_print("fail 18: '%s'\n", tstr); + return EXIT_FAILURE; + } + g_free(tstr); + mowgli_object_unref(tuple); return EXIT_SUCCESS;