ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/prefs_editor_gtk.cpp
(Generate patch)

Comparing BasiliskII/src/Unix/prefs_editor_gtk.cpp (file contents):
Revision 1.34 by gbeauche, 2006-04-17T14:25:57Z vs.
Revision 1.40 by gbeauche, 2008-01-01T09:40:33Z

# Line 1 | Line 1
1   /*
2   *  prefs_editor_gtk.cpp - Preferences editor, Unix implementation using GTK+
3   *
4 < *  Basilisk II (C) 1997-2005 Christian Bauer
4 > *  Basilisk II (C) 1997-2008 Christian Bauer
5   *
6   *  This program is free software; you can redistribute it and/or modify
7   *  it under the terms of the GNU General Public License as published by
# Line 45 | Line 45
45  
46   // Global variables
47   static GtkWidget *win;                          // Preferences window
48 < static bool start_clicked = true;       // Return value of PrefsEditor() function
48 > static bool start_clicked = false;      // Return value of PrefsEditor() function
49  
50  
51   // Prototypes
# Line 428 | Line 428 | static void mn_about(...)
428          dialog = gnome_about_new(
429                  "Basilisk II",
430                  version,
431 <                "Copyright (C) 1997-2005 Christian Bauer",
431 >                "Copyright (C) 1997-2008 Christian Bauer",
432                  authors,
433                  "Basilisk II comes with ABSOLUTELY NO WARRANTY."
434                  "This is free software, and you are welcome to redistribute it"
# Line 444 | Line 444 | static void mn_about(...)
444          char str[512];
445          sprintf(str,
446                  "Basilisk II\nVersion %d.%d\n\n"
447 <                "Copyright (C) 1997-2005 Christian Bauer et al.\n"
447 >                "Copyright (C) 1997-2008 Christian Bauer et al.\n"
448                  "E-mail: Christian.Bauer@uni-mainz.de\n"
449                  "http://www.uni-mainz.de/~bauec002/B2Main.html\n\n"
450                  "Basilisk II comes with ABSOLUTELY NO\n"
# Line 712 | Line 712 | static GtkWidget *w_jit_cache_size;
712   static GtkWidget *w_jit_lazy_flush;
713   static GtkWidget *w_jit_follow_const_jumps;
714  
715 + // Are we running a JIT capable CPU?
716 + static bool is_jit_capable(void)
717 + {
718 + #if USE_JIT && (defined __i386__ || defined __x86_64__)
719 +        return true;
720 + #elif defined __APPLE__ && defined __MACH__
721 +        // XXX run-time detect so that we can use a PPC GUI prefs editor
722 +        static char cpu[10];
723 +        if (cpu[0] == 0) {
724 +                FILE *fp = popen("uname -p", "r");
725 +                if (fp == NULL)
726 +                        return false;
727 +                fgets(cpu, sizeof(cpu) - 1, fp);
728 +                fclose(fp);
729 +        }
730 +        if (cpu[0] == 'i' && cpu[2] == '8' && cpu[3] == '6') // XXX assuming i?86
731 +                return true;
732 + #endif
733 +        return false;
734 + }
735 +
736   // Set sensitivity of widgets
737   static void set_jit_sensitive(void)
738   {
# Line 750 | Line 771 | static void tb_jit_follow_const_jumps(Gt
771   // Read settings from widgets and set preferences
772   static void read_jit_settings(void)
773   {
774 < #if USE_JIT
754 <        bool jit_enabled = PrefsFindBool("jit");
774 >        bool jit_enabled = is_jit_capable() && PrefsFindBool("jit");
775          if (jit_enabled) {
776                  const char *str = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(w_jit_cache_size)->entry));
777                  PrefsReplaceInt32("jitcachesize", atoi(str));
778          }
759 #endif
779   }
780  
781   // Create "JIT Compiler" pane
782   static void create_jit_pane(GtkWidget *top)
783   {
784 < #if USE_JIT
784 >        if (!is_jit_capable())
785 >                return;
786 >
787          GtkWidget *box, *table, *label, *menu;
788          char str[32];
789          
# Line 788 | Line 809 | static void create_jit_pane(GtkWidget *t
809          w_jit_follow_const_jumps = make_checkbox(box, STR_JIT_FOLLOW_CONST_JUMPS, "jitinline", GTK_SIGNAL_FUNC(tb_jit_follow_const_jumps));
810  
811          set_jit_sensitive();
791 #endif
812   }
813  
814   /*
# Line 1413 | Line 1433 | static void create_serial_pane(GtkWidget
1433   static GtkWidget *w_ramsize;
1434   static GtkWidget *w_rom_file;
1435  
1436 + // Don't use CPU when idle?
1437 + static void tb_idlewait(GtkWidget *widget)
1438 + {
1439 +        PrefsReplaceBool("idlewait", GTK_TOGGLE_BUTTON(widget)->active);
1440 + }
1441 +
1442   // "Ignore SEGV" button toggled
1443   #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
1444   static void tb_ignoresegv(GtkWidget *widget)
# Line 1505 | Line 1531 | static void create_memory_pane(GtkWidget
1531  
1532          w_rom_file = table_make_file_entry(table, 4, STR_ROM_FILE_CTRL, "rom");
1533  
1534 +        make_checkbox(box, STR_IDLEWAIT_CTRL, "idlewait", GTK_SIGNAL_FUNC(tb_idlewait));
1535   #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
1536          make_checkbox(box, STR_IGNORESEGV_CTRL, "ignoresegv", GTK_SIGNAL_FUNC(tb_ignoresegv));
1537   #endif
# Line 1540 | Line 1567 | uint8 XPRAM[XPRAM_SIZE];
1567   void MountVolume(void *fh) { }
1568   void FileDiskLayout(loff_t size, uint8 *data, loff_t &start_byte, loff_t &real_size) { }
1569  
1570 + #if defined __APPLE__ && defined __MACH__
1571 + void DarwinSysInit(void) { }
1572 + void DarwinSysExit(void) { }
1573 + void DarwinAddFloppyPrefs(void) { }
1574 + void DarwinAddSerialPrefs(void) { }
1575 + bool DarwinCDReadTOC(char *, uint8 *) { }
1576 + #endif
1577 +
1578  
1579   /*
1580   *  Display alert
# Line 1601 | Line 1636 | void WarningAlert(const char *text)
1636   *  RPC handlers
1637   */
1638  
1639 + static GMainLoop *g_gui_loop;
1640 +
1641   static int handle_ErrorAlert(rpc_connection_t *connection)
1642   {
1643          D(bug("handle_ErrorAlert\n"));
# Line 1633 | Line 1670 | static int handle_Exit(rpc_connection_t
1670   {
1671          D(bug("handle_Exit\n"));
1672  
1673 +        g_main_quit(g_gui_loop);
1674          return RPC_ERROR_NO_ERROR;
1675   }
1676  
1677  
1678   /*
1679 + *  SIGCHLD handler
1680 + */
1681 +
1682 + static char g_app_path[PATH_MAX];
1683 + static rpc_connection_t *g_gui_connection = NULL;
1684 +
1685 + static void sigchld_handler(int sig, siginfo_t *sip, void *)
1686 + {
1687 +        D(bug("Child %d exitted with status = %x\n", sip->si_pid, sip->si_status));
1688 +
1689 +        // XXX perform a new wait because sip->si_status is sometimes not
1690 +        // the exit _value_ on MacOS X but rather the usual status field
1691 +        // from waitpid() -- we could arrange this code in some other way...
1692 +        int status;
1693 +        if (waitpid(sip->si_pid, &status, 0) < 0)
1694 +                status = sip->si_status;
1695 +        if (WIFEXITED(status))
1696 +                status = WEXITSTATUS(status);
1697 +        if (status & 0x80)
1698 +                status |= -1 ^0xff;
1699 +
1700 +        if (status < 0) {       // negative -> execlp/-errno
1701 +                char str[256];
1702 +                sprintf(str, GetString(STR_NO_B2_EXE_FOUND), g_app_path, strerror(-status));
1703 +                ErrorAlert(str);
1704 +                status = 1;
1705 +        }
1706 +
1707 +        if (status != 0) {
1708 +                if (g_gui_connection)
1709 +                        rpc_exit(g_gui_connection);
1710 +                exit(status);
1711 +        }
1712 + }
1713 +
1714 +
1715 + /*
1716   *  Start standalone GUI
1717   */
1718  
# Line 1667 | Line 1742 | int main(int argc, char *argv[])
1742          if (start) {
1743                  char gui_connection_path[64];
1744                  sprintf(gui_connection_path, "/org/BasiliskII/GUI/%d", getpid());
1670                
1671                int pid = fork();
1672                if (pid == 0) {                 // Child
1673                        char b2_path[PATH_MAX];
1674                        strcpy(b2_path, argv[0]);
1675                        char *p = strrchr(b2_path, '/');
1676                        p = p ? p + 1 : b2_path;
1677                        *p = '\0';
1678                        strcat(b2_path, "BasiliskII");
1679                        execl(b2_path, b2_path, "--gui-connection", gui_connection_path, (char *)NULL);
1745  
1746 +                // Catch exits from the child process
1747 +                struct sigaction sigchld_sa, old_sigchld_sa;
1748 +                sigemptyset(&sigchld_sa.sa_mask);
1749 +                sigchld_sa.sa_sigaction = sigchld_handler;
1750 +                sigchld_sa.sa_flags = SA_NOCLDSTOP | SA_SIGINFO;
1751 +                if (sigaction(SIGCHLD, &sigchld_sa, &old_sigchld_sa) < 0) {
1752                          char str[256];
1753 <                        sprintf(str, GetString(STR_NO_B2_EXE_FOUND), b2_path, strerror(errno));
1753 >                        sprintf(str, GetString(STR_SIG_INSTALL_ERR), SIGCHLD, strerror(errno));
1754                          ErrorAlert(str);
1755                          return 1;
1756                  }
1686                else {                                  // Parent
1687                        rpc_connection_t *connection;
1688                        if ((connection = rpc_init_server(gui_connection_path)) == NULL) {
1689                                printf("ERROR: failed to initialize GUI-side RPC server connection\n");
1690                                return 1;
1691                        }
1757  
1758 <                        static const rpc_method_descriptor_t vtable[] = {
1759 <                                { RPC_METHOD_ERROR_ALERT,                       handle_ErrorAlert },
1760 <                                { RPC_METHOD_WARNING_ALERT,                     handle_WarningAlert },
1761 <                                { RPC_METHOD_EXIT,                                      handle_Exit }
1762 <                        };
1763 <                        if (rpc_method_add_callbacks(connection, vtable, sizeof(vtable) / sizeof(vtable[0])) < 0) {
1764 <                                printf("ERROR: failed to setup GUI method callbacks\n");
1765 <                                return 1;
1758 >                // Search and run the BasiliskII executable
1759 >                char *p;
1760 >                strcpy(g_app_path, argv[0]);
1761 >                if ((p = strstr(g_app_path, "BasiliskIIGUI.app/Contents/MacOS")) != NULL) {
1762 >                    strcpy(p, "BasiliskII.app/Contents/MacOS/BasiliskII");
1763 >                        if (access(g_app_path, X_OK) < 0) {
1764 >                                char str[256];
1765 >                                sprintf(str, GetString(STR_NO_B2_EXE_FOUND), g_app_path, strerror(errno));
1766 >                                WarningAlert(str);
1767 >                                strcpy(g_app_path, "/Applications/BasiliskII.app/Contents/MacOS/BasiliskII");
1768                          }
1769 +                } else {
1770 +                        p = strrchr(g_app_path, '/');
1771 +                        p = p ? p + 1 : g_app_path;
1772 +                        strcpy(p, "BasiliskII");
1773 +                }
1774  
1775 <                        if (rpc_listen(connection) < 0) {
1776 <                                printf("ERROR: failed to initialize RPC server thread\n");
1777 <                                return 1;
1778 <                        }
1775 >                int pid = fork();
1776 >                if (pid == 0) {
1777 >                        D(bug("Trying to execute %s\n", g_app_path));
1778 >                        execlp(g_app_path, g_app_path, "--gui-connection", gui_connection_path, (char *)NULL);
1779 > #ifdef _POSIX_PRIORITY_SCHEDULING
1780 >                        // XXX get a chance to run the parent process so that to not confuse/upset GTK...
1781 >                        sched_yield();
1782 > #endif
1783 >                        _exit(-errno);
1784 >                }
1785  
1786 <                        int status, ret = -1;
1787 <                        while (waitpid(pid, &status, 0) != pid)
1788 <                                ;
1789 <                        if (WIFEXITED(status))
1790 <                                ret = WEXITSTATUS(status);
1786 >                // Establish a connection to Basilisk II
1787 >                if ((g_gui_connection = rpc_init_server(gui_connection_path)) == NULL) {
1788 >                        printf("ERROR: failed to initialize GUI-side RPC server connection\n");
1789 >                        return 1;
1790 >                }
1791 >                static const rpc_method_descriptor_t vtable[] = {
1792 >                        { RPC_METHOD_ERROR_ALERT,                       handle_ErrorAlert },
1793 >                        { RPC_METHOD_WARNING_ALERT,                     handle_WarningAlert },
1794 >                        { RPC_METHOD_EXIT,                                      handle_Exit }
1795 >                };
1796 >                if (rpc_method_add_callbacks(g_gui_connection, vtable, sizeof(vtable) / sizeof(vtable[0])) < 0) {
1797 >                        printf("ERROR: failed to setup GUI method callbacks\n");
1798 >                        return 1;
1799 >                }
1800 >                int socket;
1801 >                if ((socket = rpc_listen_socket(g_gui_connection)) < 0) {
1802 >                        printf("ERROR: failed to initialize RPC server thread\n");
1803 >                        return 1;
1804 >                }
1805 >
1806 >                g_gui_loop = g_main_new(TRUE);
1807 >                while (g_main_is_running(g_gui_loop)) {
1808  
1809 <                        rpc_exit(connection);
1810 <                        return ret;
1809 >                        // Process a few events pending
1810 >                        const int N_EVENTS_DISPATCH = 10;
1811 >                        for (int i = 0; i < N_EVENTS_DISPATCH; i++) {
1812 >                                if (!g_main_iteration(FALSE))
1813 >                                        break;
1814 >                        }
1815 >
1816 >                        // Check for RPC events (100 ms timeout)
1817 >                        int ret = rpc_wait_dispatch(g_gui_connection, 100000);
1818 >                        if (ret == 0)
1819 >                                continue;
1820 >                        if (ret < 0)
1821 >                                break;
1822 >                        rpc_dispatch(g_gui_connection);
1823                  }
1824 +
1825 +                rpc_exit(g_gui_connection);
1826 +                return 0;
1827          }
1828  
1829          return 0;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines