From 220e36f0f54dcb0342ba32b6325e9add2f47347c Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Wed, 29 Jul 2020 15:07:07 +0200 Subject: Add embedded gettext support from resource. --- configure.ac | 23 +++- plugin/Makefile.am | 9 +- plugin/Makefile.mingw32.in | 68 +++++----- plugin/drumgizmo_plugin.h | 7 + plugingui/Makefile.am | 115 +++++++++++------ plugingui/locale/Makefile.am | 4 + plugingui/locale/da.po | 72 +++++++++++ plugingui/locale/drumgizmo.pot | 69 ++++++++++ plugingui/locale/fr.po | 71 ++++++++++ plugingui/maintab.cc | 22 ++-- plugingui/mainwindow.cc | 14 +- plugingui/resource.cc | 2 +- plugingui/testmain.cc | 7 + plugingui/uitranslation.cc | 51 ++++++++ plugingui/uitranslation.h | 41 ++++++ src/Makefile.am | 10 +- src/translation.cc | 287 +++++++++++++++++++++++++++++++++++++++++ src/translation.h | 60 +++++++++ test/Makefile.am | 42 +++++- test/locale/da.mo | Bin 0 -> 948 bytes test/resource_test.cc | 5 + test/translationtest.cc | 80 ++++++++++++ test/uitests/Makefile.am | 9 +- 23 files changed, 976 insertions(+), 92 deletions(-) create mode 100644 plugingui/locale/Makefile.am create mode 100644 plugingui/locale/da.po create mode 100644 plugingui/locale/drumgizmo.pot create mode 100644 plugingui/locale/fr.po create mode 100644 plugingui/uitranslation.cc create mode 100644 plugingui/uitranslation.h create mode 100644 src/translation.cc create mode 100644 src/translation.h create mode 100644 test/locale/da.mo create mode 100644 test/translationtest.cc diff --git a/configure.ac b/configure.ac index 123e884..1151ad1 100644 --- a/configure.ac +++ b/configure.ac @@ -127,7 +127,7 @@ AC_LANG_POP([C++]) dnl =========================== dnl Set up debug compile args if the user requested it dnl =========================== -AS_IF([test "x$with_debug" == "xyes"], +AS_IF([test "x$with_debug" = "xyes"], [AC_MSG_WARN([*** Building with debug support!]) DEBUG_FLAGS="-Wall -Werror -g $NO_UNDEFINED_PARAM" HUGIN_PARM=""] @@ -136,6 +136,26 @@ AC_SUBST(DEBUG_FLAGS) CXXFLAGS="$CXXFLAGS $HUGIN_PARM" + +dnl =========================== +dnl Enable/disable NLS support +dnl =========================== +AC_ARG_WITH([nls], + AS_HELP_STRING([--with-nls], + [Build with nls support (default nls enabled)]), + [], + [with_nls=yes]) + AS_IF([test "x$with_nls" == "xyes"], + [AC_MSG_RESULT([*** Building with nls support!]) + AC_CHECK_PROGS([XGETTEXT], [xgettext]) + AC_CHECK_PROGS([MSGMERGE], [msgmerge]) + AC_CHECK_PROGS([MSGFMT], [msgfmt]) + AC_DEFINE_UNQUOTED([WITH_NLS], , [Build with nls support])], + [AC_MSG_WARN([*** Building without nls support!])] +) +AM_CONDITIONAL([WITH_NLS], [test "x$with_nls" = "xyes"]) + + dnl =========================== dnl Check for GUI backend dnl =========================== @@ -690,6 +710,7 @@ AC_CONFIG_FILES( plugin/Makefile plugin/vst/Makefile plugingui/Makefile + plugingui/locale/Makefile man/Makefile test/Makefile test/dgreftest/Makefile diff --git a/plugin/Makefile.am b/plugin/Makefile.am index 91786c2..f382acc 100644 --- a/plugin/Makefile.am +++ b/plugin/Makefile.am @@ -36,7 +36,8 @@ drumgizmo_la_LDFLAGS = -shared -module -avoid-version \ drumgizmo_la_LIBADD = $(LV2_LIBS) \ $(top_builddir)/plugingui/libdggui.la \ - $(top_builddir)/src/libdg.la + $(top_builddir)/src/libdg.la \ + $(top_builddir)/src/libnls.la ttlgen_CPPFLAGS = \ $(DEBUG_FLAGS) \ @@ -108,9 +109,11 @@ drumgizmo_vst_la_SOURCES = \ drumgizmo_vst_la_LDFLAGS = -shared -module -avoid-version \ -no-undefined -export-symbols $(top_srcdir)/plugin/drumgizmo_vst.sym -drumgizmo_vst_la_LIBADD = vst/libvstsdk.la \ +drumgizmo_vst_la_LIBADD = \ + vst/libvstsdk.la \ $(top_builddir)/plugingui/libdggui.la \ - $(top_builddir)/src/libdg.la + $(top_builddir)/src/libdg.la \ + $(top_builddir)/src/libnls.la install-data-hook: diff --git a/plugin/Makefile.mingw32.in b/plugin/Makefile.mingw32.in index fad7960..e58abc4 100644 --- a/plugin/Makefile.mingw32.in +++ b/plugin/Makefile.mingw32.in @@ -47,6 +47,7 @@ DG_SRC = \ @top_srcdir@/src/sem.cc \ @top_srcdir@/src/staminafilter.cc \ @top_srcdir@/src/thread.cc \ + @top_srcdir@/src/translation.cc \ @top_srcdir@/src/velocityfilter.cc \ @top_srcdir@/src/versionstr.cc DG_CFLAGS = -I@top_srcdir@ -I@top_srcdir@/src \ @@ -108,6 +109,7 @@ GUI_SRC = \ @top_srcdir@/plugingui/timingframecontent.cc \ @top_srcdir@/plugingui/toggle.cc \ @top_srcdir@/plugingui/tooltip.cc \ + @top_srcdir@/plugingui/uitranslation.cc \ @top_srcdir@/plugingui/utf8.cc \ @top_srcdir@/plugingui/verticalline.cc \ @top_srcdir@/plugingui/visualizerframecontent.cc \ @@ -143,39 +145,45 @@ SRC = \ drumgizmo_plugin.cc RES = \ - resources/bg.png \ - resources/bypass_button.png \ - resources/font.png \ - resources/fontemboss.png \ - resources/help_button.png \ - resources/knob.png \ - resources/logo.png \ - resources/png_error \ - resources/progress.png \ - resources/pushbutton.png \ - resources/sidebar.png \ - resources/slider.png \ - resources/stddev_horizontal.png \ - resources/stddev_horizontal_disabled.png \ - resources/stddev_vertical.png \ - resources/stddev_vertical_disabled.png \ - resources/switch_back_off.png \ - resources/switch_back_on.png \ - resources/switch_front.png \ - resources/tab.png \ - resources/thinlistbox.png \ - resources/topbar.png \ - resources/toplogo.png \ - resources/vertline.png \ - resources/widget.png \ - ../ABOUT \ - ../AUTHORS \ - ../BUGS \ - ../COPYING + @top_srcdir@/plugingui/resources/bg.png \ + @top_srcdir@/plugingui/resources/bypass_button.png \ + @top_srcdir@/plugingui/resources/font.png \ + @top_srcdir@/plugingui/resources/fontemboss.png \ + @top_srcdir@/plugingui/resources/help_button.png \ + @top_srcdir@/plugingui/resources/knob.png \ + @top_srcdir@/plugingui/resources/logo.png \ + @top_srcdir@/plugingui/resources/png_error \ + @top_srcdir@/plugingui/resources/progress.png \ + @top_srcdir@/plugingui/resources/pushbutton.png \ + @top_srcdir@/plugingui/resources/sidebar.png \ + @top_srcdir@/plugingui/resources/slider.png \ + @top_srcdir@/plugingui/resources/stddev_horizontal.png \ + @top_srcdir@/plugingui/resources/stddev_horizontal_disabled.png \ + @top_srcdir@/plugingui/resources/stddev_vertical.png \ + @top_srcdir@/plugingui/resources/stddev_vertical_disabled.png \ + @top_srcdir@/plugingui/resources/switch_back_off.png \ + @top_srcdir@/plugingui/resources/switch_back_on.png \ + @top_srcdir@/plugingui/resources/switch_front.png \ + @top_srcdir@/plugingui/resources/tab.png \ + @top_srcdir@/plugingui/resources/thinlistbox.png \ + @top_srcdir@/plugingui/resources/topbar.png \ + @top_srcdir@/plugingui/resources/toplogo.png \ + @top_srcdir@/plugingui/resources/vertline.png \ + @top_srcdir@/plugingui/resources/widget.png \ + @top_srcdir@/plugingui/../ABOUT \ + @top_srcdir@/plugingui/../AUTHORS \ + @top_srcdir@/plugingui/../BUGS \ + @top_srcdir@/plugingui/../COPYING + +NLS_RES = \ + @top_builddir@/plugingui/locale/da.mo \ + @top_builddir@/plugingui/locale/fr.mo all: + (cd @top_srcdir@/plugingui/locale; msgfmt -c -v -o da.mo da.po) + (cd @top_srcdir@/plugingui/locale; msgfmt -c -v -o fr.mo fr.po) g++ -I@top_srcdir@/getoptpp @top_srcdir@/plugingui/rcgen.cc -o @top_srcdir@/plugingui/rcgen - (cd @top_srcdir@/plugingui; ./rcgen $(RES) > resource_data.cc) + @top_srcdir@/plugingui/rcgen -s @top_srcdir@/plugingui/ -s @top_builddir@/plugingui/ $(RES) $(NLS_RES) -o @top_srcdir@/plugingui/resource_data.cc g++ $(CXXFLAGS) @top_srcdir@/plugingui/resource_data.cc -c gcc $(CFLAGS) $(DBG_CFLAGS) @top_srcdir@/hugin/hugin.c -c gcc $(CFLAGS) $(DBG_CFLAGS) @top_srcdir@/hugin/hugin_syslog.c -c diff --git a/plugin/drumgizmo_plugin.h b/plugin/drumgizmo_plugin.h index 1f91fbc..521ec86 100644 --- a/plugin/drumgizmo_plugin.h +++ b/plugin/drumgizmo_plugin.h @@ -26,6 +26,8 @@ */ #pragma once +#include + #include #ifdef LV2 @@ -37,6 +39,7 @@ #endif #include +#include #include #include #include @@ -214,4 +217,8 @@ private: static constexpr std::size_t width{750}; static constexpr std::size_t height{713}; + +#ifdef WITH_NLS + UITranslation translation; +#endif // WITH_NLS }; diff --git a/plugingui/Makefile.am b/plugingui/Makefile.am index cb49d53..64f0125 100644 --- a/plugingui/Makefile.am +++ b/plugingui/Makefile.am @@ -1,44 +1,78 @@ +SUBDIRS = locale +DISTDIRS = locale + noinst_PROGRAMS = plugingui rcgen noinst_LTLIBRARIES = libdggui.la # If you add a file here, remember to add it to plugin/Makefile.mingw32.in RES = \ - resources/bg.png \ - resources/bypass_button.png \ - resources/font.png \ - resources/fontemboss.png \ - resources/help_button.png \ - resources/knob.png \ - resources/logo.png \ - resources/png_error \ - resources/progress.png \ - resources/pushbutton.png \ - resources/sidebar.png \ - resources/slider.png \ - resources/stddev_horizontal.png \ - resources/stddev_horizontal_disabled.png \ - resources/stddev_vertical.png \ - resources/stddev_vertical_disabled.png \ - resources/switch_back_off.png \ - resources/switch_back_on.png \ - resources/switch_front.png \ - resources/tab.png \ - resources/thinlistbox.png \ - resources/topbar.png \ - resources/toplogo.png \ - resources/vertline.png \ - resources/widget.png \ - ../ABOUT \ - ../AUTHORS \ - ../BUGS \ - ../COPYING + $(top_srcdir)/plugingui/resources/bg.png \ + $(top_srcdir)/plugingui/resources/bypass_button.png \ + $(top_srcdir)/plugingui/resources/font.png \ + $(top_srcdir)/plugingui/resources/fontemboss.png \ + $(top_srcdir)/plugingui/resources/help_button.png \ + $(top_srcdir)/plugingui/resources/knob.png \ + $(top_srcdir)/plugingui/resources/logo.png \ + $(top_srcdir)/plugingui/resources/png_error \ + $(top_srcdir)/plugingui/resources/progress.png \ + $(top_srcdir)/plugingui/resources/pushbutton.png \ + $(top_srcdir)/plugingui/resources/sidebar.png \ + $(top_srcdir)/plugingui/resources/slider.png \ + $(top_srcdir)/plugingui/resources/stddev_horizontal.png \ + $(top_srcdir)/plugingui/resources/stddev_horizontal_disabled.png \ + $(top_srcdir)/plugingui/resources/stddev_vertical.png \ + $(top_srcdir)/plugingui/resources/stddev_vertical_disabled.png \ + $(top_srcdir)/plugingui/resources/switch_back_off.png \ + $(top_srcdir)/plugingui/resources/switch_back_on.png \ + $(top_srcdir)/plugingui/resources/switch_front.png \ + $(top_srcdir)/plugingui/resources/tab.png \ + $(top_srcdir)/plugingui/resources/thinlistbox.png \ + $(top_srcdir)/plugingui/resources/topbar.png \ + $(top_srcdir)/plugingui/resources/toplogo.png \ + $(top_srcdir)/plugingui/resources/vertline.png \ + $(top_srcdir)/plugingui/resources/widget.png \ + $(top_srcdir)/plugingui/../ABOUT \ + $(top_srcdir)/plugingui/../AUTHORS \ + $(top_srcdir)/plugingui/../BUGS \ + $(top_srcdir)/plugingui/../COPYING + +if WITH_NLS +$(top_srcdir)/plugingui/locale/drumgizmo.pot: $(GUI_SRC) + (cd $(top_srcdir)/plugingui/; $(XGETTEXT) --package-name "$(PACKAGE)" --package-version "$(VERSION)" --copyright-holder="DrumGizmo Team" -k_ -o locale/drumgizmo.pot $(GUI_SRC) ) + grep -v '"POT-Creation-Date:' $(top_srcdir)/plugingui/locale/drumgizmo.pot > $(top_srcdir)/plugingui/locale/drumgizmo.pot.tmp + mv $(top_srcdir)/plugingui/locale/drumgizmo.pot.tmp $(top_srcdir)/plugingui/locale/drumgizmo.pot + +NLS_RES = \ + $(top_builddir)/plugingui/locale/da.mo \ + $(top_builddir)/plugingui/locale/fr.mo + +# NOTE: Manually create initial (new) .po file with msginit +$(top_srcdir)/plugingui/locale/da.po \ +$(top_srcdir)/plugingui/locale/fr.po: locale/drumgizmo.pot + $(MSGMERGE) --update $@ $(top_srcdir)/plugingui/locale/drumgizmo.pot + +$(top_builddir)/plugingui/locale/da.mo: $(top_srcdir)/plugingui/locale/da.po + $(MSGFMT) -c -v -o $@ $(top_srcdir)/plugingui/locale/da.po + +$(top_builddir)/plugingui/locale/fr.mo: $(top_srcdir)/plugingui/locale/fr.po + $(MSGFMT) -c -v -o $@ $(top_srcdir)/plugingui/locale/fr.po + +endif rcgen_verbose = $(rcgen_verbose_@AM_V@) rcgen_verbose_ = $(rcgen_verbose_@AM_DEFAULT_V@) rcgen_verbose_0 = @echo " RCGEN "$@; -$(top_builddir)/plugingui/resource_data.cc: rcgen$(EXEEXT) $(RES) - $(rcgen_verbose)./rcgen$(EXEEXT) -d $(top_srcdir)/plugingui -o $@ $(RES) +BUILT_SOURCES = \ + resource_data.cc \ + $(NLS_RES) + +resource_data.cc: rcgen$(EXEEXT) $(RES) $(NLS_RES) + $(rcgen_verbose)./rcgen$(EXEEXT) -s $(top_srcdir)/plugingui/ -s $(top_builddir)/plugingui/ -o $@ $(RES) $(NLS_RES) + +CLEANFILES = \ + resource_data.cc \ + $(NLS_RES) libdggui_la_CPPFLAGS = \ $(DEBUG_FLAGS) \ @@ -61,7 +95,7 @@ libdggui_la_LIBADD = \ $(GUI_LIBS) $(PTHREAD_LIBS) # If you add a file here, remember to add it to plugin/Makefile.mingw32.in -nodist_libdggui_la_SOURCES = \ +GUI_SRC = \ abouttab.cc \ bleedcontrolframecontent.cc \ button.cc \ @@ -113,12 +147,18 @@ nodist_libdggui_la_SOURCES = \ timingframecontent.cc \ toggle.cc \ tooltip.cc \ + uitranslation.cc \ utf8.cc \ verticalline.cc \ visualizerframecontent.cc \ widget.cc \ - window.cc \ - lodepng/lodepng.cpp \ + window.cc + +libdggui_la_SOURCES = \ + $(GUI_SRC) \ + lodepng/lodepng.cpp + +nodist_libdggui_la_SOURCES = \ $(top_builddir)/plugingui/resource_data.cc if ENABLE_X11 @@ -169,7 +209,10 @@ libdggui_la_CPPFLAGS += \ -I$(top_srcdir)/pugl endif -plugingui_LDADD = libdggui.la $(top_builddir)/src/libdg.la +plugingui_LDADD = \ + libdggui.la \ + $(top_builddir)/src/libdg.la \ + $(top_builddir)/src/libnls.la plugingui_CXXFLAGS = \ $(DEBUG_FLAGS) \ @@ -190,7 +233,6 @@ rcgen_SOURCES = \ rcgen.cc EXTRA_DIST = \ - $(nodist_libdggui_la_SOURCES) \ $(RES) \ abouttab.h \ bleedcontrolframecontent.h \ @@ -257,6 +299,7 @@ EXTRA_DIST = \ timingframecontent.h \ toggle.h \ tooltip.h \ + uitranslation.h \ utf8.h \ verticalline.h \ visualizerframecontent.h \ diff --git a/plugingui/locale/Makefile.am b/plugingui/locale/Makefile.am new file mode 100644 index 0000000..a5d93bb --- /dev/null +++ b/plugingui/locale/Makefile.am @@ -0,0 +1,4 @@ +EXTRA_DIST = \ + drumgizmo.pot \ + da.po \ + fr.po diff --git a/plugingui/locale/da.po b/plugingui/locale/da.po new file mode 100644 index 0000000..579b3c3 --- /dev/null +++ b/plugingui/locale/da.po @@ -0,0 +1,72 @@ +# Danish translations for drumgizmo package +# Danske oversættelser for pakke drumgizmo. +# Copyright (C) 2019 THE drumgizmo'S COPYRIGHT HOLDER +# This file is distributed under the same license as the drumgizmo package. +# Automatically generated, 2019. +# +msgid "" +msgstr "" +"Project-Id-Version: drumgizmo 0.9.17\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-13 21:07+0200\n" +"PO-Revision-Date: 2019-09-13 19:42+0200\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: da\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-1\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: maintab.cc:121 mainwindow.cc:56 +msgid "Drumkit" +msgstr "" + +#: maintab.cc:122 +msgid "Status" +msgstr "" + +#: maintab.cc:123 +msgid "Resampling" +msgstr "" + +#: maintab.cc:124 +msgid "Disk Streaming" +msgstr "" + +#: maintab.cc:125 +msgid "Bleed Control" +msgstr "" + +#: maintab.cc:127 +msgid "Velocity Humanizer" +msgstr "" + +#: maintab.cc:129 +msgid "Timing Humanizer" +msgstr "" + +#: maintab.cc:131 +msgid "Sample Selection" +msgstr "" + +#: maintab.cc:134 +msgid "Visualizer" +msgstr "" + +#: maintab.cc:136 +#, fuzzy +msgid "Velocity Curve" +msgstr "" + +#: mainwindow.cc:51 +msgid "DrumGizmo v" +msgstr "" + +#: mainwindow.cc:55 +msgid "Main" +msgstr "" + +#: mainwindow.cc:58 +msgid "About" +msgstr "" diff --git a/plugingui/locale/drumgizmo.pot b/plugingui/locale/drumgizmo.pot new file mode 100644 index 0000000..5fcce8b --- /dev/null +++ b/plugingui/locale/drumgizmo.pot @@ -0,0 +1,69 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) 2020 DrumGizmo Team +# This file is distributed under the same license as the drumgizmo package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: drumgizmo 0.9.19\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: maintab.cc:121 mainwindow.cc:56 +msgid "Drumkit" +msgstr "" + +#: maintab.cc:122 +msgid "Status" +msgstr "" + +#: maintab.cc:123 +msgid "Resampling" +msgstr "" + +#: maintab.cc:124 +msgid "Disk Streaming" +msgstr "" + +#: maintab.cc:125 +msgid "Bleed Control" +msgstr "" + +#: maintab.cc:127 +msgid "Velocity Humanizer" +msgstr "" + +#: maintab.cc:129 +msgid "Timing Humanizer" +msgstr "" + +#: maintab.cc:131 +msgid "Sample Selection" +msgstr "" + +#: maintab.cc:134 +msgid "Visualizer" +msgstr "" + +#: maintab.cc:136 +msgid "Velocity Curve" +msgstr "" + +#: mainwindow.cc:51 +msgid "DrumGizmo v" +msgstr "" + +#: mainwindow.cc:55 +msgid "Main" +msgstr "" + +#: mainwindow.cc:58 +msgid "About" +msgstr "" diff --git a/plugingui/locale/fr.po b/plugingui/locale/fr.po new file mode 100644 index 0000000..6582266 --- /dev/null +++ b/plugingui/locale/fr.po @@ -0,0 +1,71 @@ +# Danish translations for drumgizmo package +# Danske oversættelser for pakke drumgizmo. +# Copyright (C) 2019 THE drumgizmo'S COPYRIGHT HOLDER +# This file is distributed under the same license as the drumgizmo package. +# Automatically generated, 2019. +# +msgid "" +msgstr "" +"Project-Id-Version: drumgizmo 0.9.17\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-13 21:07+0200\n" +"PO-Revision-Date: 2019-09-09 16:21+0200\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: da\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-1\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: maintab.cc:121 mainwindow.cc:56 +msgid "Drumkit" +msgstr "" + +#: maintab.cc:122 +msgid "Status" +msgstr "" + +#: maintab.cc:123 +msgid "Resampling" +msgstr "" + +#: maintab.cc:124 +msgid "Disk Streaming" +msgstr "" + +#: maintab.cc:125 +msgid "Bleed Control" +msgstr "" + +#: maintab.cc:127 +msgid "Velocity Humanizer" +msgstr "" + +#: maintab.cc:129 +msgid "Timing Humanizer" +msgstr "" + +#: maintab.cc:131 +msgid "Sample Selection" +msgstr "" + +#: maintab.cc:134 +msgid "Visualizer" +msgstr "" + +#: maintab.cc:136 +msgid "Velocity Curve" +msgstr "" + +#: mainwindow.cc:51 +msgid "DrumGizmo v" +msgstr "" + +#: mainwindow.cc:55 +msgid "Main" +msgstr "" + +#: mainwindow.cc:58 +msgid "About" +msgstr "" diff --git a/plugingui/maintab.cc b/plugingui/maintab.cc index 771e0d2..5b5555f 100644 --- a/plugingui/maintab.cc +++ b/plugingui/maintab.cc @@ -26,6 +26,8 @@ */ #include "maintab.h" +#include + namespace { @@ -116,22 +118,22 @@ MainTab::MainTab(Widget* parent, layout.setSpacing(0); layout.setResizeChildren(true); - add("Drumkit", drumkit_frame, drumkitframe_content, 12, 0); - add("Status", status_frame, statusframe_content, 14, 0); - add("Resampling", resampling_frame, resamplingframe_content, 9, 0); - add("Disk Streaming", diskstreaming_frame, diskstreamingframe_content, 7, 0); - add("Bleed Control", bleedcontrol_frame, bleedcontrolframe_content, 7, 0); + add(_("Drumkit"), drumkit_frame, drumkitframe_content, 12, 0); + add(_("Status"), status_frame, statusframe_content, 14, 0); + add(_("Resampling"), resampling_frame, resamplingframe_content, 9, 0); + add(_("Disk Streaming"), diskstreaming_frame, diskstreamingframe_content, 7, 0); + add(_("Bleed Control"), bleedcontrol_frame, bleedcontrolframe_content, 7, 0); - add("Velocity Humanizer", humanizer_frame, humanizerframe_content, 8, 1); + add(_("Velocity Humanizer"), humanizer_frame, humanizerframe_content, 8, 1); humanizer_frame.setHelpText(humanizer_tip); - add("Timing Humanizer", timing_frame, timingframe_content, 8, 1); + add(_("Timing Humanizer"), timing_frame, timingframe_content, 8, 1); timing_frame.setHelpText(timing_tip); - add("Sample Selection", sampleselection_frame, + add(_("Sample Selection"), sampleselection_frame, sampleselectionframe_content, 8, 1); sampleselection_frame.setHelpText(sampleselection_tip); - add("Visualizer", visualizer_frame, visualizerframe_content, 8, 1); + add(_("Visualizer"), visualizer_frame, visualizerframe_content, 8, 1); visualizer_frame.setHelpText(visualizer_tip); - add("Velocity Curve", power_frame, powerframe_content, 17, 1); + add(_("Velocity Curve"), power_frame, powerframe_content, 17, 1); power_frame.setHelpText(power_tip); humanizer_frame.setOnSwitch(settings.enable_velocity_modifier); diff --git a/plugingui/mainwindow.cc b/plugingui/mainwindow.cc index a625bc3..932e8f3 100644 --- a/plugingui/mainwindow.cc +++ b/plugingui/mainwindow.cc @@ -26,11 +26,13 @@ */ #include "mainwindow.h" +#include + #include -#include "painter.h" +#include -#include +#include "painter.h" namespace GUI { @@ -46,14 +48,14 @@ MainWindow::MainWindow(Settings& settings, void* native_window) CONNECT(this, sizeChangeNotifier, this, &MainWindow::sizeChanged); CONNECT(eventHandler(), closeNotifier, this, &MainWindow::closeEventHandler); - setCaption("DrumGizmo v" VERSION); + setCaption(std::string(_("DrumGizmo v")) + VERSION); tabs.setTabWidth(100); tabs.move(16, 0); // x-offset to make room for the left side bar. - tabs.addTab("Main", &main_tab); - drumkit_tab_id = tabs.addTab("Drumkit", &drumkit_tab); + tabs.addTab(_("Main"), &main_tab); + drumkit_tab_id = tabs.addTab(_("Drumkit"), &drumkit_tab); changeDrumkitTabVisibility(false); // Hide while no kit is loaded - tabs.addTab("About", &about_tab); + tabs.addTab(_("About"), &about_tab); CONNECT(&drumkit_tab, imageChangeNotifier, this, &MainWindow::changeDrumkitTabVisibility); diff --git a/plugingui/resource.cc b/plugingui/resource.cc index 3462317..44f5540 100644 --- a/plugingui/resource.cc +++ b/plugingui/resource.cc @@ -77,7 +77,7 @@ Resource::Resource(const std::string& name) // Find internal resource in rc_data. const rc_data_t* p = rc_data; - while(p->name[0] != '\0') // last entry in rc_data has the name := "" + while(*p->name) // last entry in rc_data has the name := "" { if(name == p->name) { diff --git a/plugingui/testmain.cc b/plugingui/testmain.cc index 91effc4..1195ceb 100644 --- a/plugingui/testmain.cc +++ b/plugingui/testmain.cc @@ -29,12 +29,19 @@ #include #include +#include #include "mainwindow.h" #include "window.h" +#include "resource.h" +#include "uitranslation.h" int main() { +#ifdef WITH_NLS + UITranslation translation; +#endif // WITH_NLS + INFO(example, "We are up and running"); void* native_window_handle{nullptr}; diff --git a/plugingui/uitranslation.cc b/plugingui/uitranslation.cc new file mode 100644 index 0000000..0546be8 --- /dev/null +++ b/plugingui/uitranslation.cc @@ -0,0 +1,51 @@ +/* -*- Mode: c++ -*- */ +/*************************************************************************** + * uitranslation.cc + * + * Thu May 7 18:04:40 CEST 2020 + * Copyright 2020 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "uitranslation.h" + +#ifdef WITH_NLS + +#include "resource.h" + +UITranslation::UITranslation() +{ + auto lang = Translation::getISO639LanguageName(); + printf("LANG: %s\n", lang.data()); + std::string res = ":locale/"; + res += lang + ".mo"; + + GUI::Resource mo(res); + if(!mo.valid()) + { + printf("Locale not in resources - use default\n"); + // Locale not in resources - use default + return; + } + printf("Using mo: %s\n", res.data()); + load(mo.data(), mo.size()); +} + +#endif // WITH_NLS diff --git a/plugingui/uitranslation.h b/plugingui/uitranslation.h new file mode 100644 index 0000000..5341255 --- /dev/null +++ b/plugingui/uitranslation.h @@ -0,0 +1,41 @@ +/* -*- Mode: c++ -*- */ +/*************************************************************************** + * uitranslation.h + * + * Thu May 7 18:04:40 CEST 2020 + * Copyright 2020 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include + +#include + +#ifdef WITH_NLS +class UITranslation + : public Translation +{ +public: + UITranslation(); + ~UITranslation() = default; +}; +#endif diff --git a/src/Makefile.am b/src/Makefile.am index f2a392d..b656f48 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,4 +1,11 @@ -noinst_LTLIBRARIES = libdg.la libzr.la libpugi.la +noinst_LTLIBRARIES = libdg.la libzr.la libpugi.la libnls.la + +# shared nls component + +libnls_la_CPPFLAGS = +libnls_la_LIBADD = +libnls_la_SOURCES = \ + translation.cc # libzita-resampler @@ -129,6 +136,7 @@ EXTRA_DIST = \ staminafilter.h \ syncedsettings.h \ thread.h \ + translation.h \ velocityfilter.h \ versionstr.h \ zrwrapper.h diff --git a/src/translation.cc b/src/translation.cc new file mode 100644 index 0000000..18763e4 --- /dev/null +++ b/src/translation.cc @@ -0,0 +1,287 @@ +/* -*- Mode: c++ -*- */ +/*************************************************************************** + * translation.cc + * + * Sun Sep 8 14:13:22 CEST 2019 + * Copyright 2019 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "translation.h" + +#ifdef WITH_NLS + +#include +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#endif + +namespace +{ +using Text = std::pair; +using Texts = std::vector; + +struct +{ + std::mutex mutex; + int refcnt{0}; + Texts texts; +} singleton; + + +bool comparator(const Text& a, const Text& b) +{ + return a.first < b.first; +} +} + +Translation::Translation() +{ + std::lock_guard(singleton.mutex); + ++singleton.refcnt; +} + +Translation::~Translation() +{ + std::lock_guard(singleton.mutex); + + --singleton.refcnt; + + if(singleton.refcnt == 0) + { + singleton.texts.clear(); + } +} + +bool Translation::load(const char* catalog, std::size_t size) +{ + Texts texts; + + // https://www.gnu.org/software/gettext/manual/html_node/MO-Files.html + + // byte + // +------------------------------------------+ + // 0 | magic number = 0x950412de | + // | | + // 4 | file format revision = 0 | + // | | + // 8 | number of strings | == N + // | | + // 12 | offset of table with original strings | == O + // | | + // 16 | offset of table with translation strings | == T + // | | + // 20 | size of hashing table | == S + // | | + // 24 | offset of hashing table | == H + // | | + // . . + // . (possibly more entries later) . + // . . + // | | + // O | length & offset 0th string ----------------. + // O + 8 | length & offset 1st string ------------------. + // ... ... | | + // O + ((N-1)*8)| length & offset (N-1)th string | | | + // | | | | + // T | length & offset 0th translation ---------------. + // T + 8 | length & offset 1st translation -----------------. + // ... ... | | | | + // T + ((N-1)*8)| length & offset (N-1)th translation | | | | | + // | | | | | | + // H | start hash table | | | | | + // ... ... | | | | + // H + S * 4 | end hash table | | | | | + // | | | | | | + // | NUL terminated 0th string <----------------' | | | + // | | | | | + // | NUL terminated 1st string <------------------' | | + // | | | | + // ... ... | | + // | | | | + // | NUL terminated 0th translation <---------------' | + // | | | + // | NUL terminated 1st translation <-----------------' + // | | + // ... ... + // | | + // +------------------------------------------+ + constexpr std::uint32_t magic_number_le = 0x950412de; + constexpr std::uint32_t magic_number_be = 0xde120495; + + const char* ptr = catalog; + + // Verify magic number + std::uint32_t magic_number = *reinterpret_cast(ptr); + if(magic_number != magic_number_le && magic_number != magic_number_be) + { + // Error - bad magic number + return false; + } + ptr += sizeof(magic_number); + + // Verify file format revision + std::uint32_t file_format_revision = + *reinterpret_cast(ptr); + if(file_format_revision != 0) + { + // Error - bad file format revision + return false; + } + ptr += sizeof(file_format_revision); + + // Read number of string in the catalog + std::uint32_t number_of_strings = + *reinterpret_cast(ptr); + ptr += sizeof(number_of_strings); + + // Read orig_table_offset + std::uint32_t orig_table_offset = + *reinterpret_cast(ptr); + ptr += sizeof(orig_table_offset); + + // Read transl_table_offset + std::uint32_t transl_table_offset = + *reinterpret_cast(ptr); + ptr += sizeof(transl_table_offset); + + // Read hash_table_size + std::uint32_t hash_table_size = + *reinterpret_cast(ptr); + ptr += sizeof(hash_table_size); + + // Read hash_table_offset + std::uint32_t hash_table_offset = + *reinterpret_cast(ptr); + ptr += sizeof(hash_table_offset); + + + // Read original/translated string tables: + const char* orig_ptr = catalog + orig_table_offset; + const char* transl_ptr = catalog + transl_table_offset; + for(std::uint32_t string_index = 0; + string_index < number_of_strings; ++string_index) + { + // Read string_length + std::uint32_t orig_string_length = + *reinterpret_cast(orig_ptr); + orig_ptr += sizeof(orig_string_length); + + // Read string_offset + std::uint32_t orig_string_offset = + *reinterpret_cast(orig_ptr); + orig_ptr += sizeof(orig_string_offset); + + std::string orig; + orig.append(catalog + orig_string_offset, orig_string_length); + + // Read string_length + std::uint32_t transl_string_length = + *reinterpret_cast(transl_ptr); + transl_ptr += sizeof(transl_string_length); + + // Read string_offset + std::uint32_t transl_string_offset = + *reinterpret_cast(transl_ptr); + transl_ptr += sizeof(transl_string_offset); + + std::string transl; + transl.append(catalog + transl_string_offset, transl_string_length); + + texts.push_back(make_pair(const_hash(orig.data()), transl)); + } + + std::sort(texts.begin(), texts.end(), comparator); + + { + std::lock_guard(singleton.mutex); + std::swap(singleton.texts, texts); + } + + return true; +} + +const char* Translation::gettext(std::uint64_t msgid, const char* original) +{ + std::lock_guard(singleton.mutex); + if(singleton.refcnt == 0) + { + return original; + } + + auto it = std::lower_bound(singleton.texts.begin(), + singleton.texts.end(), + make_pair(msgid, std::string()), comparator); + if(it == singleton.texts.end() || + it->first != msgid) + { + return original; + } + + return it->second.data(); +} + +std::string Translation::getISO639LanguageName() +{ + std::string lang; + +#ifdef _WIN32 + LCID lcid = GetUserDefaultLCID(); + char name[LOCALE_NAME_MAX_LENGTH]; + GetLocaleInfo(lcid, LOCALE_SISO639LANGNAME, name, LOCALE_NAME_MAX_LENGTH); + lang = name; +#else + try + { + auto langstr = setlocale(LC_ALL, ""); + if(langstr != nullptr) + { + lang = langstr; + } + } + catch(...) + { + // Bad locale: don't load anything - use default + printf("Bad locale: don't load anything - use default\n"); + return ""; + } + + if(lang == "C") + { + printf("Don't load anything - use default\n"); + return ""; // Don't load anything - use default + } + + auto _ = lang.find('_'); + lang = lang.substr(0, _); +#endif + + return lang; +} + +#endif // WITH_NLS diff --git a/src/translation.h b/src/translation.h new file mode 100644 index 0000000..7f506a6 --- /dev/null +++ b/src/translation.h @@ -0,0 +1,60 @@ +/* -*- Mode: c++ -*- */ +/*************************************************************************** + * translation.h + * + * Sun Sep 8 14:13:22 CEST 2019 + * Copyright 2019 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include + +#ifdef WITH_NLS + +#include + +std::uint64_t constexpr const_hash(const char* input) +{ + return *input ? + static_cast(*input) + 33 * const_hash(input + 1) : + 5381; +} + +#define _(msg) Translation::gettext(const_hash(msg), msg) + +class Translation +{ +public: + Translation(); + virtual ~Translation(); + + bool load(const char* catalog, std::size_t size); + + static const char* gettext(std::uint64_t msgid, const char* original); + static std::string getISO639LanguageName(); +}; + +#else + +#define _(msg) msg + +#endif diff --git a/test/Makefile.am b/test/Makefile.am index c9ece6e..372b57f 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -10,11 +10,16 @@ TESTS = resource enginetest paintertest configfile audiocache \ dgxmlparsertest domloadertest configparsertest midimapparsertest \ eventsdstest powermaptest +if WITH_NLS +TESTS += translationtest +endif + EXTRA_DIST = \ dgunit.h \ drumkit_creator.h \ lv2_test_host.h \ - scopedfile.h + scopedfile.h \ + locale/da.mo if ENABLE_LV2 TESTS += lv2 @@ -25,11 +30,13 @@ check_PROGRAMS = $(TESTS) resource_CXXFLAGS = -DOUTPUT=\"resource\" $(SNDFILE_CFLAGS) \ $(DEBUG_FLAGS) \ -I$(top_srcdir)/src \ + -I$(top_srcdir)/plugingui \ -I$(top_srcdir)/hugin resource_LDFLAGS = $(SNDFILE_LIBS) +nodist_resource_SOURCES = \ + $(top_builddir)/plugingui/resource_data.cc resource_SOURCES = \ $(top_srcdir)/plugingui/resource.cc \ - $(top_srcdir)/plugingui/resource_data.cc \ $(top_srcdir)/hugin/hugin.c \ $(top_srcdir)/src/random.cc \ dgtest.cc \ @@ -279,4 +286,35 @@ powermaptest_SOURCES = \ powermaptest.cc \ dgtest.cc +RES = \ + $(top_srcdir)/test/locale/da.mo + +rcgen_verbose = $(rcgen_verbose_@AM_V@) +rcgen_verbose_ = $(rcgen_verbose_@AM_DEFAULT_V@) +rcgen_verbose_0 = @echo " RCGEN "$@; + +translationtest_resource_data.cc: $(top_builddir)/plugingui/rcgen $(RES) + $(rcgen_verbose)$(top_builddir)/plugingui/rcgen$(EXEEXT) -s $(top_srcdir)/test/ -o $@ $(RES) + +translationtest_CXXFLAGS = \ + -DOUTPUT=\"translationtest\" \ + -I$(top_srcdir)/plugingui \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/hugin \ + -DMO_SRC=\"$(top_srcdir)/test/locale/da.mo\" \ + -Wno-invalid-source-encoding +translationtest_LDFLAGS = +nodist_translationtest_SOURCES = \ + $(top_builddir)/test/translationtest_resource_data.cc +translationtest_SOURCES = \ + $(top_srcdir)/hugin/hugin.c \ + $(top_srcdir)/plugingui/resource.cc \ + $(top_srcdir)/src/translation.cc \ + $(top_srcdir)/plugingui/uitranslation.cc \ + translationtest.cc \ + dgtest.cc + +BUILT_SOURCES = translationtest_resource_data.cc +CLEANFILES = translationtest_resource_data.cc + endif diff --git a/test/locale/da.mo b/test/locale/da.mo new file mode 100644 index 0000000..13eeaca Binary files /dev/null and b/test/locale/da.mo differ diff --git a/test/resource_test.cc b/test/resource_test.cc index 28a244e..1beae94 100644 --- a/test/resource_test.cc +++ b/test/resource_test.cc @@ -86,6 +86,11 @@ public: ResourceTester rc("no_such_file"); DGUNIT_ASSERT(!rc.valid()); } + + { + ResourceTester rc(":no_such_file"); + DGUNIT_ASSERT(!rc.valid()); + } } }; diff --git a/test/translationtest.cc b/test/translationtest.cc new file mode 100644 index 0000000..f64e1f3 --- /dev/null +++ b/test/translationtest.cc @@ -0,0 +1,80 @@ +/* -*- Mode: c++ -*- */ +/*************************************************************************** + * translationtest.cc + * + * Sun Sep 8 14:51:08 CEST 2019 + * Copyright 2019 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "dgunit.h" + +#include + +#include +#include +#include + +class TranslationTest + : public DGUnit +{ +public: + TranslationTest() + { + DGUNIT_TEST(TranslationTest::testFromFile); + DGUNIT_TEST(TranslationTest::testFromLocale); + } + + void testFromFile() + { + Translation t; + char buf[100000]; + FILE* fp = fopen(MO_SRC, "r"); + DGUNIT_ASSERT(fp != nullptr); + auto sz = fread(buf, 1, sizeof(buf), fp); + fclose(fp); + DGUNIT_ASSERT(t.load(buf, sz)); + + // Look up translation from .mo file + DGUNIT_ASSERT_EQUAL(std::string("Trommesæt"), + std::string(_("Drumkit"))); + + // No translation, return key + DGUNIT_ASSERT_EQUAL(std::string("No translation"), + std::string(_("No translation"))); + } + + void testFromLocale() + { + setenv("LANG", "da_DK.UTF-8", 1); + UITranslation t; + + // Look up translation from .mo file + DGUNIT_ASSERT_EQUAL(std::string("Trommesæt"), + std::string(_("Drumkit"))); + + // No translation, return key + DGUNIT_ASSERT_EQUAL(std::string("No translation"), + std::string(_("No translation"))); + } +}; + +// Registers the fixture into the 'registry' +static TranslationTest test; diff --git a/test/uitests/Makefile.am b/test/uitests/Makefile.am index a5e6d01..b28682f 100644 --- a/test/uitests/Makefile.am +++ b/test/uitests/Makefile.am @@ -55,7 +55,7 @@ rcgen_verbose = $(rcgen_verbose_@AM_V@) rcgen_verbose_ = $(rcgen_verbose_@AM_DEFAULT_V@) rcgen_verbose_0 = @echo " RCGEN "$@; -$(top_builddir)/test/uitests/benchmarktest_resource_data.cc: $(top_builddir)/plugingui/rcgen $(RES) +benchmarktest_resource_data.cc: $(top_builddir)/plugingui/rcgen $(RES) $(rcgen_verbose)$(top_builddir)/plugingui/rcgen$(EXEEXT) -d $(top_srcdir)/test/uitests -o $@ $(RES) benchmarktest_LDADD = \ @@ -65,11 +65,16 @@ benchmarktest_CXXFLAGS = \ -I$(top_srcdir)/plugingui \ -I$(top_srcdir)/src \ -I$(top_srcdir)/hugin +nodist_benchmarktest_SOURCES = \ + benchmarktest_resource_data.cc benchmarktest_SOURCES = \ benchmarktest.cc \ - $(top_builddir)/test/uitests/benchmarktest_resource_data.cc \ $(top_srcdir)/hugin/hugin.c +BUILT_SOURCES = benchmarktest_resource_data.cc +CLEANFILES = benchmarktest_resource_data.cc + + powerwidgettest_LDADD = \ $(top_builddir)/plugingui/libdggui.la \ $(top_builddir)/src/libdg.la -- cgit v1.2.3