#include #include #include #include #include #include #include #include #include "common.h" #define COMMON_TAG_COUNT 9 static gchar *common_tags[] = { _("ALBUM"), _("ARTIST"), _("COMMENT"), _("COMPOSER"), _("DATE"), _("GENRE"), _("PERFORMER"), _("TITLE"), _("TRACKNUMBER") }; enum { COL_NAME, COL_VALUE, N_COLS }; typedef struct { GtkWidget *window; GtkWidget *location; GtkWidget *techinfo; GtkWidget *metadata; IAPEDecompress *pAPEDecompress; gchar *current_filename; } MAC_META_INFO; typedef struct { GtkWidget *tag_window; GtkWidget *field_name_widget; GtkWidget *field_value_widget; gboolean is_edit; } MAC_META_TAG; static MAC_META_INFO mac_info; static MAC_META_TAG mac_tag; #ifdef __cplusplus extern "C"{ #endif /* callbacks of the whole APE info window */ static void cb_info_box_close(GtkWidget *widget, gpointer data); static void cb_info_box_destroy(GtkWidget *widget, gpointer data); static gint cb_info_box_delete(GtkWidget *widget, GdkEvent *event, gpointer data ); /* callbacks of the meta data related */ static void cb_metadata_add(GtkWidget *widget, gpointer data); static void cb_metadata_edit(GtkWidget *widget, gpointer data); static void cb_metadata_remove(GtkWidget *widget, gpointer data); static void cb_metadata_update_file(GtkWidget *widget, gpointer data); /* callbacks of tag editing related */ static void cb_tag_window_ok(GtkWidget *widget, gpointer data); static void cb_tag_window_cancel(GtkWidget *widget, gpointer data); static void cb_tag_window_destroy(GtkWidget *widget, gpointer data); static gint cb_tag_window_delete(GtkWidget *widget, GdkEvent *event, gpointer data ); /* internal util functions */ static void insert_metadata(GtkListStore* metadata, CAPETag *pAPETag); static void insert_techinfo(GtkListStore* techinfo, IAPEDecompress *pAPEDecompress); static void mac_tag_window_create(); static void mac_info_box_create(); /************************** * tag window related * **************************/ void cb_tag_window_destroy(GtkWidget *widget, gpointer data) { /* do some clean stuff of tag window */ mac_tag.tag_window = NULL; mac_tag.field_name_widget = NULL; mac_tag.field_value_widget = NULL; mac_tag.is_edit = FALSE; } gint cb_tag_window_delete(GtkWidget *widget, GdkEvent *event, gpointer data ) { /* Don't destroy the window */ gtk_widget_hide_all(mac_tag.tag_window); return TRUE; } void cb_tag_window_ok(GtkWidget *widget, gpointer data) { const gchar *field_name; gchar *field_value; GtkEntry *entry; GtkTextView *value_widget; GtkTextBuffer *value_buffer; GtkTextIter start_iter, end_iter; entry = GTK_ENTRY(GTK_BIN(mac_tag.field_name_widget)->child); field_name = gtk_entry_get_text(entry); value_widget = GTK_TEXT_VIEW(mac_tag.field_value_widget); value_buffer = gtk_text_view_get_buffer(value_widget); gtk_text_buffer_get_start_iter(value_buffer, &start_iter); gtk_text_buffer_get_end_iter(value_buffer, &end_iter); field_value = gtk_text_buffer_get_text(value_buffer, &start_iter, &end_iter, FALSE); if (mac_tag.is_edit) { /* Editing a tag */ GtkTreeSelection *selection; GtkTreeIter iter; GtkTreeModel *model; selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(mac_info.metadata)); if (gtk_tree_selection_get_selected(selection, &model, &iter)) { gtk_list_store_set((GtkListStore *)model, &iter, COL_VALUE, field_value, -1); } } else { /* Adding a tag */ GtkListStore *list_store; GtkTreeIter iter; list_store = (GtkListStore *)gtk_tree_view_get_model(GTK_TREE_VIEW(mac_info.metadata)); gtk_list_store_append(list_store, &iter); gtk_list_store_set(list_store, &iter, COL_NAME, field_name, COL_VALUE, field_value, -1); } g_free(field_value); gtk_widget_hide_all(mac_tag.tag_window); } void cb_tag_window_cancel(GtkWidget *widget, gpointer data) { gtk_widget_hide_all(mac_tag.tag_window); } /************************** * info box related * **************************/ void cb_info_box_destroy(GtkWidget *widget, gpointer data) { /* do some clean stuff of info box window */ mac_info.window = NULL; mac_info.location = NULL; mac_info.techinfo = NULL; mac_info.metadata = NULL; g_free(mac_info.current_filename); mac_info.current_filename = NULL; if (mac_info.pAPEDecompress) { delete mac_info.pAPEDecompress; } mac_info.pAPEDecompress = NULL; } gint cb_info_box_delete(GtkWidget *widget, GdkEvent *event, gpointer data ) { gtk_widget_hide_all(mac_info.window); return TRUE; } void cb_info_box_close(GtkWidget *widget, gpointer data) { gtk_widget_hide_all(mac_info.window); } /************************** * meta data related * **************************/ void cb_metadata_update_file(GtkWidget *widget, gpointer data) { GtkTreeIter iter; GtkTreeModel *model; gboolean res; /* remove all tags, then add one by one */ CAPETag *apeTag = (CAPETag *)mac_info.pAPEDecompress->GetInfo(APE_INFO_TAG); apeTag->ClearFields(); model = gtk_tree_view_get_model(GTK_TREE_VIEW(mac_info.metadata)); res = gtk_tree_model_get_iter_first(model, &iter); while (res) { gchar *name, *value; gtk_tree_model_get(model, &iter, COL_NAME, &name, COL_VALUE, &value, -1); wchar_t *utf16_name = GetUTF16FromUTF8((const str_utf8 *)name); apeTag->SetFieldString(utf16_name, value, TRUE); g_free(name); g_free(value); res = gtk_tree_model_iter_next(model, &iter); } if (apeTag->Save() != ERROR_SUCCESS) { printf("error update files, error code = %d\n", res); } } void cb_metadata_add(GtkWidget *widget, gpointer data) { GtkEntry *entry; GtkTextView *field_value; GtkTextBuffer *value_buffer; if (!mac_tag.tag_window) { mac_tag_window_create(); } entry = GTK_ENTRY(GTK_BIN(mac_tag.field_name_widget)->child); field_value = GTK_TEXT_VIEW(mac_tag.field_value_widget); value_buffer = gtk_text_view_get_buffer(field_value); gtk_widget_set_sensitive(mac_tag.field_name_widget, TRUE); gtk_entry_set_text(entry, ""); gtk_text_buffer_set_text(value_buffer, "", -1); mac_tag.is_edit = FALSE; gtk_window_set_title(GTK_WINDOW(mac_tag.tag_window), _("Adding a Tag")); gtk_widget_show_all(mac_tag.tag_window); } void cb_metadata_edit(GtkWidget *widget, gpointer data) { GtkEntry *entry; GtkTextView *field_value; GtkTextBuffer *value_buffer; GtkTreeSelection *selection; GtkTreeIter iter; GtkTreeModel *model; selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(mac_info.metadata)); if (!gtk_tree_selection_get_selected(selection, &model, &iter)) { return; } gchar *name; gchar *value; gtk_tree_model_get(model, &iter, COL_NAME, &name, COL_VALUE, &value, -1); if (!mac_tag.tag_window) { mac_tag_window_create(); } entry = GTK_ENTRY(GTK_BIN(mac_tag.field_name_widget)->child); field_value = GTK_TEXT_VIEW(mac_tag.field_value_widget); value_buffer = gtk_text_view_get_buffer(field_value); gtk_entry_set_text(entry, name); gtk_widget_set_sensitive(mac_tag.field_name_widget, FALSE); gtk_text_buffer_set_text(value_buffer, value, -1); g_free(name); g_free(value); mac_tag.is_edit = TRUE; gtk_window_set_title(GTK_WINDOW(mac_tag.tag_window), _("Editing a Tag")); gtk_widget_show_all(mac_tag.tag_window); } void cb_metadata_remove(GtkWidget *widget, gpointer data) { GtkTreeSelection *selection; GtkTreeIter iter; GtkTreeModel *model; selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(mac_info.metadata)); if (!gtk_tree_selection_get_selected(selection, &model, &iter)) { return; } gtk_list_store_remove(GTK_LIST_STORE(model), &iter); } /*************************** * internal util functions * ***************************/ void insert_metadata(GtkListStore* list_store, CAPETag *pAPETag) { GtkTreeIter iter; if (!list_store || !pAPETag) { return; } gtk_list_store_clear(list_store); BOOL bHasID3Tag = pAPETag->GetHasID3Tag(); BOOL bHasAPETag = pAPETag->GetHasAPETag(); if (bHasID3Tag || bHasAPETag) { CAPETagField * pTagField; int index = 0; while ((pTagField = pAPETag->GetTagField(index)) != NULL) { index ++; const wchar_t *field_name; char field_value[255]; gchar *name; field_name = pTagField->GetFieldName(); name = (gchar *)GetUTF8FromUTF16(field_name); memset(field_value, 0, 255); int size = 255; pAPETag->GetFieldString(field_name, (char *)field_value, &size, TRUE); gtk_list_store_append(list_store, &iter); gtk_list_store_set(list_store, &iter, COL_NAME, name, COL_VALUE, field_value, -1); g_free(name); } } } void insert_techinfo(GtkListStore* list_store, IAPEDecompress *pAPEDecompress) { GtkTreeIter iter; gchar *name, *value; if (!list_store || !pAPEDecompress) { return; } gtk_list_store_clear(list_store); /* APE Version */ name = _("Version"); value = g_strdup_printf("%.2f", (float)pAPEDecompress->GetInfo(APE_INFO_FILE_VERSION) / float(1000)); gtk_list_store_append(list_store, &iter); gtk_list_store_set(list_store, &iter, COL_NAME, name, COL_VALUE, value, -1); g_free(value); /* Compression Level */ name = _("Compression Level"); switch (pAPEDecompress->GetInfo(APE_INFO_COMPRESSION_LEVEL)) { case COMPRESSION_LEVEL_FAST: value = _("Fast"); break; case COMPRESSION_LEVEL_NORMAL: value = _("Normal"); break; case COMPRESSION_LEVEL_HIGH: value = _("High"); break; case COMPRESSION_LEVEL_EXTRA_HIGH: value = _("Extra High"); break; case COMPRESSION_LEVEL_INSANE: value = _("Insane"); break; } gtk_list_store_append(list_store, &iter); gtk_list_store_set(list_store, &iter, COL_NAME, name, COL_VALUE, value, -1); /* Format Flags */ name = _("Flags"); value = g_strdup_printf("%d", pAPEDecompress->GetInfo(APE_INFO_FORMAT_FLAGS)); gtk_list_store_append(list_store, &iter); gtk_list_store_set(list_store, &iter, COL_NAME, name, COL_VALUE, value, -1); g_free(value); /* Sample Rate */ name = _("Sample Rate"); value = g_strdup_printf("%d", pAPEDecompress->GetInfo(APE_INFO_SAMPLE_RATE)); gtk_list_store_append(list_store, &iter); gtk_list_store_set(list_store, &iter, COL_NAME, name, COL_VALUE, value, -1); g_free(value); /* Bits Per Sample */ name = _("Bits Per Sample"); value = g_strdup_printf("%d", pAPEDecompress->GetInfo(APE_INFO_BITS_PER_SAMPLE)); gtk_list_store_append(list_store, &iter); gtk_list_store_set(list_store, &iter, COL_NAME, name, COL_VALUE, value, -1); g_free(value); /* Channels */ name = _("Channels"); value = g_strdup_printf("%d", pAPEDecompress->GetInfo(APE_INFO_CHANNELS)); gtk_list_store_append(list_store, &iter); gtk_list_store_set(list_store, &iter, COL_NAME, name, COL_VALUE, value, -1); g_free(value); /* Actrual File if the file is APL */ char *ext = strrchr(mac_info.current_filename, '.'); if(ext) { if (!strcasecmp(ext, ".apl")) { name = _("Actrual File"); CIO *pIO = (CIO *)pAPEDecompress->GetInfo(APE_INFO_IO_SOURCE); if (pIO) { wchar_t nameBuf[255]; memset(nameBuf, 0, 255 * sizeof(wchar_t)); pIO->GetName(nameBuf); gchar *actrual_name = (gchar *)GetUTF8FromUTF16(nameBuf); gchar *basename = g_strdup(g_basename(name)); value = basename; gtk_list_store_append(list_store, &iter); gtk_list_store_set(list_store, &iter, COL_NAME, name, COL_VALUE, value, -1); g_free(actrual_name); g_free(basename); } } } /* Total File Size */ name = _("File Size"); value = g_strdup_printf("%d bytes", pAPEDecompress->GetInfo(APE_INFO_APE_TOTAL_BYTES)); gtk_list_store_append(list_store, &iter); gtk_list_store_set(list_store, &iter, COL_NAME, name, COL_VALUE, value, -1); g_free(value); /* Length (Time) */ name = _("Length"); unsigned int length = pAPEDecompress->GetInfo(APE_DECOMPRESS_LENGTH_MS); int min, sec, ms; ms = length % 1000; sec = length / 1000; min = sec / 60; sec = sec % 60; value = g_strdup_printf("%d:%d.%d ", min, sec, ms); gtk_list_store_append(list_store, &iter); gtk_list_store_set(list_store, &iter, COL_NAME, name, COL_VALUE, value, -1); g_free(value); /* Average Bitrate */ name = _("Bitrate"); value = g_strdup_printf("%d", pAPEDecompress->GetInfo(APE_DECOMPRESS_AVERAGE_BITRATE)); gtk_list_store_append(list_store, &iter); gtk_list_store_set(list_store, &iter, COL_NAME, name, COL_VALUE, value, -1); g_free(value); } void mac_tag_window_create() { GtkWidget *tag_window; GtkWidget *vbox, *hbox; GtkWidget *field_name_label; GtkWidget *field_value_label; GtkWidget *field_name; GtkWidget *field_value; GtkWidget *button_ok, *button_cancel; gint i = 0; tag_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); g_signal_connect(GTK_OBJECT(tag_window), "destroy", GTK_SIGNAL_FUNC(cb_tag_window_destroy), NULL); g_signal_connect(GTK_OBJECT (tag_window), "delete_event", GTK_SIGNAL_FUNC (cb_tag_window_delete), NULL); gtk_container_set_border_width(GTK_CONTAINER(tag_window), 10); gtk_window_set_modal(GTK_WINDOW(tag_window), TRUE); gtk_widget_set_size_request(tag_window, 250, 300); vbox = gtk_vbox_new(FALSE, 5); gtk_container_add(GTK_CONTAINER(tag_window), vbox); field_name_label = gtk_label_new(_("Field Name:")); gtk_misc_set_alignment(GTK_MISC(field_name_label), 0, 0); field_value_label = gtk_label_new(_("Field Value:")); gtk_misc_set_alignment(GTK_MISC(field_value_label), 0, 0); field_name = gtk_combo_box_entry_new_text(); for (i = 0; i < COMMON_TAG_COUNT; i ++) { gtk_combo_box_append_text(GTK_COMBO_BOX(field_name), common_tags[i]); } field_value = gtk_text_view_new(); gtk_text_view_set_editable(GTK_TEXT_VIEW(field_value), TRUE); hbox = gtk_hbutton_box_new(); gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END); gtk_box_set_spacing(GTK_BOX(hbox), 5); button_ok = gtk_button_new_with_label("OK"); g_signal_connect(GTK_OBJECT(button_ok), "clicked", GTK_SIGNAL_FUNC(cb_tag_window_ok), NULL); button_cancel = gtk_button_new_with_label("Cancel"); g_signal_connect(GTK_OBJECT(button_cancel), "clicked", GTK_SIGNAL_FUNC(cb_tag_window_cancel), NULL); gtk_box_pack_start(GTK_BOX(hbox), button_ok, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(hbox), button_cancel, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(vbox), field_name_label, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox), field_name, FALSE, TRUE, 0); gtk_box_pack_start(GTK_BOX(vbox), field_value_label, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox), field_value, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0); mac_tag.tag_window = tag_window; mac_tag.field_name_widget = field_name; mac_tag.field_value_widget = field_value; } void mac_info_box_create() { GtkWidget *window = NULL; GtkWidget *location = NULL; GtkWidget *metadata = NULL; GtkWidget *techinfo = NULL; GtkWidget *location_frame, *metadata_frame, *techinfo_frame; GtkWidget *vbox, *hbox; GtkWidget *bottom_hbox; GtkWidget *close_button, *update_button; GtkWidget *meta_vbox; GtkWidget *buttons_hbox; GtkWidget *meta_add, *meta_remove, *meta_edit; GtkListStore *store; GtkTreeViewColumn *column; GtkCellRenderer *renderer; window = gtk_window_new(GTK_WINDOW_TOPLEVEL); // gtk_window_set_policy(GTK_WINDOW(window), FALSE, FALSE, FALSE); g_signal_connect(GTK_OBJECT(window), "destroy", GTK_SIGNAL_FUNC(cb_info_box_destroy), NULL); g_signal_connect(GTK_OBJECT (window), "delete_event", GTK_SIGNAL_FUNC (cb_info_box_delete), NULL); gtk_container_set_border_width(GTK_CONTAINER(window), 10); location_frame = gtk_frame_new(_("Location")); metadata_frame = gtk_frame_new(_("Metadata")); techinfo_frame = gtk_frame_new(_("Technical info")); vbox = gtk_vbox_new(FALSE, 5); hbox = gtk_hbox_new(FALSE, 5); bottom_hbox = gtk_hbutton_box_new(); gtk_button_box_set_layout(GTK_BUTTON_BOX(bottom_hbox), GTK_BUTTONBOX_END); gtk_box_set_spacing(GTK_BOX(bottom_hbox), 5); gtk_container_add(GTK_CONTAINER(window), vbox); gtk_box_pack_start(GTK_BOX(vbox), location_frame, FALSE, TRUE, 0); gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(vbox), bottom_hbox, FALSE, TRUE, 0); gtk_box_pack_start(GTK_BOX(hbox), metadata_frame, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(hbox), techinfo_frame, FALSE, FALSE, 0); update_button = gtk_button_new_with_label(_("Update File")); gtk_box_pack_start(GTK_BOX(bottom_hbox), update_button, TRUE, TRUE, 0); g_signal_connect(GTK_OBJECT(update_button), "clicked", GTK_SIGNAL_FUNC(cb_metadata_update_file), NULL); close_button = gtk_button_new_with_label(_("Close")); g_signal_connect(GTK_OBJECT(close_button), "clicked", GTK_SIGNAL_FUNC(cb_info_box_close), NULL); gtk_box_pack_end(GTK_BOX(bottom_hbox), close_button, TRUE, TRUE, 0); location = gtk_entry_new(); gtk_container_add(GTK_CONTAINER(location_frame), location); gtk_editable_set_editable(GTK_EDITABLE(location), FALSE); meta_vbox = gtk_vbox_new(FALSE, 0); buttons_hbox = gtk_hbutton_box_new(); gtk_button_box_set_layout(GTK_BUTTON_BOX(buttons_hbox), GTK_BUTTONBOX_END); gtk_box_set_spacing(GTK_BOX(buttons_hbox), 5); meta_add = gtk_button_new_with_label(_("Add")); g_signal_connect(GTK_OBJECT(meta_add), "clicked", GTK_SIGNAL_FUNC(cb_metadata_add), NULL); meta_remove = gtk_button_new_with_label(_("Remove")); g_signal_connect(GTK_OBJECT(meta_remove), "clicked", GTK_SIGNAL_FUNC(cb_metadata_remove), NULL); meta_edit = gtk_button_new_with_label(_("Edit")); g_signal_connect(GTK_OBJECT(meta_edit), "clicked", GTK_SIGNAL_FUNC(cb_metadata_edit), NULL); gtk_box_pack_start(GTK_BOX(buttons_hbox), meta_add, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(buttons_hbox), meta_edit, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(buttons_hbox), meta_remove, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(meta_vbox), buttons_hbox, FALSE, TRUE, 0); store = gtk_list_store_new(N_COLS, G_TYPE_STRING, G_TYPE_STRING); metadata = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); g_object_unref(store); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes( _("Name"), renderer, "text", COL_NAME, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(metadata), column); gtk_tree_view_column_set_resizable(column, TRUE); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes( _("Value"), renderer, "text", COL_VALUE, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(metadata), column); gtk_tree_view_column_set_resizable(column, TRUE); gtk_tree_view_columns_autosize(GTK_TREE_VIEW(metadata)); gtk_box_pack_start(GTK_BOX(meta_vbox), metadata, TRUE, TRUE, 0); gtk_container_add(GTK_CONTAINER(metadata_frame), meta_vbox); store = gtk_list_store_new(N_COLS, G_TYPE_STRING, G_TYPE_STRING); techinfo = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); g_object_unref(store); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes( _("Name"), renderer, "text", COL_NAME, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(techinfo), column); gtk_tree_view_column_set_resizable(column, TRUE); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes( _("Value"), renderer, "text", COL_VALUE, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(techinfo), column); gtk_tree_view_column_set_resizable(column, TRUE); gtk_tree_view_columns_autosize(GTK_TREE_VIEW(techinfo)); gtk_container_add(GTK_CONTAINER(techinfo_frame), techinfo); mac_info.window = window; mac_info.location = location; mac_info.techinfo = techinfo; mac_info.metadata = metadata; } void mac_file_info_box(char *filename) { char *title; url2filename(filename); int nRetVal; wchar_t *pUTF16Name; if (!mac_info.window) { mac_info_box_create(); } if (mac_info.current_filename) { g_free(mac_info.current_filename); } mac_info.current_filename = (gchar *)GetUTF8FromANSI(filename); title = g_strdup_printf(_("File Info - %s"), g_basename(mac_info.current_filename)); gtk_window_set_title(GTK_WINDOW(mac_info.window), title); g_free(title); gtk_entry_set_text(GTK_ENTRY(mac_info.location), mac_info.current_filename); if (mac_info.pAPEDecompress) { delete mac_info.pAPEDecompress; } pUTF16Name = GetUTF16FromANSI(filename); mac_info.pAPEDecompress = CreateIAPEDecompress(pUTF16Name, &nRetVal); if (mac_info.pAPEDecompress == NULL || nRetVal != ERROR_SUCCESS) { printf("Oops, something is wrong with the file, error_code = %d\n", nRetVal); return; } CAPETag *apeTag = (CAPETag *)mac_info.pAPEDecompress->GetInfo(APE_INFO_TAG); GtkListStore *list_store; list_store = (GtkListStore *)gtk_tree_view_get_model(GTK_TREE_VIEW(mac_info.metadata)); insert_metadata(list_store, apeTag); list_store = (GtkListStore *)gtk_tree_view_get_model(GTK_TREE_VIEW(mac_info.techinfo)); insert_techinfo(list_store, mac_info.pAPEDecompress); gtk_widget_show_all(mac_info.window); } int main(int argc, char *argv[]) { if (argc < 2) { printf("usage: fileinfo filename\n"); return 0; } gtk_set_locale(); gtk_init(&argc, &argv); mac_file_info_box(argv[1]); gtk_main(); return 0; } #ifdef __cplusplus } #endif