f5f127cea367622c42961774b06c32636cbbe83f
[ardour.git] / gtk2_ardour / about.cc
1 /*
2     Copyright (C) 2003 Paul Davis 
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18     $Id$
19 */
20
21 #include <algorithm>
22 #include <unistd.h>
23 #include <sys/types.h>
24 #include <sys/wait.h>
25 #include <cstdio>
26 #include <ctime>
27 #include <cstdlib>
28
29 #include <gtk--/label.h>
30 #include <gtk--/text.h>
31 #include <gtk--/scrolledwindow.h>
32 #include <gtk--/notebook.h>
33
34 #include <ardour/ardour.h>
35 #include <ardour/version.h>
36
37 #include "utils.h"
38 #include "version.h"
39
40 #include <gtkmmext/gtk_ui.h>
41 #include <gtkmmext/doi.h>
42
43 #include "about.h"
44 #include "rgb_macros.h"
45 #include "ardour_ui.h"
46
47 #include "i18n.h"
48
49 using namespace Gtk;
50 using namespace std;
51 using namespace SigC;
52 using namespace ARDOUR;
53
54 #ifdef WITH_PAYMENT_OPTIONS
55
56 /* XPM */
57 static const gchar * paypal_xpm[] = {
58 "62 31 33 1",
59 "       c None",
60 ".      c #325781",
61 "+      c #154170",
62 "@      c #C1CDDA",
63 "#      c #4E6E92",
64 "$      c #D1D5DA",
65 "%      c #88A0B8",
66 "&      c #B4C4D3",
67 "*      c #C8D3DE",
68 "=      c #D7E1E9",
69 "-      c #002158",
70 ";      c #F6F8FA",
71 ">      c #44658B",
72 ",      c #E7ECF0",
73 "'      c #A4B7CA",
74 ")      c #9DB0C4",
75 "!      c #E3F1F7",
76 "~      c #708CA9",
77 "{      c #E1E7ED",
78 "]      c #567698",
79 "^      c #7C96B1",
80 "/      c #E7F5FA",
81 "(      c #EEF1F4",
82 "_      c #6883A2",
83 ":      c #244873",
84 "<      c #BBBBBB",
85 "[      c #E9E9E9",
86 "}      c #063466",
87 "|      c #22364D",
88 "1      c #94A7BD",
89 "2      c #000000",
90 "3      c #EAF7FC",
91 "4      c #FFFFFF",
92 "1'111111111111111111111111111111111111111111111111111111111%_#",
93 "%333333333333333333333333333333333333333333333333333333333333.",
94 "%444444444444444444444444444444444444444444444444444444444444:",
95 "_4333333!!!!!!33333333333333333333!!!!!!33333333333!%%%%1334[:",
96 "_444444@+}}}}+>)44444444444444444,:}}}}}.^(44444444@}..+.44($:",
97 "_433333^:&&&&)_}_33///33333333333&+)&&&'~+./3///333^.(;#]33($:",
98 "_444444>_444444'}_>...#%####~,]##..444444=+#]...>1;#_4;.144($:",
99 "_43333!+'4,>#=4(:+_%%%]}}#~#}_+~~:]44_>&44#}_%%%_+>:14=}@33($:",
100 "_44444*+$4&--)4(+%44444%-)4=--'4{+14,}-~44##44444&}}*4)+444($:",
101 "_433331:;4):_;4*}_]:.$4*-~4{}>44#-=4@.#{4;+>_:.&4,++;4_#333($:",
102 "_44444_#444444=.-.%&*,41-#4(:@4'-:(44444(_-:^&*,4*}#44.%444($:",
103 "_43333:%4;@@'~+-%44*&44]-.;;'4,:-#44*@&%:-];4{'(4)-%4{+&333($:",
104 "_4444{}@4*}}+>#:;4^-#4;.>+,444_+:^4(:}+.]}=4'-+(4_-&4&+{444($:",
105 "_4333'+(41:*=3'.44*)(4=+)+*44@}%+@4=}&=/@}{4{1{44:+,4^.3333($:",
106 "_4444~>,,]#444*})(;**,':*}'4;._@}=,%:444(+~(;{&,*}.,,>~4444($:",
107 "_4333>}}}}^3333~}::}}}}>].;4^+=~}}}}]3333'}+:}}}}}}}}}'3333($:",
108 "_4444$@@@@(44444$))@*@*^}$4=}14=@@@@{44444=))&*@@@@@@@;4444($:",
109 "_433333333333333333333=+:%%.>/33333333333333333333333333333($:",
110 "_4444444444444444444441....>=444444444444444444444444444444($:",
111 "_4333333333333333333333333333333333333333333333333333333333($:",
112 "_4444444444444444444444444444444444444444444444444444444444($:",
113 "_4333333333333333333333333333333333333333333333333333333333($:",
114 "_4444442222444222442444242444244222242444242222244222244444($:",
115 "_4333332333232333233232332232233233332233233323332333333333($:",
116 "_4444442222442222244424442424244222442424244424444222444444($:",
117 "_4333332333332333233323332333233233332332233323333333233333($:",
118 "_4444442444442444244424442444244222242444244424442222444444($:",
119 "_433333333333333333333333333333333333333333333333333333333344:",
120 "#4([[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[=&:",
121 ".=&<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<1|",
122 "::||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||"};
123 #endif
124
125 static gint 
126 stoppit (GdkEventButton* ev, Gtk::Notebook* notebook)
127 {
128         gtk_signal_emit_stop_by_name (GTK_OBJECT(notebook->gtkobj()),
129                                       "button_release_event");
130         return TRUE;
131 }
132
133 static const char* author_names[] = {
134         N_("Marcus Andersson"),
135         N_("Jeremy Hall"),
136         N_("Steve Harris"),
137         N_("Tim Mayberry"),
138         N_("Mark Stewart"),
139         N_("Sam Chessman"),
140         N_("Jack O'Quin"),
141         N_("Matt Krai"),
142         N_("Ben Bell"),
143         N_("Gerard van Dongen"),
144         N_("Thomas Charbonnel"),
145         N_("Nick Mainsbridge"),
146         N_("Colin Law"),
147         N_("Sampo Savolainen"),
148         N_("Joshua Leach"),
149         N_("Rob Holland"),
150         N_("Per Sigmond"),
151         N_("Doug Mclain"),
152         0
153 };
154
155 static const char* translators[] = {
156         N_("French:\n\tAlain Fréhel <alain.frehel@free.fr>"),
157         N_("German:\n\tKarsten Petersen <kapet@kapet.de>"),
158         N_("Italian:\n\tFilippo Pappalardo <filippo@email.it>"),
159         N_("Portuguese:\n\tRui Nuno Capela <rncbc@rncbc.org>"),
160         N_("Brazilian Portuguese:\n\tAlexander da Franca Fernandes <alexander@nautae.eti.br>\
161 \n\tChris Ross <chris@tebibyte.org>"),
162         N_("Spanish:\n\t Alex Krohn <alexkrohn@fastmail.fm>"),
163         N_("Russian:\n\t Igor Blinov <pitstop@nm.ru>"),
164         0
165 };
166
167
168 About::About (ARDOUR_UI * ui)
169         : Window (GTK_WINDOW_TOPLEVEL), _ui (ui)
170 #ifdef WITH_PAYMENT_OPTIONS
171         , paypal_pixmap (paypal_xpm)
172 #endif
173 {
174         using namespace Notebook_Helpers;
175
176         about_index = 0;
177         about_cnt = 0;
178         drawn = false;
179
180         Gtk::Label* small_label = manage (new Label (_(
181 "Copyright (C) 1999-2005 Paul Davis\n"
182 "Ardour comes with ABSOLUTELY NO WARRANTY\n"
183 "This is free software, and you are welcome to redistribute it\n"
184 "under certain conditions; see the file COPYING for details.\n")));
185
186         Gtk::Label* version_label = 
187                 manage (new Label 
188                         (compose(_("Ardour: %1\n(built with ardour/gtk %2.%3.%4 libardour: %5.%6.%7)"), 
189                                  VERSIONSTRING, 
190                                  gtk_ardour_major_version, 
191                                  gtk_ardour_minor_version, 
192                                  gtk_ardour_micro_version, 
193                                  libardour_major_version, 
194                                  libardour_minor_version, 
195                                  libardour_micro_version))); 
196
197         Notebook* notebook = manage (new Notebook);
198
199         ScrolledWindow* author_scroller = manage (new ScrolledWindow);
200         Text* author_text = manage (new Text);
201
202         author_text->set_editable (false);
203         author_text->set_name (X_("AboutText"));
204
205         string str = _(
206 "Primary author:\n\t\
207 Paul Davis\n\n\
208 Major developers:\n\t\
209 Jesse Chappell\n\t\
210 Taybin Rutkin\n\
211 Contributors:\n\t");
212
213         for (int32_t n = 0; author_names[n] != 0; ++n) {
214                 str += _(author_names[n]);
215                 str += "\n\t";
216         }
217
218         author_text->insert (str);
219
220         author_scroller->add (*author_text);
221         author_scroller->set_usize (-1, 75);
222         author_scroller->set_policy (GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
223
224         ScrolledWindow* translator_scroller = manage (new ScrolledWindow);
225         Text* translator_text = manage (new Text);
226
227         translator_text->set_editable (false);
228         translator_text->set_name (X_("AboutText"));
229
230         str = "";
231         
232         for (int32_t n = 0; translators[n] != 0; ++n) {
233                 str += _(translators[n]);
234                 str += '\n';
235         }
236
237         translator_text->insert (str);
238         
239         translator_scroller->add (*translator_text);
240         translator_scroller->set_usize (-1, 75);
241         translator_scroller->set_policy (GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
242
243         Label* author_tab_label = manage (new Label (_("Authors")));
244         Label* translator_tab_label = manage (new Label (_("Translators")));
245
246         notebook->pages().push_back (TabElem (*author_scroller, *author_tab_label));
247         notebook->pages().push_back (TabElem (*translator_scroller, *translator_tab_label));
248
249         notebook->set_name ("AboutNoteBook");
250         notebook->button_release_event.connect_after (bind (slot (stoppit), notebook));
251
252         logo_pixmap = 0;
253         logo_height = 0;
254         logo_width = 0;
255         
256         set_name ("AboutWindow");
257         set_title ("ardour: about");
258         set_wmclass ("ardour_about", "Ardour");
259         
260         vbox.set_border_width (5);
261         vbox.set_spacing (5);
262
263         if (load_logo_size ()) {
264                 logo_area.set_usize (logo_width, logo_height);
265                 load_logo (*this);
266
267                 vbox.pack_start (logo_area, false, false);
268                 logo_area.expose_event.connect (slot (*this, &About::logo_area_expose));
269         } else {
270                 expose_event.connect (slot (*this, &About::logo_area_expose));
271         }
272
273         small_label->set_name  ("AboutWindowSmallLabel");
274         version_label->set_name("AboutWindowSmallLabel");
275
276         first_label.set_name ("AboutWindowLabel");
277         third_label.set_name ("AboutWindowPDLabel");
278         second_label.set_name ("AboutWindowLabel");
279
280         subvbox.pack_start (*small_label, false, false);
281         subvbox.pack_start (*version_label, false, false);
282         subvbox.pack_start (*notebook, true, true);
283
284 #ifdef WITH_PAYMENT_OPTIONS
285         paypal_button.add (paypal_pixmap);
286         
287         HBox *payment_box = manage (new HBox);
288         payment_box->pack_start (paypal_button, true, false);
289
290         subvbox.pack_start (*payment_box, false, false);
291 #endif
292
293         delete_event.connect (bind (slot (just_hide_it), static_cast<Gtk::Window*> (this)));
294
295         add (vbox);
296         add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK);
297
298         set_position (GTK_WIN_POS_CENTER);
299
300         show_all ();
301         subvbox.hide ();
302
303         /* wait for the first logo expose event to complete so that
304            we know we are fully drawn.
305         */
306
307         while (!drawn) {
308                 gtk_main_iteration ();
309         }
310 }
311
312 About::~About ()
313 {
314 }
315
316 void
317 About::show_sub (bool yn)
318 {
319         if (yn) {
320                 vbox.pack_start (subvbox, true, true);
321                 subvbox.show_all ();
322         } else {
323                 vbox.remove (subvbox);
324                 subvbox.hide ();
325         }
326 }
327
328 gint
329 About::button_release_event_impl (GdkEventButton* ev)
330 {
331         hide();
332
333         if (!_ui->shown ()) {
334                 /* show it immediately */
335                 _ui->show();
336         }
337         
338         return TRUE;
339 }
340
341 void
342 About::realize_impl ()
343 {
344         Window::realize_impl ();
345         get_window().set_decorations (GdkWMDecoration (GDK_DECOR_BORDER|GDK_DECOR_RESIZEH));
346         // get_window().set_decorations (GdkWMDecoration (0));
347 }
348
349 bool
350 About::load_logo_size ()
351 {
352         gchar buf[1024];
353         FILE *fp;
354         string path = find_data_file ("splash.ppm");
355
356         if (path.length() == 0) {
357                 return false;
358         }
359
360         if ((fp = fopen (path.c_str(), "rb")) == 0) {
361                 error << compose (_("cannot open splash image file \"%1\""), path) << endmsg;
362                 return false;
363         }
364         
365         fgets (buf, sizeof (buf), fp);
366         if (strcmp (buf, "P6\n") != 0) {
367                 fclose (fp);
368                 return false;
369         }
370         
371         fgets (buf, sizeof (buf), fp);
372         fgets (buf, sizeof (buf), fp);
373         sscanf (buf, "%d %d", &logo_width, &logo_height);
374         fclose (fp);
375         return true;
376 }
377
378 bool
379 About::load_logo (Gtk::Window& window)
380 {
381         GdkGC* gc;
382         gchar   buf[1024];
383         guchar *pixelrow;
384         FILE *fp;
385         gint count;
386         gint i;
387         string path;
388
389         path = find_data_file ("splash.ppm");
390
391         if (path.length() == 0) {
392                 return false;
393         }
394         
395         if ((fp = fopen (path.c_str(), "rb")) == 0) {
396                 return false;
397         }
398         
399         fgets (buf, sizeof (buf), fp);
400         if (strcmp (buf, "P6\n") != 0) {
401                 fclose (fp);
402                 return false;
403         }
404         
405         fgets (buf, sizeof (buf), fp);
406         fgets (buf, sizeof (buf), fp);
407         sscanf (buf, "%d %d", &logo_width, &logo_height);
408         
409         fgets (buf, sizeof (buf), fp);
410         if (strcmp (buf, "255\n") != 0) {
411                 fclose (fp);
412                 return false;
413         }
414
415         Gtk::Preview preview (GTK_PREVIEW_COLOR);
416
417         preview.size (logo_width, logo_height);
418         pixelrow = new guchar[logo_width * 3];
419         
420         for (i = 0; i < logo_height; i++) {
421                 count = fread (pixelrow, sizeof (unsigned char), logo_width * 3, fp);
422                 if (count != (logo_width * 3))
423                 {
424                         delete [] pixelrow;
425                         fclose (fp);
426                         return false;
427                 }
428                 preview.draw_row (pixelrow, 0, i, logo_width);
429         }
430         
431         window.realize ();
432
433         logo_pixmap = gdk_pixmap_new (GTK_WIDGET(window.gtkobj())->window, logo_width, logo_height,
434                                       gtk_preview_get_visual()->depth);
435         gc = gdk_gc_new (logo_pixmap);
436         gtk_preview_put (preview.gtkobj(), logo_pixmap, gc, 0, 0, 0, 0, logo_width, logo_height);
437         gdk_gc_destroy (gc);
438         
439         delete [] pixelrow;
440         fclose (fp);
441         
442         return true;
443 }
444
445 gint
446 About::logo_area_expose (GdkEventExpose* ev)
447 {
448         if (!drawn) {
449                 drawn = true;
450         }
451
452         if (logo_pixmap) {
453                 logo_area.get_window().draw_pixmap (logo_area.get_style()->get_black_gc(),
454                                                     Gdk_Pixmap (logo_pixmap),
455                                                     0, 0,
456                                                     ((logo_area.width() - logo_width) / 2),
457                                                     ((logo_area.height() - logo_height) / 2),
458                                                     logo_width, logo_height);
459                 gdk_flush ();
460         }
461
462         return FALSE;
463 }
464
465 #ifdef WITH_PAYMENT_OPTIONS
466 void
467 About::goto_paypal ()
468 {
469         char buf[PATH_MAX+16];
470         char *argv[4];
471         char *docfile = "foo";
472         int grandchild;
473         
474         if (fork() == 0) {
475
476                 /* child */
477
478                 if ((grandchild = fork()) == 0) {
479                         
480                         /* grandchild */
481                         
482                         argv[0] = "mozilla";
483                         argv[1] = "-remote";
484                         snprintf (buf, sizeof(buf), "openurl(%s)", docfile);
485                         argv[2] = buf;
486                         argv[3] = 0;
487
488                         execvp ("mozilla", argv);
489                         error << "could not start mozilla" << endmsg;
490
491                 } else {
492                         int status;
493                         waitpid (grandchild, &status, 0);
494                 }
495
496         } 
497 }
498 #endif