#include #include #include "gm-mcp-negotiate.h" #include "gm-mcp.h" #include "gm-mcp-session.h" #include "gm-mcp-package.h" #include "../gm-debug.h" #include "../gm-support.h" #define GM_MCP_NEGOTIATE_GET_PRIVATE(object)( \ G_TYPE_INSTANCE_GET_PRIVATE((object), \ GM_TYPE_MCP_NEGOTIATE, GmMcpNegotiatePrivate)) typedef struct _PackageInfo { GmMcpPackageClass *klass; gdouble version; } PackageInfo; struct _GmMcpNegotiatePrivate { GList *packages; }; /* Signals enum { PROTO NUM_SIGNALS }; static guint gm_mcp_negotiate_signals[NUM_SIGNALS] = {0};*/ void gm_mcp_negotiate_handle_simple(GmMcpPackage *package, gchar *suffix, GList *fields); static void gm_mcp_negotiate_init(GmMcpNegotiate *self); static void gm_mcp_negotiate_class_init(GmMcpNegotiateClass *klass); //static void gm_mcp_negotiate_class_finalize(gpointer klass, // gpointer klass_data); static gpointer gm_mcp_negotiate_parent_class = NULL; static void gm_mcp_negotiate_class_intern_init(gpointer klass) { gm_mcp_negotiate_parent_class = g_type_class_peek_parent(klass); gm_mcp_negotiate_class_init((GmMcpNegotiateClass *) klass); } GType gm_mcp_negotiate_get_type() { static GType g_define_type_id = 0; if (G_UNLIKELY(g_define_type_id == 0)) { static const GTypeInfo g_define_type_info = { sizeof (GmMcpNegotiateClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) gm_mcp_negotiate_class_intern_init, (GClassFinalizeFunc) NULL, //gm_mcp_negotiate_class_finalize, NULL, /* class_data */ sizeof (GmMcpNegotiate), 0, /* n_preallocs */ (GInstanceInitFunc) gm_mcp_negotiate_init, NULL /* value_table */ }; g_define_type_id = g_type_register_static(GM_TYPE_MCP_PACKAGE, "GmMcpNegotiate", &g_define_type_info, (GTypeFlags) 0); } return g_define_type_id; \ } static void gm_mcp_negotiate_finalize(GObject *object) { //GmMcpNegotiate *obj = GM_MCP_NEGOTIATE(object); G_OBJECT_CLASS(gm_mcp_negotiate_parent_class)->finalize(object); } /*static void gm_mcp_negotiate_class_finalize(gpointer klass, gpointer klass_data) { GmMcpPackageClass *pklass = GM_MCP_PACKAGE_CLASS(klass); g_list_free(pklass->depends); g_list_free(pklass->overrides); }*/ static void gm_mcp_negotiate_class_init(GmMcpNegotiateClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS(klass); GmMcpPackageClass *pklass = GM_MCP_PACKAGE_CLASS(klass); object_class->finalize = gm_mcp_negotiate_finalize; /*gm_mcp_negotiate_signals[PROTO] = g_signal_new("proto", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GmMcpNegotiateClass, proto), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);*/ pklass->name = "mcp-negotiate"; pklass->handle_simple = &gm_mcp_negotiate_handle_simple; g_type_class_add_private(object_class, sizeof(GmMcpNegotiatePrivate)); } static void gm_mcp_negotiate_init(GmMcpNegotiate *obj) { obj->priv = GM_MCP_NEGOTIATE_GET_PRIVATE(obj); obj->priv->packages = NULL; } PackageInfo * gm_mcp_negotiate_find_package(GmMcpNegotiate *package, gchar *name) { PackageInfo *pinfo; GList *elem; for (elem = package->priv->packages; elem; elem = elem->next) { pinfo = (PackageInfo *)(elem->data); if (strcasecmp(pinfo->klass->name, name) == 0) { return pinfo; } } return NULL; } void gm_mcp_negotiate_fix_overrides(GmMcpNegotiate *package) { GList *l, *item, *over; PackageInfo *pinfo, *pover; gchar *name; l = g_list_copy(package->priv->packages); for (item = l; item; item = item->next) { pinfo = (PackageInfo *)(item); for (over = pinfo->klass->overrides; over; over = over->next) { name = (gchar *)(over->data); if ((pover = gm_mcp_negotiate_find_package(package, name))) { gm_debug_msg(DEBUG_MCP, "GmMcpNegotiate.FixOverrides: package %s " "overrides %s", pinfo->klass->name, pover->klass->name); package->priv->packages = g_list_remove( package->priv->packages, pover); } } } g_list_free(l); } void gm_mcp_negotiate_fix_depends(GmMcpNegotiate *package) { PackageInfo *pinfo, *pdep; GList *l, *item, *dep; gchar *name; l = g_list_copy(package->priv->packages); for (item = l; item; item = item->next) { pinfo = (PackageInfo *)(item->data); for (dep = pinfo->klass->depends; dep; dep = dep->next) { name = (gchar *)(dep->data); if (!(pdep = gm_mcp_negotiate_find_package(package, name))) { gm_debug_msg(DEBUG_MCP, "GmMcpNegotiate.FixDepends: package %s depends " "on %s, but %s is not supported", pinfo->klass->name, name, name); // Remove package because depencendies are not met package->priv->packages = g_list_remove( package->priv->packages, pinfo); break; } else { // Make sure this dependency is loaded before the package package->priv->packages = g_list_remove( package->priv->packages, pdep); package->priv->packages = g_list_insert_before( package->priv->packages, g_list_find(package->priv->packages, pinfo), pdep); } } } g_list_free(l); } /* Public */ GmMcpNegotiate * gm_mcp_negotiate_new() { GmMcpNegotiate *obj = GM_MCP_NEGOTIATE(g_object_new(GM_TYPE_MCP_NEGOTIATE, NULL)); return obj; } /* Private */ gboolean gm_mcp_negotiate_send_can(GmMcpPackageClass *klass, gpointer user_data) { GmMcpNegotiate *package = GM_MCP_NEGOTIATE(user_data); gchar *min_v, *max_v; min_v = g_strdup_printf("%'.1f", klass->min_version); gm_fix_decimal_point_rev(min_v, strlen(min_v)); max_v = g_strdup_printf("%'.1f", klass->max_version); gm_fix_decimal_point_rev(max_v, strlen(max_v)); gm_mcp_session_send_simple(GM_MCP_PACKAGE_SESSION(package), "mcp-negotiate-can", "package", klass->name, "min-version", min_v, "max-version", max_v, NULL); g_free(min_v); g_free(max_v); return FALSE; } void gm_mcp_negotiate_handle_simple(GmMcpPackage *package, gchar *suffix, GList *fields) { gchar const *pname; GmMcpPackageClass *pklass; GmMcpNegotiate *negotiate = GM_MCP_NEGOTIATE(package); PackageInfo *pinfo; double version; gchar const *min_v, *max_v; gchar *cmin, *cmax; GList *elem; if (strcasecmp(suffix, "can") == 0) { // Fields has package, min-version, max-version pname = gm_mcp_find_value(fields, "package"); pklass = gm_mcp_session_find_package_class(pname); if (pklass) { min_v = gm_mcp_find_value(fields, "min-version"); cmin = gm_fix_decimal_point(g_strdup(min_v), strlen(min_v)); max_v = gm_mcp_find_value(fields, "max-version"); cmax = gm_fix_decimal_point(g_strdup(max_v), strlen(max_v)); version = gm_mcp_get_version(pklass->min_version, pklass->max_version, g_ascii_strtod(min_v, NULL), g_ascii_strtod(max_v, NULL)); g_free(cmin); g_free(cmax); if (version > 0.0) { gm_debug_msg(DEBUG_MCP, "GmMcpNegotiate.HandleSimple: %s, " "package is supported", pname); pinfo = g_new(PackageInfo, 1); pinfo->klass = pklass; pinfo->version = version; negotiate->priv->packages = g_list_append( negotiate->priv->packages, pinfo); } else { gm_debug_msg(DEBUG_MCP, "GmMcpNegotiate.HandleSimple: %s, package " "supported but wrong version!", pname); } } else { gm_debug_msg(DEBUG_MCP, "GmMcpNegotiate.HandleSimple: %s, package is not " "supported!", pname); } } else if (strcasecmp(suffix, "end") == 0) { gm_mcp_session_package_class_for_each(gm_mcp_negotiate_send_can, (gpointer)(negotiate)); gm_mcp_session_send_simple(GM_MCP_PACKAGE_SESSION(negotiate), "mcp-negotiate-end", NULL); gm_mcp_negotiate_fix_overrides(negotiate); gm_mcp_negotiate_fix_depends(negotiate); for (elem = negotiate->priv->packages; elem; elem = elem->next) { pinfo = (PackageInfo *)(elem->data); gm_mcp_session_create_package(GM_MCP_PACKAGE_SESSION(negotiate), pinfo->klass, pinfo->version); g_free(pinfo); } g_list_free(negotiate->priv->packages); negotiate->priv->packages = NULL; } }