simply future debugging of exit at start.
[ardour.git] / gtk2_ardour / utils.cc
index 913d962831b919764c6959d2b5139616f97e2481..facbe92db53990a4d0139dd544a2150c70cc7c7f 100644 (file)
@@ -28,6 +28,7 @@
 #include <clocale>
 #include <cstring>
 #include <cctype>
+#include <cmath>
 #include <fstream>
 #include <list>
 #include <sys/stat.h>
@@ -44,7 +45,9 @@
 #include <gtkmm2ext/utils.h>
 #include "ardour/rc_configuration.h"
 #include "ardour/filesystem_paths.h"
+
 #include "canvas/item.h"
+#include "canvas/utils.h"
 
 #include "ardour_ui.h"
 #include "debug.h"
@@ -63,6 +66,10 @@ using Gtkmm2ext::Keyboard;
 
 sigc::signal<void>  DPIReset;
 
+#ifdef PLATFORM_WINDOWS
+#define random() rand()
+#endif
+
 
 /** Add an element to a menu, settings its sensitivity.
  * @param m Menu to add to.
@@ -283,7 +290,7 @@ rgba_from_style (string style, uint32_t r, uint32_t g, uint32_t b, uint32_t a, s
        if (state == Gtk::STATE_NORMAL && rgba) {
                return (uint32_t) RGBA_TO_UINT(r,g,b,a);
        } else {
-               return (uint32_t) RGB_TO_UINT(r,g,b);
+               return (uint32_t) RGBA_TO_UINT(r,g,b,255);
        }
 }
 
@@ -335,9 +342,69 @@ rgba_p_from_style (string style, float *r, float *g, float *b, string attr, int
 }
 
 void
-set_color (Gdk::Color& c, int rgb)
+set_color_from_rgb (Gdk::Color& c, uint32_t rgb)
+{
+       /* Gdk::Color color ranges are 16 bit, so scale from 8 bit by
+          multiplying by 256.
+       */
+       c.set_rgb ((rgb >> 16)*256, ((rgb & 0xff00) >> 8)*256, (rgb & 0xff)*256);
+}
+
+void
+set_color_from_rgba (Gdk::Color& c, uint32_t rgba)
+{
+       /* Gdk::Color color ranges are 16 bit, so scale from 8 bit by
+          multiplying by 256.
+       */
+       c.set_rgb ((rgba >> 24)*256, ((rgba & 0xff0000) >> 16)*256, ((rgba & 0xff00) >> 8)*256);
+}
+
+uint32_t
+gdk_color_to_rgba (Gdk::Color const& c)
 {
-       c.set_rgb((rgb >> 16)*256, ((rgb & 0xff00) >> 8)*256, (rgb & 0xff)*256);
+       /* since alpha value is not available from a Gdk::Color, it is
+          hardcoded as 0xff (aka 255 or 1.0)
+       */
+
+       const uint32_t r = c.get_red_p () * 255.0;
+       const uint32_t g = c.get_green_p () * 255.0;
+       const uint32_t b = c.get_blue_p () * 255.0;
+       const uint32_t a = 0xff;
+
+       return RGBA_TO_UINT (r,g,b,a);
+}
+
+uint32_t
+contrasting_text_color (uint32_t c)
+{
+       double r, g, b, a;
+       ArdourCanvas::color_to_rgba (c, r, g, b, a);
+
+       const double black_r = 0.0;
+       const double black_g = 0.0;
+       const double black_b = 0.0;
+
+       const double white_r = 1.0;
+       const double white_g = 1.0;
+       const double white_b = 1.0;
+
+       /* Use W3C contrast guideline calculation */
+
+       double white_contrast = (max (r, white_r) - min (r, white_r)) +
+               (max (g, white_g) - min (g, white_g)) + 
+               (max (b, white_b) - min (b, white_b));
+
+       double black_contrast = (max (r, black_r) - min (r, black_r)) +
+               (max (g, black_g) - min (g, black_g)) + 
+               (max (b, black_b) - min (b, black_b));
+
+       if (white_contrast > black_contrast) {          
+               /* use white */
+               return ArdourCanvas::rgba_to_color (1.0, 1.0, 1.0, 1.0);
+       } else {
+               /* use black */
+               return ArdourCanvas::rgba_to_color (0.0, 0.0, 0.0, 1.0);
+       }
 }
 
 bool
@@ -567,7 +634,7 @@ get_xpm (std::string name)
 {
        if (!xpm_map[name]) {
 
-               SearchPath spath(ARDOUR::ardour_data_search_path());
+               Searchpath spath(ARDOUR::ardour_data_search_path());
 
                spath.add_subdirectory_to_paths("pixmaps");
 
@@ -587,25 +654,93 @@ get_xpm (std::string name)
        return xpm_map[name];
 }
 
+vector<string>
+get_icon_sets ()
+{
+       Searchpath spath(ARDOUR::ardour_data_search_path());
+       spath.add_subdirectory_to_paths ("icons");
+       vector<string> r;
+       
+       r.push_back (_("default"));
+
+       for (vector<string>::iterator s = spath.begin(); s != spath.end(); ++s) {
+
+               vector<string> entries;
+
+               get_files_in_directory (*s, entries);
+
+               for (vector<string>::iterator e = entries.begin(); e != entries.end(); ++e) {
+
+                       string d = *e;
+
+                       /* ignore dotfiles, . and .. */
+
+                       if (d.empty() || d[0] == '.') {
+                               continue;
+                       }
+                       
+                       Glib::ustring path = Glib::build_filename (*s, *e);
+
+                       if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
+                               r.push_back (Glib::filename_to_utf8 (*e));
+                       }
+               }
+       }
+
+       return r;
+}
+
 std::string
-get_icon_path (const char* cname)
+get_icon_path (const char* cname, string icon_set)
 {
+       std::string data_file_path;
        string name = cname;
        name += X_(".png");
 
-       SearchPath spath(ARDOUR::ardour_data_search_path());
-
-       spath.add_subdirectory_to_paths("icons");
+       Searchpath spath(ARDOUR::ardour_data_search_path());
 
-       std::string data_file_path;
+       if (!icon_set.empty() && icon_set != _("default")) {
 
-       if (!find_file_in_search_path (spath, name, data_file_path)) {
-               fatal << string_compose (_("cannot find icon image for %1 using %2"), name, spath.to_string()) << endmsg;
+               /* add "icons/icon_set" but .. not allowed to add both of these at once */
+               spath.add_subdirectory_to_paths ("icons");
+               spath.add_subdirectory_to_paths (icon_set);
+               
+               find_file_in_search_path (spath, name, data_file_path);
+       }
+       
+       if (data_file_path.empty()) {
+               
+               if (!icon_set.empty() && icon_set != _("default")) {
+                       warning << string_compose (_("icon \"%1\" not found for icon set \"%2\", fallback to default"), cname, icon_set) << endmsg;
+               }
+               
+               Searchpath def (ARDOUR::ardour_data_search_path());
+               def.add_subdirectory_to_paths ("icons");
+       
+               if (!find_file_in_search_path (def, name, data_file_path)) {
+                       fatal << string_compose (_("cannot find icon image for %1 using %2"), name, spath.to_string()) << endmsg;
+                       /*NOTREACHED*/
+               }
        }
 
        return data_file_path;
 }
 
+Glib::RefPtr<Gdk::Pixbuf>
+get_icon (const char* cname, string icon_set)
+{
+       Glib::RefPtr<Gdk::Pixbuf> img;
+       try {
+               img = Gdk::Pixbuf::create_from_file (get_icon_path (cname, icon_set));
+       } catch (const Gdk::PixbufError &e) {
+               cerr << "Caught PixbufError: " << e.what() << endl;
+       } catch (...) {
+               error << string_compose (_("Caught exception while loading icon named %1"), cname) << endmsg;
+       }
+
+       return img;
+}
+
 Glib::RefPtr<Gdk::Pixbuf>
 get_icon (const char* cname)
 {
@@ -740,7 +875,9 @@ set_pango_fontsize ()
 
        /* FT2 rendering - used by GnomeCanvas, sigh */
 
+#ifndef PLATFORM_WINDOWS
        pango_ft2_font_map_set_resolution ((PangoFT2FontMap*) pango_ft2_font_map_new(), val/1024, val/1024);
+#endif
 
        /* Cairo rendering, in case there is any */
 
@@ -841,3 +978,15 @@ unique_random_color (list<Gdk::Color>& used_colors)
                /* XXX need throttle here to make sure we don't spin for ever */
        }
 }
+
+string 
+rate_as_string (float r)
+{
+       char buf[32];
+       if (fmod (r, 1000.0f)) {
+               snprintf (buf, sizeof (buf), "%.1f kHz", r/1000.0);
+       } else {
+               snprintf (buf, sizeof (buf), "%.0f kHz", r/1000.0);
+       }
+       return buf;
+}