diff --git a/Makefile.in b/Makefile.in index afc1bfb12..41edc3c41 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.14.1 from Makefile.am. +# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2013 Free Software Foundation, Inc. +# Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -16,7 +16,17 @@ VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -80,19 +90,6 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = . -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(top_srcdir)/configure $(am__configure_deps) $(dist_doc_DATA) \ - $(dist_pkgdata_DATA) $(nobase_dist_pkgdata_DATA) ABOUT-NLS \ - autotools/ar-lib autotools/compile autotools/config.guess \ - autotools/config.rpath autotools/config.sub autotools/depcomp \ - autotools/install-sh autotools/missing autotools/ltmain.sh \ - $(top_srcdir)/autotools/ar-lib $(top_srcdir)/autotools/compile \ - $(top_srcdir)/autotools/config.guess \ - $(top_srcdir)/autotools/config.rpath \ - $(top_srcdir)/autotools/config.sub \ - $(top_srcdir)/autotools/install-sh \ - $(top_srcdir)/autotools/ltmain.sh \ - $(top_srcdir)/autotools/missing ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_c99_func_lrint.m4 \ $(top_srcdir)/m4/ac_c99_func_lrintf.m4 \ @@ -133,6 +130,9 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ac_c99_func_lrint.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ + $(am__configure_deps) $(dist_doc_DATA) $(dist_pkgdata_DATA) \ + $(nobase_dist_pkgdata_DATA) $(am__DIST_COMMON) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d @@ -228,6 +228,17 @@ ETAGS = etags CTAGS = ctags CSCOPE = cscope DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/autotools/ar-lib \ + $(top_srcdir)/autotools/compile \ + $(top_srcdir)/autotools/config.guess \ + $(top_srcdir)/autotools/config.rpath \ + $(top_srcdir)/autotools/config.sub \ + $(top_srcdir)/autotools/install-sh \ + $(top_srcdir)/autotools/ltmain.sh \ + $(top_srcdir)/autotools/missing ABOUT-NLS autotools/ar-lib \ + autotools/compile autotools/config.guess \ + autotools/config.rpath autotools/config.sub autotools/depcomp \ + autotools/install-sh autotools/ltmain.sh autotools/missing DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) @@ -576,7 +587,6 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign Makefile -.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ @@ -892,15 +902,15 @@ dist-xz: distdir $(am__post_remove_distdir) dist-tarZ: distdir - @echo WARNING: "Support for shar distribution archives is" \ - "deprecated." >&2 + @echo WARNING: "Support for distribution archives compressed with" \ + "legacy program 'compress' is deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__post_remove_distdir) dist-shar: distdir - @echo WARNING: "Support for distribution archives compressed with" \ - "legacy program 'compress' is deprecated." >&2 + @echo WARNING: "Support for shar distribution archives is" \ + "deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz $(am__post_remove_distdir) @@ -936,17 +946,17 @@ distcheck: dist esac chmod -R a-w $(distdir) chmod u+w $(distdir) - mkdir $(distdir)/_build $(distdir)/_inst + mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ - && $(am__cd) $(distdir)/_build \ - && ../configure \ + && $(am__cd) $(distdir)/_build/sub \ + && ../../configure \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ - --srcdir=.. --prefix="$$dc_install_base" \ + --srcdir=../.. --prefix="$$dc_install_base" \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ @@ -1132,6 +1142,8 @@ uninstall-am: uninstall-binSCRIPTS uninstall-dist_docDATA \ uninstall-dist_docDATA uninstall-dist_pkgdataDATA \ uninstall-nobase_dist_pkgdataDATA +.PRECIOUS: Makefile + audacity$(EXEEXT): src/audacity$(EXEEXT) rm -f audacity$(EXEEXT) diff --git a/configure b/configure index 446c10b48..cd58a082e 100755 --- a/configure +++ b/configure @@ -1702,7 +1702,7 @@ Optional Packages: (or the compiler's sysroot if not specified). --with-lib-preference whether to use local and/or system libraries, in order of preference (default="system local") - --with-wx-version select wxWidgets version (if both installed) [2.8,] + --with-wx-version select wxWidgets version (if both installed) [3.0,] --with-expat which expat to use for XML file support: [system,local] --with-ffmpeg use ffmpeg for import and export support @@ -2889,7 +2889,7 @@ ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. -am__api_version='1.14' +am__api_version='1.15' # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or @@ -3061,8 +3061,8 @@ test "$program_suffix" != NONE && ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` -# expand $ac_aux_dir to an absolute path -am_aux_dir=`cd $ac_aux_dir && pwd` +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` if test x"${MISSING+set}" != xset; then case $am_aux_dir in @@ -3081,7 +3081,7 @@ else $as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} fi -if test x"${install_sh}" != xset; then +if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; @@ -3409,8 +3409,8 @@ MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} # mkdir_p='$(MKDIR_P)' -# We need awk for the "check" target. The system "awk" is bad on -# some platforms. +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. # Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AMTAR='$${TAR-tar}' @@ -3584,6 +3584,7 @@ END fi fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5 $as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; } # Check whether --enable-maintainer-mode was given. @@ -19774,8 +19775,10 @@ _ACEOF -# Extract the first word of "wx-config", so it can be a program name with args. -set dummy wx-config; ac_word=$2 +for ac_prog in wx-config wx-config-3.0 +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_WX_CONFIG+:} false; then : @@ -19802,7 +19805,6 @@ done done IFS=$as_save_IFS - test -z "$ac_cv_path_WX_CONFIG" && ac_cv_path_WX_CONFIG="no" ;; esac fi @@ -19816,6 +19818,10 @@ $as_echo "no" >&6; } fi + test -n "$WX_CONFIG" && break +done +test -n "$WX_CONFIG" || WX_CONFIG="no" + if [ "$WX_CONFIG" = "no" ] ; then as_fn_error $? "Could not find wx-config: is wxWidgets installed? is wx-config in your path?" "$LINENO" 5 fi @@ -19826,19 +19832,19 @@ else wxconfigargs="" fi -wxconfigargs="$static_wx_preference $unicode_preference $wxconfigargs $wx_preference" +wxconfigargs="$static_wx_preference $unicode_preference $wxconfigargs $wx_preference" wx_version=`${WX_CONFIG} $wxconfigargs --version` -{ $as_echo "$as_me:${as_lineno-$LINENO}: Checking that the chosen version of wxWidgets is 2.8.x" >&5 -$as_echo "$as_me: Checking that the chosen version of wxWidgets is 2.8.x" >&6;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: Checking that the chosen version of wxWidgets is 3.0.x" >&5 +$as_echo "$as_me: Checking that the chosen version of wxWidgets is 3.0.x" >&6;} case "${wx_version}" in - 2.8.* | 3.0.*) + 3.0.*) echo "Great, you're using wxWidgets ${wx_version}!" ;; *) wx_list=`${WX_CONFIG} --list` - as_fn_error $? "Unable to locate a suitable configuration of wxWidgets v2.8.x or higher. + as_fn_error $? "Unable to locate a suitable configuration of wxWidgets v3.0.x or higher. The currently available configurations are listed below. If necessary, either install the package for your distribution or download the latest version of wxWidgets diff --git a/configure.ac b/configure.ac index 58dc3de02..b21663ade 100644 --- a/configure.ac +++ b/configure.ac @@ -188,11 +188,9 @@ AC_ARG_ENABLE(gtk3, [AS_HELP_STRING([--enable-gtk3],[enable use of GTK+-3.0 (def AC_ARG_WITH(wx-version, [AS_HELP_STRING([--with-wx-version], - [select wxWidgets version (if both installed) [2.8,]])], + [select wxWidgets version (if both installed) [3.0,]])], wx_preference="--version=$withval", wx_preference="") -dnl At the moment we only support wx2.8. If we start supporting 3.0 when it -dnl comes out, we'll want it back again. dnl ---------------------------------------------------- dnl If user asked for debug, put debug in compiler flags @@ -274,7 +272,7 @@ dnl there isn't a way to turn them off. dnl------------------------------------------------------------- dnl wxWidgets -- we assume that if wx-config is found, wxWidgets is successfully installed. -AC_PATH_PROG(WX_CONFIG, wx-config, no, $PATH:/usr/local/bin ) +AC_PATH_PROGS(WX_CONFIG, wx-config wx-config-3.0, no, $PATH:/usr/local/bin ) if [[ "$WX_CONFIG" = "no" ]] ; then AC_MSG_ERROR([Could not find wx-config: is wxWidgets installed? is wx-config in your path?]) fi @@ -288,18 +286,18 @@ else fi dnl more things we always pass to wx-config -wxconfigargs="$static_wx_preference $unicode_preference $wxconfigargs $wx_preference" +wxconfigargs="$static_wx_preference $unicode_preference $wxconfigargs $wx_preference" wx_version=`${WX_CONFIG} $wxconfigargs --version` -AC_MSG_NOTICE([Checking that the chosen version of wxWidgets is 2.8.x]) +AC_MSG_NOTICE([Checking that the chosen version of wxWidgets is 3.0.x]) case "${wx_version}" in - 2.8.* | 3.0.*) + 3.0.*) echo "Great, you're using wxWidgets ${wx_version}!" ;; *) wx_list=`${WX_CONFIG} --list` - AC_MSG_ERROR([Unable to locate a suitable configuration of wxWidgets v2.8.x or higher. + AC_MSG_ERROR([Unable to locate a suitable configuration of wxWidgets v3.0.x or higher. The currently available configurations are listed below. If necessary, either install the package for your distribution or download the latest version of wxWidgets diff --git a/help/Makefile.in b/help/Makefile.in index 527156799..4cd49099e 100644 --- a/help/Makefile.in +++ b/help/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.14.1 from Makefile.am. +# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2013 Free Software Foundation, Inc. +# Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -15,7 +15,17 @@ @SET_MAKE@ VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -79,8 +89,6 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = help -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(dist_man_MANS) $(dist_appdata_DATA) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_c99_func_lrint.m4 \ $(top_srcdir)/m4/ac_c99_func_lrintf.m4 \ @@ -121,6 +129,8 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ac_c99_func_lrint.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(dist_appdata_DATA) \ + $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/src/configwin.h \ $(top_builddir)/src/configunix.h @@ -178,6 +188,7 @@ NROFF = nroff MANS = $(dist_man_MANS) DATA = $(dist_appdata_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(dist_man_MANS) $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ @@ -401,7 +412,6 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign help/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign help/Makefile -.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ @@ -647,6 +657,8 @@ uninstall-man: uninstall-man1 tags-am uninstall uninstall-am uninstall-dist_appdataDATA \ uninstall-man uninstall-man1 +.PRECIOUS: Makefile + # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff --git a/images/Makefile.in b/images/Makefile.in index c8c7bdf5d..5d7abcc72 100644 --- a/images/Makefile.in +++ b/images/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.14.1 from Makefile.am. +# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2013 Free Software Foundation, Inc. +# Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -15,7 +15,17 @@ @SET_MAKE@ VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -79,10 +89,6 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = images -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(dist_icons16_DATA) $(dist_icons22_DATA) $(dist_icons24_DATA) \ - $(dist_icons32_DATA) $(dist_icons48_DATA) \ - $(dist_iconsscalable_DATA) $(dist_pixmap_DATA) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_c99_func_lrint.m4 \ $(top_srcdir)/m4/ac_c99_func_lrintf.m4 \ @@ -123,6 +129,10 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ac_c99_func_lrint.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(dist_icons16_DATA) \ + $(dist_icons22_DATA) $(dist_icons24_DATA) $(dist_icons32_DATA) \ + $(dist_icons48_DATA) $(dist_iconsscalable_DATA) \ + $(dist_pixmap_DATA) $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/src/configwin.h \ $(top_builddir)/src/configunix.h @@ -182,6 +192,7 @@ DATA = $(dist_icons16_DATA) $(dist_icons22_DATA) $(dist_icons24_DATA) \ $(dist_icons32_DATA) $(dist_icons48_DATA) \ $(dist_iconsscalable_DATA) $(dist_pixmap_DATA) $(pixmap_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ @@ -483,7 +494,6 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign images/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign images/Makefile -.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ @@ -843,6 +853,8 @@ uninstall-am: uninstall-dist_icons16DATA uninstall-dist_icons22DATA \ uninstall-dist_iconsscalableDATA uninstall-dist_pixmapDATA \ uninstall-pixmapDATA +.PRECIOUS: Makefile + # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff --git a/lib-src/FileDialog/FileDialog.cpp b/lib-src/FileDialog/FileDialog.cpp index 4dd26adce..49f1b9bcc 100644 --- a/lib-src/FileDialog/FileDialog.cpp +++ b/lib-src/FileDialog/FileDialog.cpp @@ -16,28 +16,10 @@ custom controls. #include "FileDialog.h" -///////////////////////////////////////////////////////////////////////////// -// Name: common/fldlgcmn.cpp -// Purpose: wxFileDialog common functions -// Author: John Labenski -// Modified by: Leland Lucius -// Created: 14.06.03 (extracted from src/*/filedlg.cpp) -// RCS-ID: $Id: FileDialog.cpp,v 1.8 2008-10-05 14:48:59 richardash1981 Exp $ -// Copyright: (c) Robert Roebling -// Licence: wxWindows licence -// -// Modified for Audacity to support an additional button on Save dialogs -// -///////////////////////////////////////////////////////////////////////////// - -DEFINE_EVENT_TYPE(EVT_FILEDIALOG_SELECTION_CHANGED); -DEFINE_EVENT_TYPE(EVT_FILEDIALOG_FILTER_CHANGED); -DEFINE_EVENT_TYPE(EVT_FILEDIALOG_ADD_CONTROLS); - FileDialogBase::FileDialogBase() { m_creator = NULL; - m_userdata = NULL; + m_userdata = 0; } bool FileDialogBase::HasUserPaneCreator() const @@ -63,62 +45,107 @@ void FileDialogBase::CreateUserPane(wxWindow *parent) // FileDialog convenience functions //---------------------------------------------------------------------------- -wxString FileSelector(const wxString & title, - const wxString & defaultDir, - const wxString & defaultFileName, - const wxString & defaultExtension, - const wxString & filter, +///////////////////////////////////////////////////////////////////////////// +// Name: src/common/fldlgcmn.cpp +// Purpose: wxFileDialog common functions +// Author: John Labenski +// Modified by: Leland Lucius for use with Audacity +// Created: 14.06.03 (extracted from src/*/filedlg.cpp) +// Copyright: (c) Robert Roebling +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +wxString FileSelector(const wxString& title, + const wxString& defaultDir, + const wxString& defaultFileName, + const wxString& defaultExtension, + const wxString& filter, int flags, - wxWindow *parent) + wxWindow *parent, + int x, int y) { - // The defaultExtension, if non-empty, is - // appended to the filename if the user fails to type an extension. The new - // implementation (taken from wxFileSelectorEx) appends the extension - // automatically, by looking at the filter specification. In fact this - // should be better than the native Microsoft implementation because - // Windows only allows *one* default extension, whereas here we do the - // right thing depending on the filter the user has chosen. + // The defaultExtension, if non-empty, is + // appended to the filename if the user fails to type an extension. The new + // implementation (taken from FileSelectorEx) appends the extension + // automatically, by looking at the filter specification. In fact this + // should be better than the native Microsoft implementation because + // Windows only allows *one* default extension, whereas here we do the + // right thing depending on the filter the user has chosen. - // If there's a default extension specified but no filter, we create a - // suitable filter. + // If there's a default extension specified but no filter, we create a + // suitable filter. - wxString filter2; - if (!defaultExtension.empty() && filter.empty()) - filter2 = wxString(wxT("*.")) + defaultExtension; - else if (!filter.empty()) - filter2 = filter; + wxString filter2; + if ( !defaultExtension.empty() && filter.empty() ) + filter2 = wxString(wxT("*.")) + defaultExtension; + else if ( !filter.empty() ) + filter2 = filter; - FileDialog fileDialog(parent, title, defaultDir, - defaultFileName, filter2, - flags); + FileDialog fileDialog(parent, title, defaultDir, + defaultFileName, filter2, + flags, wxPoint(x, y)); - // if filter is of form "All files (*)|*|..." set correct filter index - if (!defaultExtension.empty() && filter2.find(wxT('|')) != wxString::npos) - { - int filterIndex = 0; - - wxArrayString descriptions, filters; - // don't care about errors, handled already by FileDialog - (void)wxParseCommonDialogsFilter(filter2, descriptions, filters); - - for (size_t n=0; n 0) - fileDialog.SetFilterIndex(filterIndex); - } - - wxString filename; - if (fileDialog.ShowModal() == wxID_OK) - { - filename = fileDialog.GetPath(); - } - - return filename; + // if filter is of form "All files (*)|*|..." set correct filter index + if ( !defaultExtension.empty() && filter2.find(wxT('|')) != wxString::npos ) + { + int filterIndex = 0; + + wxArrayString descriptions, filters; + // don't care about errors, handled already by FileDialog + (void)wxParseCommonDialogsFilter(filter2, descriptions, filters); + for (size_t n=0; n 0) + fileDialog.SetFilterIndex(filterIndex); + } + + wxString filename; + if ( fileDialog.ShowModal() == wxID_OK ) + { + filename = fileDialog.GetPath(); + } + + return filename; } + +//---------------------------------------------------------------------------- +// FileSelectorEx +//---------------------------------------------------------------------------- + +wxString FileSelectorEx(const wxString& title, + const wxString& defaultDir, + const wxString& defaultFileName, + int* defaultFilterIndex, + const wxString& filter, + int flags, + wxWindow* parent, + int x, + int y) + +{ + FileDialog fileDialog(parent, + title, + defaultDir, + defaultFileName, + filter, + flags, wxPoint(x, y)); + + wxString filename; + if ( fileDialog.ShowModal() == wxID_OK ) + { + if ( defaultFilterIndex ) + *defaultFilterIndex = fileDialog.GetFilterIndex(); + + filename = fileDialog.GetPath(); + } + + return filename; +} + diff --git a/lib-src/FileDialog/FileDialog.h b/lib-src/FileDialog/FileDialog.h index 3bd570af1..39e5919d8 100644 --- a/lib-src/FileDialog/FileDialog.h +++ b/lib-src/FileDialog/FileDialog.h @@ -14,29 +14,13 @@ custom controls. *//*******************************************************************/ -#ifndef _FILE_DIALOG_H_ -#define _FILE_DIALOG_H_ +#ifndef _FILEDIALOG_H_ +#define _FILEDIALOG_H_ #include #include #include -typedef void (*fdCallback)(void *, int); - -///////////////////////////////////////////////////////////////////////////// -// Name: filedlg.h -// Purpose: wxFileDialog base header -// Author: Robert Roebling -// Modified by: Leland Lucius -// Created: 8/17/99 -// Copyright: (c) Robert Roebling -// RCS-ID: $Id: FileDialog.h,v 1.9 2008-05-24 02:57:39 llucius Exp $ -// Licence: wxWindows licence -// -// Modified for Audacity to support an additional button on Save dialogs -// -///////////////////////////////////////////////////////////////////////////// - #define FD_NO_ADD_EXTENSION 0x0400 class FileDialogBase : public wxFileDialogBase @@ -57,34 +41,51 @@ protected: UserPaneCreatorFunction m_creator; wxUIntPtr m_userdata; - - wxString m_buttonlabel; - fdCallback m_callback; - void *m_cbdata; }; #if defined(__WXGTK__) -#include "gtk/FileDialog.h" +#include "gtk/FileDialogPrivate.h" #elif defined(__WXMAC__) -#include "mac/FileDialog.h" +#include "mac/FileDialogPrivate.h" #elif defined(__WXMSW__) #include "win/FileDialogPrivate.h" #else #error Unknown implementation #endif +///////////////////////////////////////////////////////////////////////////// +// Name: wx/filedlg.h +// Purpose: wxFileDialog base header +// Author: Robert Roebling +// Modified by: Leland Lucius for use by Audacity +// Created: 8/17/99 +// Copyright: (c) Robert Roebling +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + //---------------------------------------------------------------------------- // FileDialog convenience functions //---------------------------------------------------------------------------- -wxString -FileSelector(const wxString & message = wxFileSelectorPromptStr, - const wxString & default_path = wxEmptyString, - const wxString & default_filename = wxEmptyString, - const wxString & default_extension = wxEmptyString, - const wxString & wildcard = wxFileSelectorDefaultWildcardStr, +wxString +FileSelector(const wxString& message = wxFileSelectorPromptStr, + const wxString& default_path = wxEmptyString, + const wxString& default_filename = wxEmptyString, + const wxString& default_extension = wxEmptyString, + const wxString& wildcard = wxFileSelectorDefaultWildcardStr, int flags = 0, - wxWindow *parent = NULL); + wxWindow *parent = NULL, + int x = wxDefaultCoord, int y = wxDefaultCoord); + +// An extended version of FileSelector +wxString +FileSelectorEx(const wxString& message = wxFileSelectorPromptStr, + const wxString& default_path = wxEmptyString, + const wxString& default_filename = wxEmptyString, + int *indexDefaultExtension = NULL, + const wxString& wildcard = wxFileSelectorDefaultWildcardStr, + int flags = 0, + wxWindow *parent = NULL, + int x = wxDefaultCoord, int y = wxDefaultCoord); #endif - diff --git a/lib-src/FileDialog/Makefile.am b/lib-src/FileDialog/Makefile.am index a07b4eaad..282b31ccd 100644 --- a/lib-src/FileDialog/Makefile.am +++ b/lib-src/FileDialog/Makefile.am @@ -1,34 +1,28 @@ ACLOCAL_AMFLAGS = -I m4 -EXTRA_DIST = FileDialog.vcproj FileDialogPrivate.h.in - lib_LTLIBRARIES = libFileDialog.la libFileDialog_la_CPPFLAGS = $(WX_CXXFLAGS) libFileDialog_la_LIBADD = $(WX_LIBS) libFileDialog_la_SOURCES = FileDialog.cpp FileDialog.h -if GENERIC -libFileDialog_la_SOURCES += \ - generic/FileDialogPrivate.cpp \ - generic/FileDialogPrivate.h \ - $(NULL) -endif - if GTK libFileDialog_la_CPPFLAGS += $(GTK_CFLAGS) libFileDialog_la_LIBADD += $(GTK_LIBS) libFileDialog_la_SOURCES += \ gtk/FileDialogPrivate.cpp \ gtk/FileDialogPrivate.h \ - gtk/private.h \ $(NULL) endif if MAC -libFileDialog_la_SOURCES += mac/FileDialogPrivate.cpp mac/FileDialogPrivate.h +libFileDialog_la_SOURCES += mac/FileDialogPrivate.mm \ + mac/FileDialogPrivate.h \ + $(NULL) endif if WINDOWS -libFileDialog_la_SOURCES += win/FileDialogPrivate.cpp win/FileDialogPrivate.h +libFileDialog_la_SOURCES += win/FileDialogPrivate.cpp \ + win/FileDialogPrivate.h \ + $(NULL) endif diff --git a/lib-src/FileDialog/Makefile.in b/lib-src/FileDialog/Makefile.in index 62f169d51..ffc8ea300 100644 --- a/lib-src/FileDialog/Makefile.in +++ b/lib-src/FileDialog/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.14.1 from Makefile.am. +# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2013 Free Software Foundation, Inc. +# Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -15,7 +15,17 @@ @SET_MAKE@ VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -78,34 +88,17 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ -@GENERIC_TRUE@am__append_1 = \ -@GENERIC_TRUE@ generic/FileDialogPrivate.cpp \ -@GENERIC_TRUE@ generic/FileDialogPrivate.h \ -@GENERIC_TRUE@ $(NULL) - -@GTK_TRUE@am__append_2 = $(GTK_CFLAGS) -@GTK_TRUE@am__append_3 = $(GTK_LIBS) -@GTK_TRUE@am__append_4 = \ +@GTK_TRUE@am__append_1 = $(GTK_CFLAGS) +@GTK_TRUE@am__append_2 = $(GTK_LIBS) +@GTK_TRUE@am__append_3 = \ @GTK_TRUE@ gtk/FileDialogPrivate.cpp \ @GTK_TRUE@ gtk/FileDialogPrivate.h \ @GTK_TRUE@ gtk/private.h \ @GTK_TRUE@ $(NULL) -@MAC_TRUE@am__append_5 = mac/FileDialogPrivate.cpp mac/FileDialogPrivate.h -@WINDOWS_TRUE@am__append_6 = win/FileDialogPrivate.cpp win/FileDialogPrivate.h +@MAC_TRUE@am__append_4 = mac/FileDialogPrivate.cpp mac/FileDialogPrivate.h +@WINDOWS_TRUE@am__append_5 = win/FileDialogPrivate.cpp win/FileDialogPrivate.h subdir = . -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(top_srcdir)/configure $(am__configure_deps) \ - $(top_srcdir)/autotools/depcomp autotools/ar-lib \ - autotools/compile autotools/config.guess autotools/config.sub \ - autotools/depcomp autotools/install-sh autotools/missing \ - autotools/ltmain.sh $(top_srcdir)/autotools/ar-lib \ - $(top_srcdir)/autotools/compile \ - $(top_srcdir)/autotools/config.guess \ - $(top_srcdir)/autotools/config.sub \ - $(top_srcdir)/autotools/install-sh \ - $(top_srcdir)/autotools/ltmain.sh \ - $(top_srcdir)/autotools/missing ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ @@ -113,6 +106,8 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ + $(am__configure_deps) $(am__DIST_COMMON) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d @@ -152,21 +147,17 @@ am__DEPENDENCIES_1 = libFileDialog_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_2) am__libFileDialog_la_SOURCES_DIST = FileDialog.cpp FileDialog.h \ - generic/FileDialogPrivate.cpp generic/FileDialogPrivate.h \ gtk/FileDialogPrivate.cpp gtk/FileDialogPrivate.h \ gtk/private.h mac/FileDialogPrivate.cpp \ mac/FileDialogPrivate.h win/FileDialogPrivate.cpp \ win/FileDialogPrivate.h am__dirstamp = $(am__leading_dot)dirstamp -@GENERIC_TRUE@am__objects_1 = \ -@GENERIC_TRUE@ generic/libFileDialog_la-FileDialogPrivate.lo -@GTK_TRUE@am__objects_2 = gtk/libFileDialog_la-FileDialogPrivate.lo -@MAC_TRUE@am__objects_3 = mac/libFileDialog_la-FileDialogPrivate.lo -@WINDOWS_TRUE@am__objects_4 = \ +@GTK_TRUE@am__objects_1 = gtk/libFileDialog_la-FileDialogPrivate.lo +@MAC_TRUE@am__objects_2 = mac/libFileDialog_la-FileDialogPrivate.lo +@WINDOWS_TRUE@am__objects_3 = \ @WINDOWS_TRUE@ win/libFileDialog_la-FileDialogPrivate.lo am_libFileDialog_la_OBJECTS = libFileDialog_la-FileDialog.lo \ - $(am__objects_1) $(am__objects_2) $(am__objects_3) \ - $(am__objects_4) + $(am__objects_1) $(am__objects_2) $(am__objects_3) libFileDialog_la_OBJECTS = $(am_libFileDialog_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) @@ -252,6 +243,17 @@ ETAGS = etags CTAGS = ctags CSCOPE = cscope AM_RECURSIVE_TARGETS = cscope +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/autotools/ar-lib \ + $(top_srcdir)/autotools/compile \ + $(top_srcdir)/autotools/config.guess \ + $(top_srcdir)/autotools/config.sub \ + $(top_srcdir)/autotools/depcomp \ + $(top_srcdir)/autotools/install-sh \ + $(top_srcdir)/autotools/ltmain.sh \ + $(top_srcdir)/autotools/missing autotools/ar-lib \ + autotools/compile autotools/config.guess autotools/config.sub \ + autotools/depcomp autotools/install-sh autotools/ltmain.sh \ + autotools/missing DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) @@ -401,10 +403,10 @@ top_srcdir = @top_srcdir@ ACLOCAL_AMFLAGS = -I m4 EXTRA_DIST = FileDialog.vcproj FileDialogPrivate.h.in lib_LTLIBRARIES = libFileDialog.la -libFileDialog_la_CPPFLAGS = $(WX_CXXFLAGS) $(am__append_2) -libFileDialog_la_LIBADD = $(WX_LIBS) $(am__append_3) -libFileDialog_la_SOURCES = FileDialog.cpp FileDialog.h $(am__append_1) \ - $(am__append_4) $(am__append_5) $(am__append_6) +libFileDialog_la_CPPFLAGS = $(WX_CXXFLAGS) $(am__append_1) +libFileDialog_la_LIBADD = $(WX_LIBS) $(am__append_2) +libFileDialog_la_SOURCES = FileDialog.cpp FileDialog.h $(am__append_3) \ + $(am__append_4) $(am__append_5) all: all-am .SUFFIXES: @@ -424,7 +426,6 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign Makefile -.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ @@ -478,14 +479,6 @@ clean-libLTLIBRARIES: echo rm -f $${locs}; \ rm -f $${locs}; \ } -generic/$(am__dirstamp): - @$(MKDIR_P) generic - @: > generic/$(am__dirstamp) -generic/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) generic/$(DEPDIR) - @: > generic/$(DEPDIR)/$(am__dirstamp) -generic/libFileDialog_la-FileDialogPrivate.lo: \ - generic/$(am__dirstamp) generic/$(DEPDIR)/$(am__dirstamp) gtk/$(am__dirstamp): @$(MKDIR_P) gtk @: > gtk/$(am__dirstamp) @@ -516,8 +509,6 @@ libFileDialog.la: $(libFileDialog_la_OBJECTS) $(libFileDialog_la_DEPENDENCIES) $ mostlyclean-compile: -rm -f *.$(OBJEXT) - -rm -f generic/*.$(OBJEXT) - -rm -f generic/*.lo -rm -f gtk/*.$(OBJEXT) -rm -f gtk/*.lo -rm -f mac/*.$(OBJEXT) @@ -529,7 +520,6 @@ distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libFileDialog_la-FileDialog.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@generic/$(DEPDIR)/libFileDialog_la-FileDialogPrivate.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gtk/$(DEPDIR)/libFileDialog_la-FileDialogPrivate.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@mac/$(DEPDIR)/libFileDialog_la-FileDialogPrivate.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@win/$(DEPDIR)/libFileDialog_la-FileDialogPrivate.Plo@am__quote@ @@ -565,13 +555,6 @@ libFileDialog_la-FileDialog.lo: FileDialog.cpp @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libFileDialog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libFileDialog_la-FileDialog.lo `test -f 'FileDialog.cpp' || echo '$(srcdir)/'`FileDialog.cpp -generic/libFileDialog_la-FileDialogPrivate.lo: generic/FileDialogPrivate.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libFileDialog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT generic/libFileDialog_la-FileDialogPrivate.lo -MD -MP -MF generic/$(DEPDIR)/libFileDialog_la-FileDialogPrivate.Tpo -c -o generic/libFileDialog_la-FileDialogPrivate.lo `test -f 'generic/FileDialogPrivate.cpp' || echo '$(srcdir)/'`generic/FileDialogPrivate.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) generic/$(DEPDIR)/libFileDialog_la-FileDialogPrivate.Tpo generic/$(DEPDIR)/libFileDialog_la-FileDialogPrivate.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='generic/FileDialogPrivate.cpp' object='generic/libFileDialog_la-FileDialogPrivate.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libFileDialog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o generic/libFileDialog_la-FileDialogPrivate.lo `test -f 'generic/FileDialogPrivate.cpp' || echo '$(srcdir)/'`generic/FileDialogPrivate.cpp - gtk/libFileDialog_la-FileDialogPrivate.lo: gtk/FileDialogPrivate.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libFileDialog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gtk/libFileDialog_la-FileDialogPrivate.lo -MD -MP -MF gtk/$(DEPDIR)/libFileDialog_la-FileDialogPrivate.Tpo -c -o gtk/libFileDialog_la-FileDialogPrivate.lo `test -f 'gtk/FileDialogPrivate.cpp' || echo '$(srcdir)/'`gtk/FileDialogPrivate.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) gtk/$(DEPDIR)/libFileDialog_la-FileDialogPrivate.Tpo gtk/$(DEPDIR)/libFileDialog_la-FileDialogPrivate.Plo @@ -598,7 +581,6 @@ mostlyclean-libtool: clean-libtool: -rm -rf .libs _libs - -rm -rf generic/.libs generic/_libs -rm -rf gtk/.libs gtk/_libs -rm -rf mac/.libs mac/_libs -rm -rf win/.libs win/_libs @@ -720,15 +702,15 @@ dist-xz: distdir $(am__post_remove_distdir) dist-tarZ: distdir - @echo WARNING: "Support for shar distribution archives is" \ - "deprecated." >&2 + @echo WARNING: "Support for distribution archives compressed with" \ + "legacy program 'compress' is deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__post_remove_distdir) dist-shar: distdir - @echo WARNING: "Support for distribution archives compressed with" \ - "legacy program 'compress' is deprecated." >&2 + @echo WARNING: "Support for shar distribution archives is" \ + "deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz $(am__post_remove_distdir) @@ -764,17 +746,17 @@ distcheck: dist esac chmod -R a-w $(distdir) chmod u+w $(distdir) - mkdir $(distdir)/_build $(distdir)/_inst + mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ - && $(am__cd) $(distdir)/_build \ - && ../configure \ + && $(am__cd) $(distdir)/_build/sub \ + && ../../configure \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ - --srcdir=.. --prefix="$$dc_install_base" \ + --srcdir=../.. --prefix="$$dc_install_base" \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ @@ -860,8 +842,6 @@ clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -rm -f generic/$(DEPDIR)/$(am__dirstamp) - -rm -f generic/$(am__dirstamp) -rm -f gtk/$(DEPDIR)/$(am__dirstamp) -rm -f gtk/$(am__dirstamp) -rm -f mac/$(DEPDIR)/$(am__dirstamp) @@ -879,7 +859,7 @@ clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ distclean: distclean-am -rm -f $(am__CONFIG_DISTCLEAN_FILES) - -rm -rf ./$(DEPDIR) generic/$(DEPDIR) gtk/$(DEPDIR) mac/$(DEPDIR) win/$(DEPDIR) + -rm -rf ./$(DEPDIR) gtk/$(DEPDIR) mac/$(DEPDIR) win/$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-libtool distclean-tags @@ -927,7 +907,7 @@ installcheck-am: maintainer-clean: maintainer-clean-am -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache - -rm -rf ./$(DEPDIR) generic/$(DEPDIR) gtk/$(DEPDIR) mac/$(DEPDIR) win/$(DEPDIR) + -rm -rf ./$(DEPDIR) gtk/$(DEPDIR) mac/$(DEPDIR) win/$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic @@ -965,6 +945,8 @@ uninstall-am: uninstall-libLTLIBRARIES mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am uninstall-libLTLIBRARIES +.PRECIOUS: Makefile + # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff --git a/lib-src/FileDialog/configure b/lib-src/FileDialog/configure index f09a6a094..cdd8518f7 100755 --- a/lib-src/FileDialog/configure +++ b/lib-src/FileDialog/configure @@ -641,8 +641,6 @@ MAC_FALSE MAC_TRUE GTK_FALSE GTK_TRUE -GENERIC_FALSE -GENERIC_TRUE GTK_LIBS GTK_CFLAGS PKG_CONFIG_LIBDIR @@ -2324,7 +2322,7 @@ ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. -am__api_version='1.14' +am__api_version='1.15' # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or @@ -2496,8 +2494,8 @@ test "$program_suffix" != NONE && ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` -# expand $ac_aux_dir to an absolute path -am_aux_dir=`cd $ac_aux_dir && pwd` +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` if test x"${MISSING+set}" != xset; then case $am_aux_dir in @@ -2516,7 +2514,7 @@ else $as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} fi -if test x"${install_sh}" != xset; then +if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; @@ -2844,8 +2842,8 @@ MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} # mkdir_p='$(MKDIR_P)' -# We need awk for the "check" target. The system "awk" is bad on -# some platforms. +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. # Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AMTAR='$${TAR-tar}' @@ -2903,6 +2901,7 @@ END fi fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5 $as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; } # Check whether --enable-maintainer-mode was given. @@ -15486,8 +15485,10 @@ else fi -# Extract the first word of "wx-config", so it can be a program name with args. -set dummy wx-config; ac_word=$2 +for ac_prog in wx-config wx-config-3.0 +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_WX_CONFIG+:} false; then : @@ -15514,7 +15515,6 @@ done done IFS=$as_save_IFS - test -z "$ac_cv_path_WX_CONFIG" && ac_cv_path_WX_CONFIG="no" ;; esac fi @@ -15528,6 +15528,10 @@ $as_echo "no" >&6; } fi + test -n "$WX_CONFIG" && break +done +test -n "$WX_CONFIG" || WX_CONFIG="no" + if [ "$WX_CONFIG" = "no" ] ; then as_fn_error $? "\"Could not find wx-config: is wxWidgets installed? is wx-config in your path?\"" "$LINENO" 5 fi @@ -15740,7 +15744,7 @@ fi -IMPLEMENTATION="generic" +IMPLEMENTATION="" case "${host_os}" in darwin*) IMPLEMENTATION="mac" @@ -15763,14 +15767,6 @@ $as_echo "#define HAVE_GTK 1" >>confdefs.h ;; esac - if test "$IMPLEMENTATION" = "generic"; then - GENERIC_TRUE= - GENERIC_FALSE='#' -else - GENERIC_TRUE='#' - GENERIC_FALSE= -fi - if test "$IMPLEMENTATION" = "gtk"; then GTK_TRUE= GTK_FALSE='#' @@ -15981,10 +15977,6 @@ if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${GENERIC_TRUE}" && test -z "${GENERIC_FALSE}"; then - as_fn_error $? "conditional \"GENERIC\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi if test -z "${GTK_TRUE}" && test -z "${GTK_FALSE}"; then as_fn_error $? "conditional \"GTK\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 diff --git a/lib-src/FileDialog/configure.ac b/lib-src/FileDialog/configure.ac index d1019f568..1ab3ce732 100644 --- a/lib-src/FileDialog/configure.ac +++ b/lib-src/FileDialog/configure.ac @@ -57,7 +57,7 @@ AC_ARG_WITH(wx-config, wx_config="") dnl wxWidgets -- we assume that if wx-config is found, wxWidgets is successfully installed. -AC_PATH_PROG(WX_CONFIG, wx-config, no, $PATH:/usr/local/bin ) +AC_PATH_PROGS(WX_CONFIG, wx-config wx-config-3.0, no, $PATH:/usr/local/bin ) if [[ "$WX_CONFIG" = "no" ]] ; then AC_MSG_ERROR("Could not find wx-config: is wxWidgets installed? is wx-config in your path?") fi @@ -82,7 +82,7 @@ dnl OS-specific configuration AC_CANONICAL_HOST -IMPLEMENTATION="generic" +IMPLEMENTATION="" case "${host_os}" in darwin*) dnl Mac OS X configuration @@ -105,7 +105,6 @@ case "${host_os}" in ;; esac -AM_CONDITIONAL([GENERIC], test "$IMPLEMENTATION" = "generic") AM_CONDITIONAL([GTK], test "$IMPLEMENTATION" = "gtk") AM_CONDITIONAL([MAC], test "$IMPLEMENTATION" = "mac") AM_CONDITIONAL([WINDOWS], test "$IMPLEMENTATION" = "win") diff --git a/lib-src/FileDialog/generic/FileDialogPrivate.cpp b/lib-src/FileDialog/generic/FileDialogPrivate.cpp deleted file mode 100644 index 315a4cbed..000000000 --- a/lib-src/FileDialog/generic/FileDialogPrivate.cpp +++ /dev/null @@ -1,1608 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// Name: filedlgg.cpp -// Purpose: wxGenericFileDialog -// Author: Robert Roebling -// Modified by: Leland Lucius -// Created: 12/12/98 -// RCS-ID: $Id: FileDialogPrivate.cpp,v 1.4 2009-09-29 00:28:07 msmeyer Exp $ -// Copyright: (c) Robert Roebling -// Licence: wxWindows licence -// -// Modified for Audacity to support an additional button on Save dialogs -// -///////////////////////////////////////////////////////////////////////////// - -// For compilers that support precompilation, includes "wx.h". -#include "wx/wxprec.h" - -#ifdef __BORLANDC__ -#pragma hdrstop -#endif - -#include "../FileDialog.h" -#include "FileDialogPrivate.h" - -#include "wx/checkbox.h" -#include "wx/textctrl.h" -#include "wx/choice.h" -#include "wx/checkbox.h" -#include "wx/stattext.h" -#include "wx/debug.h" -#include "wx/log.h" -#include "wx/intl.h" -#include "wx/msgdlg.h" -#include "wx/sizer.h" -#include "wx/bmpbuttn.h" -#include "wx/tokenzr.h" -#include "wx/config.h" -#include "wx/imaglist.h" -#include "wx/dir.h" -#include "wx/artprov.h" -#include "wx/settings.h" -#include "wx/filefn.h" -#include "wx/file.h" // for wxS_IXXX constants only -#include "wx/filedlg.h" // wxFD_OPEN, wxFD_SAVE... -#include "wx/generic/dirctrlg.h" // for wxFileIconsTable - -#if wxUSE_TOOLTIPS -#include "wx/tooltip.h" -#endif - -#ifndef __WXWINCE__ -#include -#include -#endif - -#ifdef __UNIX__ -#include -#include -#ifndef __VMS -# include -#endif -#endif - -#ifdef __WINDOWS__ -#include "wx/msw/wrapwin.h" -#include "wx/msw/mslu.h" -#endif - -#ifdef __WATCOMC__ -#include -#endif - -#ifndef __WXWINCE__ -#include -#endif - -#if defined(__UNIX__) || defined(__DOS__) -#include -#endif - -// ---------------------------------------------------------------------------- -// private functions -// ---------------------------------------------------------------------------- - -static -int wxCALLBACK FileDataNameCompare( long data1, long data2, long data) -{ - FileData *fd1 = (FileData*)data1; - FileData *fd2 = (FileData*)data2; - if (fd1->GetFileName() == wxT("..")) return -data; - if (fd2->GetFileName() == wxT("..")) return data; - if (fd1->IsDir() && !fd2->IsDir()) return -data; - if (fd2->IsDir() && !fd1->IsDir()) return data; - return data*wxStrcmp( fd1->GetFileName(), fd2->GetFileName() ); -} - -static -int wxCALLBACK FileDataSizeCompare( long data1, long data2, long data) -{ - FileData *fd1 = (FileData*)data1; - FileData *fd2 = (FileData*)data2; - if (fd1->GetFileName() == wxT("..")) return -data; - if (fd2->GetFileName() == wxT("..")) return data; - if (fd1->IsDir() && !fd2->IsDir()) return -data; - if (fd2->IsDir() && !fd1->IsDir()) return data; - if (fd1->IsLink() && !fd2->IsLink()) return -data; - if (fd2->IsLink() && !fd1->IsLink()) return data; - return data*(fd1->GetSize() - fd2->GetSize()); -} - -static -int wxCALLBACK FileDataTypeCompare( long data1, long data2, long data) -{ - FileData *fd1 = (FileData*)data1; - FileData *fd2 = (FileData*)data2; - if (fd1->GetFileName() == wxT("..")) return -data; - if (fd2->GetFileName() == wxT("..")) return data; - if (fd1->IsDir() && !fd2->IsDir()) return -data; - if (fd2->IsDir() && !fd1->IsDir()) return data; - if (fd1->IsLink() && !fd2->IsLink()) return -data; - if (fd2->IsLink() && !fd1->IsLink()) return data; - return data*wxStrcmp( fd1->GetFileType(), fd2->GetFileType() ); -} - -static -int wxCALLBACK FileDataTimeCompare( long data1, long data2, long data) -{ - FileData *fd1 = (FileData*)data1; - FileData *fd2 = (FileData*)data2; - if (fd1->GetFileName() == wxT("..")) return -data; - if (fd2->GetFileName() == wxT("..")) return data; - if (fd1->IsDir() && !fd2->IsDir()) return -data; - if (fd2->IsDir() && !fd1->IsDir()) return data; - - return fd1->GetDateTime().IsLaterThan(fd2->GetDateTime()) ? int(data) : -int(data); -} - -#if defined(__WXWINCE__) -#define IsTopMostDir(dir) (dir == wxT("\\") || dir == wxT("/")) -#elif (defined(__DOS__) || defined(__WINDOWS__) || defined (__OS2__)) -#define IsTopMostDir(dir) (dir.empty()) -#else -#define IsTopMostDir(dir) (dir == wxT("/")) -#endif - -// defined in src/generic/dirctrlg.cpp -extern size_t wxGetAvailableDrives(wxArrayString &paths, wxArrayString &names, wxArrayInt &icon_ids); - -//----------------------------------------------------------------------------- -// FileData -//----------------------------------------------------------------------------- - -FileData::FileData( const wxString &filePath, const wxString &fileName, fileType type, int image_id ) -{ - Init(); - m_fileName = fileName; - m_filePath = filePath; - m_type = type; - m_image = image_id; - - ReadData(); -} - -void FileData::Init() -{ - m_size = 0; - m_type = FileData::is_file; - m_image = wxFileIconsTable::file; -} - -void FileData::Copy( const FileData& fileData ) -{ - m_fileName = fileData.GetFileName(); - m_filePath = fileData.GetFilePath(); - m_size = fileData.GetSize(); - m_dateTime = fileData.GetDateTime(); - m_permissions = fileData.GetPermissions(); - m_type = fileData.GetType(); - m_image = fileData.GetImageId(); -} - -void FileData::ReadData() -{ - if (IsDrive()) - { - m_size = 0; - return; - } - -#if defined(__DOS__) || (defined(__WINDOWS__) && !defined(__WXWINCE__)) || defined(__OS2__) - // c:\.. is a drive don't stat it - if ((m_fileName == wxT("..")) && (m_filePath.length() <= 5)) - { - m_type = is_drive; - m_size = 0; - return; - } -#endif // __DOS__ || __WINDOWS__ - -#ifdef __WXWINCE__ - - // WinCE - - DWORD fileAttribs = GetFileAttributes(m_filePath.fn_str()); - m_type |= (fileAttribs & FILE_ATTRIBUTE_DIRECTORY) != 0 ? is_dir : 0; - - wxString p, f, ext; - wxSplitPath(m_filePath, & p, & f, & ext); - if (wxStricmp(ext, wxT("exe")) == 0) - m_type |= is_exe; - - // Find out size - m_size = 0; - HANDLE fileHandle = CreateFile(m_filePath.fn_str(), - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); - - if (fileHandle != INVALID_HANDLE_VALUE) - { - m_size = GetFileSize(fileHandle, 0); - CloseHandle(fileHandle); - } - - m_dateTime = wxFileModificationTime(m_filePath); - -#else - - // OTHER PLATFORMS - - wxStructStat buff; - -#if defined(__UNIX__) && (!defined( __OS2__ ) && !defined(__VMS)) - lstat( m_filePath.fn_str(), &buff ); - m_type |= S_ISLNK( buff.st_mode ) != 0 ? is_link : 0; -#else // no lstat() - // only translate to file charset if we don't go by our - // wxStat implementation -#ifndef wxNEED_WX_UNISTD_H - wxStat( m_filePath.fn_str() , &buff ); -#else - wxStat( m_filePath, &buff ); -#endif -#endif - - m_type |= (buff.st_mode & S_IFDIR) != 0 ? is_dir : 0; - m_type |= (buff.st_mode & wxS_IXUSR) != 0 ? is_exe : 0; - m_size = (long)buff.st_size; - - m_dateTime = buff.st_mtime; -#endif - // __WXWINCE__ - -#if defined(__UNIX__) - m_permissions.Printf(wxT("%c%c%c%c%c%c%c%c%c"), - buff.st_mode & wxS_IRUSR ? wxT('r') : wxT('-'), - buff.st_mode & wxS_IWUSR ? wxT('w') : wxT('-'), - buff.st_mode & wxS_IXUSR ? wxT('x') : wxT('-'), - buff.st_mode & wxS_IRGRP ? wxT('r') : wxT('-'), - buff.st_mode & wxS_IWGRP ? wxT('w') : wxT('-'), - buff.st_mode & wxS_IXGRP ? wxT('x') : wxT('-'), - buff.st_mode & wxS_IROTH ? wxT('r') : wxT('-'), - buff.st_mode & wxS_IWOTH ? wxT('w') : wxT('-'), - buff.st_mode & wxS_IXOTH ? wxT('x') : wxT('-')); -#elif defined(__WIN32__) - DWORD attribs = GetFileAttributes(m_filePath.fn_str()); - if (attribs != (DWORD)-1) - { - m_permissions.Printf(wxT("%c%c%c%c"), - attribs & FILE_ATTRIBUTE_ARCHIVE ? wxT('A') : wxT(' '), - attribs & FILE_ATTRIBUTE_READONLY ? wxT('R') : wxT(' '), - attribs & FILE_ATTRIBUTE_HIDDEN ? wxT('H') : wxT(' '), - attribs & FILE_ATTRIBUTE_SYSTEM ? wxT('S') : wxT(' ')); - } -#endif - - // try to get a better icon - if (m_image == wxFileIconsTable::file) - { - if (m_fileName.Find(wxT('.'), true) != wxNOT_FOUND) - { - m_image = wxTheFileIconsTable->GetIconID( m_fileName.AfterLast(wxT('.'))); - } else if (IsExe()) - { - m_image = wxFileIconsTable::executable; - } - } -} - -wxString FileData::GetFileType() const -{ - if (IsDir()) - return _(""); - else if (IsLink()) - return _(""); - else if (IsDrive()) - return _(""); - else if (m_fileName.Find(wxT('.'), true) != wxNOT_FOUND) - return m_fileName.AfterLast(wxT('.')); - - return wxEmptyString; -} - -wxString FileData::GetModificationTime() const -{ - // want time as 01:02 so they line up nicely, no %r in WIN32 - return m_dateTime.FormatDate() + wxT(" ") + m_dateTime.Format(wxT("%I:%M:%S %p")); -} - -wxString FileData::GetHint() const -{ - wxString s = m_filePath; - s += wxT(" "); - - if (IsDir()) - s += _(""); - else if (IsLink()) - s += _(""); - else if (IsDrive()) - s += _(""); - else // plain file - s += wxString::Format( _("%ld bytes"), m_size ); - - s += wxT(' '); - - if ( !IsDrive() ) - { - s << GetModificationTime() - << wxT(" ") - << m_permissions; - } - - return s; -}; - -wxString FileData::GetEntry( fileListFieldType num ) const -{ - wxString s; - switch ( num ) - { - case FileList_Name: - s = m_fileName; - break; - - case FileList_Size: - if (!IsDir() && !IsLink() && !IsDrive()) - s.Printf(wxT("%ld"), m_size); - break; - - case FileList_Type: - s = GetFileType(); - break; - - case FileList_Time: - if (!IsDrive()) - s = GetModificationTime(); - break; - -#if defined(__UNIX__) || defined(__WIN32__) - case FileList_Perm: - s = m_permissions; - break; -#endif // defined(__UNIX__) || defined(__WIN32__) - - default: - wxFAIL_MSG( wxT("unexpected field in FileData::GetEntry()") ); - } - - return s; -} - -void FileData::SetNewName( const wxString &filePath, const wxString &fileName ) -{ - m_fileName = fileName; - m_filePath = filePath; -} - -void FileData::MakeItem( wxListItem &item ) -{ - item.m_text = m_fileName; - item.ClearAttributes(); - if (IsExe()) - item.SetTextColour(*wxRED); - if (IsDir()) - item.SetTextColour(*wxBLUE); - - item.m_image = m_image; - - if (IsLink()) - { - wxColour dg = wxTheColourDatabase->Find( wxT("MEDIUM GREY") ); - if ( dg.Ok() ) - item.SetTextColour(dg); - } - item.m_data = (long)this; -} - -//----------------------------------------------------------------------------- -// FileCtrl -//----------------------------------------------------------------------------- - -static bool ignoreChanges = false; - -IMPLEMENT_DYNAMIC_CLASS(FileCtrl,wxListCtrl) - -BEGIN_EVENT_TABLE(FileCtrl,wxListCtrl) -EVT_LIST_DELETE_ITEM(wxID_ANY, FileCtrl::OnListDeleteItem) -EVT_LIST_DELETE_ALL_ITEMS(wxID_ANY, FileCtrl::OnListDeleteAllItems) -EVT_LIST_END_LABEL_EDIT(wxID_ANY, FileCtrl::OnListEndLabelEdit) -EVT_LIST_COL_CLICK(wxID_ANY, FileCtrl::OnListColClick) -END_EVENT_TABLE() - - -FileCtrl::FileCtrl() -{ - m_showHidden = false; - m_sort_foward = 1; - m_sort_field = FileData::FileList_Name; -} - -FileCtrl::FileCtrl(wxWindow *win, - wxWindowID id, - const wxString& wild, - bool showHidden, - const wxPoint& pos, - const wxSize& size, - long style, - const wxValidator &validator, - const wxString &name) -: wxListCtrl(win, id, pos, size, style, validator, name), -m_wild(wild) -{ - wxImageList *imageList = wxTheFileIconsTable->GetSmallImageList(); - - SetImageList( imageList, wxIMAGE_LIST_SMALL ); - - m_showHidden = showHidden; - - m_sort_foward = 1; - m_sort_field = FileData::FileList_Name; - - m_dirName = wxT("*"); - - if (style & wxLC_REPORT) - ChangeToReportMode(); -} - -void FileCtrl::ChangeToListMode() -{ - ClearAll(); - SetSingleStyle( wxLC_LIST ); - UpdateFiles(); -} - -void FileCtrl::ChangeToReportMode() -{ - ClearAll(); - SetSingleStyle( wxLC_REPORT ); - - // do this since WIN32 does mm/dd/yy UNIX does mm/dd/yyyy - // don't hardcode since mm/dd is dd/mm elsewhere - int w, h; - wxDateTime dt(22, wxDateTime::Dec, 2002, 22, 22, 22); - wxString txt = dt.FormatDate() + wxT("22") + dt.Format(wxT("%I:%M:%S %p")); - GetTextExtent(txt, &w, &h); - - InsertColumn( 0, _("Name"), wxLIST_FORMAT_LEFT, w ); - InsertColumn( 1, _("Size"), wxLIST_FORMAT_LEFT, w/2 ); - InsertColumn( 2, _("Type"), wxLIST_FORMAT_LEFT, w/2 ); - InsertColumn( 3, _("Modified"), wxLIST_FORMAT_LEFT, w ); -#if defined(__UNIX__) - GetTextExtent(wxT("Permissions 2"), &w, &h); - InsertColumn( 4, _("Permissions"), wxLIST_FORMAT_LEFT, w ); -#elif defined(__WIN32__) - GetTextExtent(wxT("Attributes 2"), &w, &h); - InsertColumn( 4, _("Attributes"), wxLIST_FORMAT_LEFT, w ); -#endif - - UpdateFiles(); -} - -void FileCtrl::ChangeToSmallIconMode() -{ - ClearAll(); - SetSingleStyle( wxLC_SMALL_ICON ); - UpdateFiles(); -} - -void FileCtrl::ShowHidden( bool show ) -{ - m_showHidden = show; - UpdateFiles(); -} - -long FileCtrl::Add( FileData *fd, wxListItem &item ) -{ - long ret = -1; - item.m_mask = wxLIST_MASK_TEXT + wxLIST_MASK_DATA + wxLIST_MASK_IMAGE; - fd->MakeItem( item ); - long my_style = GetWindowStyleFlag(); - if (my_style & wxLC_REPORT) - { - ret = InsertItem( item ); - for (int i = 1; i < FileData::FileList_Max; i++) - SetItem( item.m_itemId, i, fd->GetEntry((FileData::fileListFieldType)i) ); - } - else if ((my_style & wxLC_LIST) || (my_style & wxLC_SMALL_ICON)) - { - ret = InsertItem( item ); - } - return ret; -} - -void FileCtrl::UpdateItem(const wxListItem &item) -{ - FileData *fd = (FileData*)GetItemData(item); - wxCHECK_RET(fd, wxT("invalid filedata")); - - fd->ReadData(); - - SetItemText(item, fd->GetFileName()); - SetItemImage(item, fd->GetImageId()); - - if (GetWindowStyleFlag() & wxLC_REPORT) - { - for (int i = 1; i < FileData::FileList_Max; i++) - SetItem( item.m_itemId, i, fd->GetEntry((FileData::fileListFieldType)i) ); - } -} - -void FileCtrl::UpdateFiles() -{ - // don't do anything before ShowModal() call which sets m_dirName - if ( m_dirName == wxT("*") ) - return; - - wxBusyCursor bcur; // this may take a while... - - DeleteAllItems(); - - wxListItem item; - item.m_itemId = 0; - item.m_col = 0; - -#if (defined(__WINDOWS__) || defined(__DOS__) || defined(__WXMAC__) || defined(__OS2__)) && !defined(__WXWINCE__) - if ( IsTopMostDir(m_dirName) ) - { - wxArrayString names, paths; - wxArrayInt icons; - size_t n, count = wxGetAvailableDrives(paths, names, icons); - - for (n=0; nGetFilePath() ) ); - new_name += wxFILE_SEP_PATH; - new_name += event.GetLabel(); - - wxLogNull log; - - if (wxFileExists(new_name)) - { - wxMessageDialog dialog(this, _("File name exists already."), _("Error"), wxOK | wxICON_ERROR ); - dialog.ShowModal(); - event.Veto(); - } - - if (wxRenameFile(fd->GetFilePath(),new_name)) - { - fd->SetNewName( new_name, event.GetLabel() ); - - ignoreChanges = true; - SetItemState( event.GetItem(), wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED ); - ignoreChanges = false; - - UpdateItem( event.GetItem() ); - EnsureVisible( event.GetItem() ); - } - else - { - wxMessageDialog dialog(this, _("Operation not permitted."), _("Error"), wxOK | wxICON_ERROR ); - dialog.ShowModal(); - event.Veto(); - } -} - -void FileCtrl::OnListColClick( wxListEvent &event ) -{ - int col = event.GetColumn(); - - switch (col) - { - case FileData::FileList_Name : - case FileData::FileList_Size : - case FileData::FileList_Type : - case FileData::FileList_Time : break; - default : return; - } - - if ((FileData::fileListFieldType)col == m_sort_field) - m_sort_foward = !m_sort_foward; - else - m_sort_field = (FileData::fileListFieldType)col; - - SortItems(m_sort_field, m_sort_foward); -} - -void FileCtrl::SortItems(FileData::fileListFieldType field, bool foward) -{ - m_sort_field = field; - m_sort_foward = foward; - long sort_dir = foward ? 1 : -1; - - switch (m_sort_field) - { - case FileData::FileList_Name : - { - wxListCtrl::SortItems((wxListCtrlCompare)FileDataNameCompare, sort_dir); - break; - } - case FileData::FileList_Size : - { - wxListCtrl::SortItems((wxListCtrlCompare)FileDataSizeCompare, sort_dir); - break; - } - case FileData::FileList_Type : - { - wxListCtrl::SortItems((wxListCtrlCompare)FileDataTypeCompare, sort_dir); - break; - } - case FileData::FileList_Time : - { - wxListCtrl::SortItems((wxListCtrlCompare)FileDataTimeCompare, sort_dir); - break; - } - default : break; - } -} - -FileCtrl::~FileCtrl() -{ - // Normally the data are freed via an EVT_LIST_DELETE_ALL_ITEMS event and - // FileCtrl::OnListDeleteAllItems. But if the event is generated after - // the destruction of the FileCtrl we need to free any data here: - FreeAllItemsData(); -} - -//----------------------------------------------------------------------------- -// FileDialog -//----------------------------------------------------------------------------- - -#define ID_FILEDIALOG 9000 -#define ID_LIST_MODE (ID_FILEDIALOG ) -#define ID_REPORT_MODE (ID_FILEDIALOG + 1) -#define ID_UP_DIR (ID_FILEDIALOG + 5) -#define ID_PARENT_DIR (ID_FILEDIALOG + 6) -#define ID_NEW_DIR (ID_FILEDIALOG + 7) -#define ID_CHOICE (ID_FILEDIALOG + 8) -#define ID_TEXT (ID_FILEDIALOG + 9) -#define ID_LIST_CTRL (ID_FILEDIALOG + 10) -#define ID_CHECK (ID_FILEDIALOG + 12) -#define ID_EXTRABUTTON (ID_FILEDIALOG + 13) - -IMPLEMENT_DYNAMIC_CLASS(FILEDIALOG, wxFileDialogBase) - -BEGIN_EVENT_TABLE(FILEDIALOG,wxDialog) -EVT_BUTTON(ID_LIST_MODE, FILEDIALOG::OnList) -EVT_BUTTON(ID_REPORT_MODE, FILEDIALOG::OnReport) -EVT_BUTTON(ID_UP_DIR, FILEDIALOG::OnUp) -EVT_BUTTON(ID_PARENT_DIR, FILEDIALOG::OnHome) -EVT_BUTTON(ID_NEW_DIR, FILEDIALOG::OnNew) -EVT_BUTTON(ID_EXTRABUTTON, FILEDIALOG::OnExtra) -EVT_BUTTON(wxID_OK, FILEDIALOG::OnListOk) -EVT_LIST_ITEM_SELECTED(ID_LIST_CTRL, FILEDIALOG::OnSelected) -EVT_LIST_ITEM_ACTIVATED(ID_LIST_CTRL, FILEDIALOG::OnActivated) -EVT_CHOICE(ID_CHOICE,FILEDIALOG::OnChoiceFilter) -EVT_TEXT_ENTER(ID_TEXT,FILEDIALOG::OnTextEnter) -EVT_TEXT(ID_TEXT,FILEDIALOG::OnTextChange) -EVT_CHECKBOX(ID_CHECK,FILEDIALOG::OnCheck) -END_EVENT_TABLE() - -long FILEDIALOG::ms_lastViewStyle = wxLC_LIST; -bool FILEDIALOG::ms_lastShowHidden = false; - -void FILEDIALOG::Init() -{ - m_bypassGenericImpl = false; - - m_choice = NULL; - m_text = NULL; - m_list = NULL; - m_check = NULL; - m_static = NULL; - m_upDirButton = NULL; - m_newDirButton = NULL; -} - -FILEDIALOG::FILEDIALOG(wxWindow *parent, - const wxString& message, - const wxString& defaultDir, - const wxString& defaultFile, - const wxString& wildCard, - long style, - const wxPoint& pos, - const wxSize& sz, - const wxString& name, - bool bypassGenericImpl ) : wxFileDialogBase() -{ - Init(); - Create( parent, message, defaultDir, defaultFile, wildCard, style, pos, sz, name,bypassGenericImpl ); -} - -bool FILEDIALOG::Create( wxWindow *parent, - const wxString& message, - const wxString& defaultDir, - const wxString& defaultFile, - const wxString& wildCard, - long style, - const wxPoint& pos, - const wxSize& sz, - const wxString& name, - bool bypassGenericImpl ) -{ - m_dialogStyle = style; - m_bypassGenericImpl = bypassGenericImpl; - - if (!wxFileDialogBase::Create(parent, message, defaultDir, defaultFile, - wildCard, style, pos, sz, name)) - { - return false; - } - - if (m_bypassGenericImpl) - return true; - - if (!wxDialog::Create( parent, wxID_ANY, message, pos, wxDefaultSize, - wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER )) - { - return false; - } - - ignoreChanges = true; - - if (wxConfig::Get(false)) - { - wxConfig::Get()->Read(wxT("/wxWindows/wxFileDialog/ViewStyle"), - &ms_lastViewStyle); - wxConfig::Get()->Read(wxT("/wxWindows/wxFileDialog/ShowHidden"), - &ms_lastShowHidden); - } - - if (m_dialogStyle == 0) - m_dialogStyle = wxFD_OPEN; - if ((m_dialogStyle & wxFD_MULTIPLE ) && !(m_dialogStyle & wxFD_OPEN)) - m_dialogStyle |= wxFD_OPEN; - - if ((m_dir.empty()) || (m_dir == wxT("."))) - { - m_dir = wxGetCwd(); - if (m_dir.empty()) - m_dir = wxFILE_SEP_PATH; - } - - size_t len = m_dir.Len(); - if ((len > 1) && (wxEndsWithPathSeparator(m_dir))) - m_dir.Remove( len-1, 1 ); - - m_path = m_dir; - m_path += wxFILE_SEP_PATH; - m_path += defaultFile; - m_filterExtension = wxEmptyString; - - // layout - - bool is_pda = (wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA); - - wxBoxSizer *mainsizer = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer *buttonsizer = new wxBoxSizer( wxHORIZONTAL ); - - wxBitmapButton *but; - - but = new wxBitmapButton(this, ID_LIST_MODE, - wxArtProvider::GetBitmap(wxART_LIST_VIEW, wxART_BUTTON)); -#if wxUSE_TOOLTIPS - but->SetToolTip( _("View files as a list view") ); -#endif - buttonsizer->Add( but, 0, wxALL, 5 ); - - but = new wxBitmapButton(this, ID_REPORT_MODE, - wxArtProvider::GetBitmap(wxART_REPORT_VIEW, wxART_BUTTON)); -#if wxUSE_TOOLTIPS - but->SetToolTip( _("View files as a detailed view") ); -#endif - buttonsizer->Add( but, 0, wxALL, 5 ); - - buttonsizer->Add( 30, 5, 1 ); - - m_upDirButton = new wxBitmapButton(this, ID_UP_DIR, - wxArtProvider::GetBitmap(wxART_GO_DIR_UP, wxART_BUTTON)); -#if wxUSE_TOOLTIPS - m_upDirButton->SetToolTip( _("Go to parent directory") ); -#endif - buttonsizer->Add( m_upDirButton, 0, wxALL, 5 ); - -#ifndef __DOS__ // VS: Home directory is meaningless in MS-DOS... - but = new wxBitmapButton(this, ID_PARENT_DIR, - wxArtProvider::GetBitmap(wxART_GO_HOME, wxART_BUTTON)); -#if wxUSE_TOOLTIPS - but->SetToolTip( _("Go to home directory") ); -#endif - buttonsizer->Add( but, 0, wxALL, 5); - - buttonsizer->Add( 20, 20 ); -#endif //!__DOS__ - - m_newDirButton = new wxBitmapButton(this, ID_NEW_DIR, - wxArtProvider::GetBitmap(wxART_NEW_DIR, wxART_BUTTON)); -#if wxUSE_TOOLTIPS - m_newDirButton->SetToolTip( _("Create new directory") ); -#endif - buttonsizer->Add( m_newDirButton, 0, wxALL, 5 ); - - if (is_pda) - mainsizer->Add( buttonsizer, 0, wxALL | wxEXPAND, 0 ); - else - mainsizer->Add( buttonsizer, 0, wxALL | wxEXPAND, 5 ); - - wxBoxSizer *staticsizer = new wxBoxSizer( wxHORIZONTAL ); - if (!is_pda) - staticsizer->Add( new wxStaticText( this, wxID_ANY, _("Current directory:") ), 0, wxRIGHT, 10 ); - m_static = new wxStaticText( this, wxID_ANY, m_dir ); - staticsizer->Add( m_static, 1 ); - mainsizer->Add( staticsizer, 0, wxEXPAND | wxLEFT|wxRIGHT|wxBOTTOM, 10 ); - - long style2 = ms_lastViewStyle; - if ( !(m_dialogStyle & wxFD_MULTIPLE) ) - style2 |= wxLC_SINGLE_SEL; - -#ifdef __WXWINCE__ - style2 |= wxSIMPLE_BORDER; -#else - style2 |= wxSUNKEN_BORDER; -#endif - - wxSize list_size(500,240); - if (is_pda) list_size = wxSize(50,80); - - m_list = new FileCtrl( this, ID_LIST_CTRL, - wxEmptyString, ms_lastShowHidden, - wxDefaultPosition, list_size, - style2); - - if (is_pda) - { - // PDAs have a different screen layout - mainsizer->Add( m_list, 1, wxEXPAND|wxSHRINK | wxLEFT|wxRIGHT, 5 ); - - wxBoxSizer *textsizer = new wxBoxSizer( wxHORIZONTAL ); - m_text = new wxTextCtrl( this, ID_TEXT, m_fileName, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER ); - textsizer->Add( m_text, 1, wxCENTER | wxALL, 5 ); - mainsizer->Add( textsizer, 0, wxEXPAND ); - - m_check = NULL; - m_choice = new wxChoice( this, ID_CHOICE ); - textsizer->Add( m_choice, 1, wxCENTER|wxALL, 5 ); - - buttonsizer = new wxBoxSizer( wxHORIZONTAL ); - buttonsizer->Add( new wxButton( this, wxID_OK ), 0, wxCENTER | wxALL, 5 ); - buttonsizer->Add( new wxButton( this, wxID_CANCEL ), 0, wxCENTER | wxALL, 5 ); - mainsizer->Add( buttonsizer, 0, wxALIGN_RIGHT ); - } - else - { - mainsizer->Add( m_list, 1, wxEXPAND | wxLEFT|wxRIGHT, 10 ); - - wxBoxSizer *textsizer = new wxBoxSizer( wxHORIZONTAL ); - m_text = new wxTextCtrl( this, ID_TEXT, m_fileName, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER ); - textsizer->Add( m_text, 1, wxCENTER | wxLEFT|wxRIGHT|wxTOP, 10 ); - textsizer->Add( new wxButton( this, wxID_OK ), 0, wxCENTER | wxLEFT|wxRIGHT|wxTOP, 10 ); - mainsizer->Add( textsizer, 0, wxEXPAND ); - - m_choicesizer = new wxBoxSizer( wxHORIZONTAL ); - m_choice = new wxChoice( this, ID_CHOICE ); - m_choicesizer->Add( m_choice, 1, wxCENTER|wxALL, 10 ); - m_check = new wxCheckBox( this, ID_CHECK, _("Show hidden files") ); - m_check->SetValue( ms_lastShowHidden ); - m_choicesizer->Add( m_check, 0, wxCENTER|wxALL, 10 ); - m_choicesizer->Add( new wxButton( this, wxID_CANCEL ), 0, wxCENTER | wxALL, 10 ); - mainsizer->Add( m_choicesizer, 0, wxEXPAND ); - } - - SetWildcard(wildCard); - - SetAutoLayout( true ); - SetSizer( mainsizer ); - - if (!is_pda) - { - mainsizer->Fit( this ); - mainsizer->SetSizeHints( this ); - - Centre( wxBOTH ); - } - - m_text->SetFocus(); - - ignoreChanges = false; - - return true; -} - -FILEDIALOG::~FILEDIALOG() -{ - ignoreChanges = true; - - if (!m_bypassGenericImpl) - { - if (wxConfig::Get(false)) - { - wxConfig::Get()->Write(wxT("/wxWindows/wxFileDialog/ViewStyle"), - ms_lastViewStyle); - wxConfig::Get()->Write(wxT("/wxWindows/wxFileDialog/ShowHidden"), - ms_lastShowHidden); - } - - const int count = m_choice->GetCount(); - for ( int i = 0; i < count; i++ ) - { - delete (wxString *)m_choice->GetClientData(i); - } - } -} - -int FILEDIALOG::ShowModal() -{ - if (!m_buttonlabel.IsEmpty()) - { - wxButton *btn = new wxButton( this, ID_EXTRABUTTON, m_buttonlabel ); - m_choicesizer->Insert( 1, btn, 0, wxCENTER | wxALL, 5 ); - } - - ignoreChanges = true; - - m_list->GoToDir(m_dir); - UpdateControls(); - m_text->SetValue(m_fileName); - - ignoreChanges = false; - - return wxDialog::ShowModal(); -} - -bool FILEDIALOG::Show( bool show ) -{ - // Called by ShowModal, so don't repeate the update -#ifndef __WIN32__ - if (show) - { - m_list->GoToDir(m_dir); - UpdateControls(); - m_text->SetValue(m_fileName); - } -#endif - - return wxDialog::Show( show ); -} - -void FILEDIALOG::DoSetFilterIndex(int filterindex) -{ - wxString *str = (wxString*) m_choice->GetClientData( filterindex ); - m_list->SetWild( *str ); - m_filterIndex = filterindex; - if ( str->Left(2) == wxT("*.") ) - { - m_filterExtension = str->Mid(1); - if (m_filterExtension == wxT(".*")) - m_filterExtension.clear(); - } - else - { - m_filterExtension.clear(); - } -} - -void FILEDIALOG::SetWildcard(const wxString& wildCard) -{ - wxFileDialogBase::SetWildcard(wildCard); - - wxArrayString wildDescriptions, wildFilters; - const size_t count = wxParseCommonDialogsFilter(m_wildCard, - wildDescriptions, - wildFilters); - wxCHECK_RET( count, wxT("wxFILEDIALOG: bad wildcard string") ); - - const size_t countOld = m_choice->GetCount(); - size_t n; - for ( n = 0; n < countOld; n++ ) - { - delete (wxString *)m_choice->GetClientData(n); - } - - for ( n = 0; n < count; n++ ) - { - m_choice->Append( wildDescriptions[n], new wxString( wildFilters[n] ) ); - } - - SetFilterIndex( 0 ); -} - -void FILEDIALOG::SetFilterIndex( int filterindex ) -{ - m_choice->SetSelection( filterindex ); - - DoSetFilterIndex(filterindex); -} - -void FILEDIALOG::OnChoiceFilter( wxCommandEvent &event ) -{ - DoSetFilterIndex((int)event.GetInt()); -} - -void FILEDIALOG::OnCheck( wxCommandEvent &event ) -{ - m_list->ShowHidden( (ms_lastShowHidden = event.GetInt() != 0) ); -} - -void FILEDIALOG::OnActivated( wxListEvent &event ) -{ - HandleAction( event.m_item.m_text ); -} - -void FILEDIALOG::OnTextEnter( wxCommandEvent &WXUNUSED(event) ) -{ - wxCommandEvent cevent(wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK); - cevent.SetEventObject( this ); - GetEventHandler()->ProcessEvent( cevent ); -} - -void FILEDIALOG::OnTextChange( wxCommandEvent &WXUNUSED(event) ) -{ - if (!ignoreChanges) - { - // Clear selections. Otherwise when the user types in a value they may - // not get the file whose name they typed. - if (m_list->GetSelectedItemCount() > 0) - { - long item = m_list->GetNextItem(-1, wxLIST_NEXT_ALL, - wxLIST_STATE_SELECTED); - while ( item != -1 ) - { - m_list->SetItemState(item,0, wxLIST_STATE_SELECTED); - item = m_list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); - } - } - } -} - -void FILEDIALOG::OnSelected( wxListEvent &event ) -{ - static bool inSelected = false; - - if (inSelected) - return; - - inSelected = true; - wxString filename( event.m_item.m_text ); - -#ifdef __WXWINCE__ - // No double-click on most WinCE devices, so do action immediately. - HandleAction( filename ); -#else - if (filename == wxT("..")) return; - - wxString dir = m_list->GetDir(); - if (!IsTopMostDir(dir)) - dir += wxFILE_SEP_PATH; - dir += filename; - if (wxDirExists(dir)) return; - - ignoreChanges = true; - m_text->SetValue( filename ); - ignoreChanges = false; -#endif - inSelected = false; -} - -void FILEDIALOG::HandleAction( const wxString &fn ) -{ - if (ignoreChanges) - return; - - wxString filename( fn ); - wxString dir = m_list->GetDir(); - if (filename.empty()) return; - if (filename == wxT(".")) return; - - // "some/place/" means they want to chdir not try to load "place" - bool want_dir = filename.Last() == wxFILE_SEP_PATH; - if (want_dir) - filename = filename.RemoveLast(); - - if (filename == wxT("..")) - { - ignoreChanges = true; - m_list->GoToParentDir(); - m_list->SetFocus(); - UpdateControls(); - ignoreChanges = false; - return; - } - -#ifdef __UNIX__ - if (filename == wxT("~")) - { - ignoreChanges = true; - m_list->GoToHomeDir(); - m_list->SetFocus(); - UpdateControls(); - ignoreChanges = false; - return; - } - - if (filename.BeforeFirst(wxT('/')) == wxT("~")) - { - filename = wxString(wxGetUserHome()) + filename.Remove(0, 1); - } -#endif // __UNIX__ - - if (!(m_dialogStyle & wxFD_SAVE)) - { - if ((filename.Find(wxT('*')) != wxNOT_FOUND) || - (filename.Find(wxT('?')) != wxNOT_FOUND)) - { - if (filename.Find(wxFILE_SEP_PATH) != wxNOT_FOUND) - { - wxMessageBox(_("Illegal file specification."), _("Error"), wxOK | wxICON_ERROR ); - return; - } - m_list->SetWild( filename ); - return; - } - } - - if (!IsTopMostDir(dir)) - dir += wxFILE_SEP_PATH; - if (!wxIsAbsolutePath(filename)) - { - dir += filename; - filename = dir; - } - - if (wxDirExists(filename)) - { - ignoreChanges = true; - m_list->GoToDir( filename ); - UpdateControls(); - ignoreChanges = false; - return; - } - - // they really wanted a dir, but it doesn't exist - if (want_dir) - { - wxMessageBox(_("Directory doesn't exist."), _("Error"), - wxOK | wxICON_ERROR ); - return; - } - - // append the default extension to the filename if it doesn't have any - // - // VZ: the logic of testing for !wxFileExists() only for the open file - // dialog is not entirely clear to me, why don't we allow saving to a - // file without extension as well? - if ( !(m_dialogStyle & wxFD_OPEN) || !wxFileExists(filename) ) - { - filename = AppendExtension(filename, m_filterExtension); - } - - // check that the file [doesn't] exist if necessary - if ( (m_dialogStyle & wxFD_SAVE) && - (m_dialogStyle & wxFD_OVERWRITE_PROMPT) && - wxFileExists( filename ) ) - { - wxString msg; - msg.Printf( _("File '%s' already exists, do you really want to overwrite it?"), filename.c_str() ); - - if (wxMessageBox(msg, _("Confirm"), wxYES_NO) != wxYES) - return; - } - else if ( (m_dialogStyle & wxFD_OPEN) && - (m_dialogStyle & wxFD_FILE_MUST_EXIST) && - !wxFileExists(filename) ) - { - wxMessageBox(_("Please choose an existing file."), _("Error"), - wxOK | wxICON_ERROR ); - } - - SetPath( filename ); - - // change to the directory where the user went if asked - if ( m_dialogStyle & wxFD_CHANGE_DIR ) - { - wxString cwd; - wxSplitPath(filename, &cwd, NULL, NULL); - - if ( cwd != wxGetCwd() ) - { - wxSetWorkingDirectory(cwd); - } - } - - if (Validate() && TransferDataFromWindow()) - EndModal(wxID_OK); -} - -void FILEDIALOG::OnListOk( wxCommandEvent &WXUNUSED(event) ) -{ - HandleAction( m_text->GetValue() ); -} - -void FILEDIALOG::OnList( wxCommandEvent &WXUNUSED(event) ) -{ - ignoreChanges = true; - m_list->ChangeToListMode(); - ms_lastViewStyle = wxLC_LIST; - m_list->SetFocus(); - ignoreChanges = false; -} - -void FILEDIALOG::OnReport( wxCommandEvent &WXUNUSED(event) ) -{ - ignoreChanges = true; - m_list->ChangeToReportMode(); - ms_lastViewStyle = wxLC_REPORT; - m_list->SetFocus(); - ignoreChanges = false; -} - -void FILEDIALOG::OnUp( wxCommandEvent &WXUNUSED(event) ) -{ - ignoreChanges = true; - m_list->GoToParentDir(); - m_list->SetFocus(); - UpdateControls(); - ignoreChanges = false; -} - -void FILEDIALOG::OnHome( wxCommandEvent &WXUNUSED(event) ) -{ - ignoreChanges = true; - m_list->GoToHomeDir(); - m_list->SetFocus(); - UpdateControls(); - ignoreChanges = false; -} - -void FILEDIALOG::OnNew( wxCommandEvent &WXUNUSED(event) ) -{ - ignoreChanges = true; - - m_list->MakeDir(); - - ignoreChanges = false; -} - -void FILEDIALOG::OnExtra( wxCommandEvent &WXUNUSED(event) ) -{ -#if !defined(GENERIC_FILEDIALOG) - ClickButton(m_choice->GetSelection()); -#endif -} - -void FILEDIALOG::SetPath( const wxString& path ) -{ - // not only set the full path but also update filename and dir - m_path = path; - -#ifdef __WXWINCE__ - if (m_path.empty()) - m_path = wxFILE_SEP_PATH; -#endif - - if ( !path.empty() ) - { - wxString ext; - wxSplitPath(path, &m_dir, &m_fileName, &ext); - if (!ext.empty()) - { - m_fileName += wxT("."); - m_fileName += ext; - } - } -} - -void FILEDIALOG::GetPaths( wxArrayString& paths ) const -{ - paths.Empty(); - if (m_list->GetSelectedItemCount() == 0) - { - paths.Add( GetPath() ); - return; - } - - paths.Alloc( m_list->GetSelectedItemCount() ); - - wxString dir = m_list->GetDir(); -#ifdef __UNIX__ - if (dir != wxT("/")) -#endif -#ifdef __WXWINCE__ - if (dir != wxT("/") && dir != wxT("\\")) -#endif - dir += wxFILE_SEP_PATH; - - wxListItem item; - item.m_mask = wxLIST_MASK_TEXT; - - item.m_itemId = m_list->GetNextItem( -1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED ); - while ( item.m_itemId != -1 ) - { - m_list->GetItem( item ); - paths.Add( dir + item.m_text ); - item.m_itemId = m_list->GetNextItem( item.m_itemId, - wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED ); - } -} - -void FILEDIALOG::GetFilenames(wxArrayString& files) const -{ - files.Empty(); - if (m_list->GetSelectedItemCount() == 0) - { - files.Add( GetFilename() ); - return; - } - files.Alloc( m_list->GetSelectedItemCount() ); - - wxListItem item; - item.m_mask = wxLIST_MASK_TEXT; - - item.m_itemId = m_list->GetNextItem( -1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED ); - while ( item.m_itemId != -1 ) - { - m_list->GetItem( item ); - files.Add( item.m_text ); - item.m_itemId = m_list->GetNextItem( item.m_itemId, - wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED ); - } -} - -void FILEDIALOG::UpdateControls() -{ - wxString dir = m_list->GetDir(); - m_static->SetLabel(dir); - - bool enable = !IsTopMostDir(dir); - m_upDirButton->Enable(enable); - -#if defined(__DOS__) || defined(__WINDOWS__) || defined(__OS2__) - m_newDirButton->Enable(enable); -#endif // defined(__DOS__) || defined(__WINDOWS__) || defined(__OS2__) -} diff --git a/lib-src/FileDialog/generic/FileDialogPrivate.h b/lib-src/FileDialog/generic/FileDialogPrivate.h deleted file mode 100644 index 2d7dd39d9..000000000 --- a/lib-src/FileDialog/generic/FileDialogPrivate.h +++ /dev/null @@ -1,304 +0,0 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: filedlgg.h -// Purpose: wxGenericFileDialog -// Author: Robert Roebling -// Modified by: Leland Lucius -// Created: 8/17/99 -// Copyright: (c) Robert Roebling -// RCS-ID: $Id: FileDialogPrivate.h,v 1.2 2008-05-24 02:57:39 llucius Exp $ -// Licence: wxWindows licence -// -// Modified for Audacity to support an additional button on Save dialogs -// -///////////////////////////////////////////////////////////////////////////// - -#ifndef _FILEDIALOGGENERICH_ -#define _FILEDIALOGGENERICH_ - -#include "wx/listctrl.h" -#include "wx/datetime.h" -#include "wx/sizer.h" - -//----------------------------------------------------------------------------- -// classes -//----------------------------------------------------------------------------- - -class wxBitmapButton; -class wxCheckBox; -class wxChoice; -class wxFileData; -class FileCtrl; -class wxListEvent; -class wxListItem; -class wxStaticText; -class wxTextCtrl; - -//------------------------------------------------------------------------- -// FileDialog -//------------------------------------------------------------------------- - -#if defined(GENERIC_FILEDIALOG) -#define FILEDIALOG GenericFileDialog -#else -#define FILEDIALOG FileDialog -#endif - - -class FILEDIALOG: public wxFileDialogBase -{ -public: - FILEDIALOG() : wxFileDialogBase() { Init(); } - - FILEDIALOG(wxWindow *parent, - const wxString& message = wxFileSelectorPromptStr, - const wxString& defaultDir = wxEmptyString, - const wxString& defaultFile = wxEmptyString, - const wxString& wildCard = wxFileSelectorDefaultWildcardStr, - long style = 0, - const wxPoint& pos = wxDefaultPosition, - const wxSize& sz = wxDefaultSize, - const wxString& name = wxFileDialogNameStr, - bool bypassGenericImpl = false ); - - bool Create( wxWindow *parent, - const wxString& message = wxFileSelectorPromptStr, - const wxString& defaultDir = wxEmptyString, - const wxString& defaultFile = wxEmptyString, - const wxString& wildCard = wxFileSelectorDefaultWildcardStr, - long style = 0, - const wxPoint& pos = wxDefaultPosition, - const wxSize& sz = wxDefaultSize, - const wxString& name = wxFileDialogNameStr, - bool bypassGenericImpl = false ); - - virtual ~FILEDIALOG(); - - virtual void SetMessage(const wxString& message) { SetTitle(message); } - virtual void SetPath(const wxString& path); - virtual void SetFilterIndex(int filterIndex); - virtual void SetWildcard(const wxString& wildCard); - - // for multiple file selection - virtual void GetPaths(wxArrayString& paths) const; - virtual void GetFilenames(wxArrayString& files) const; - -#if !defined(GENERIC_FILEDIALOG) - virtual void EnableButton(wxString label, fdCallback cb, void *cbdata); - virtual void ClickButton(int index); -#endif - - // implementation only from now on - // ------------------------------- - - virtual int ShowModal(); - virtual bool Show( bool show = true ); - - void OnSelected( wxListEvent &event ); - void OnActivated( wxListEvent &event ); - void OnList( wxCommandEvent &event ); - void OnReport( wxCommandEvent &event ); - void OnUp( wxCommandEvent &event ); - void OnHome( wxCommandEvent &event ); - void OnListOk( wxCommandEvent &event ); - void OnNew( wxCommandEvent &event ); - void OnChoiceFilter( wxCommandEvent &event ); - void OnTextEnter( wxCommandEvent &event ); - void OnTextChange( wxCommandEvent &event ); - void OnCheck( wxCommandEvent &event ); - void OnExtra( wxCommandEvent &event ); - - virtual void HandleAction( const wxString &fn ); - - virtual void UpdateControls(); - -private: - // Don't use this implementation at all :-) - bool m_bypassGenericImpl; - -protected: - // use the filter with the given index - void DoSetFilterIndex(int filterindex); - - wxString m_filterExtension; - wxChoice *m_choice; - wxTextCtrl *m_text; - FileCtrl *m_list; - wxCheckBox *m_check; - wxStaticText *m_static; - wxBitmapButton *m_upDirButton; - wxBitmapButton *m_newDirButton; - -private: - void Init(); - DECLARE_DYNAMIC_CLASS(FILEDIALOG) - DECLARE_EVENT_TABLE() - - // these variables are preserved between FileDialog calls - static long ms_lastViewStyle; // list or report? - static bool ms_lastShowHidden; // did we show hidden files? - - long m_dialogStyle; - wxBoxSizer *m_choicesizer; - wxString m_buttonlabel; - fdCallback m_callback; - void *m_cbdata; -}; - -//----------------------------------------------------------------------------- -// FileData - a class to hold the file info for the FileCtrl -//----------------------------------------------------------------------------- - -class FileData -{ -public: - enum fileType - { - is_file = 0x0000, - is_dir = 0x0001, - is_link = 0x0002, - is_exe = 0x0004, - is_drive = 0x0008 - }; - - FileData() { Init(); } - // Full copy constructor - FileData( const FileData& fileData ) { Copy(fileData); } - // Create a filedata from this information - FileData( const wxString &filePath, const wxString &fileName, - fileType type, int image_id ); - - // make a full copy of the other FileData - void Copy( const FileData &other ); - - // (re)read the extra data about the file from the system - void ReadData(); - - // get the name of the file, dir, drive - wxString GetFileName() const { return m_fileName; } - // get the full path + name of the file, dir, path - wxString GetFilePath() const { return m_filePath; } - // Set the path + name and name of the item - void SetNewName( const wxString &filePath, const wxString &fileName ); - - // Get the size of the file in bytes - long GetSize() const { return m_size; } - // Get the type of file, either file extension or , , - wxString GetFileType() const; - // get the last modification time - wxDateTime GetDateTime() const { return m_dateTime; } - // Get the time as a formatted string - wxString GetModificationTime() const; - // in UNIX get rwx for file, in MSW get attributes ARHS - wxString GetPermissions() const { return m_permissions; } - // Get the id of the image used in a wxImageList - int GetImageId() const { return m_image; } - - bool IsFile() const { return !IsDir() && !IsLink() && !IsDrive(); } - bool IsDir() const { return (m_type & is_dir ) != 0; } - bool IsLink() const { return (m_type & is_link ) != 0; } - bool IsExe() const { return (m_type & is_exe ) != 0; } - bool IsDrive() const { return (m_type & is_drive) != 0; } - - // Get/Set the type of file, file/dir/drive/link - int GetType() const { return m_type; } - - // the FileCtrl fields in report view - enum fileListFieldType - { - FileList_Name, - FileList_Size, - FileList_Type, - FileList_Time, -#if defined(__UNIX__) || defined(__WIN32__) - FileList_Perm, -#endif // defined(__UNIX__) || defined(__WIN32__) - FileList_Max - }; - - // Get the entry for report view of FileCtrl - wxString GetEntry( fileListFieldType num ) const; - - // Get a string representation of the file info - wxString GetHint() const; - // initialize a wxListItem attributes - void MakeItem( wxListItem &item ); - - // operators - FileData& operator = (const FileData& fd) { Copy(fd); return *this; } - -protected: - wxString m_fileName; - wxString m_filePath; - long m_size; - wxDateTime m_dateTime; - wxString m_permissions; - int m_type; - int m_image; - -private: - void Init(); -}; - -//----------------------------------------------------------------------------- -// FileCtrl -//----------------------------------------------------------------------------- - -class FileCtrl : public wxListCtrl -{ -public: - FileCtrl(); - FileCtrl( wxWindow *win, - wxWindowID id, - const wxString &wild, - bool showHidden, - const wxPoint &pos = wxDefaultPosition, - const wxSize &size = wxDefaultSize, - long style = wxLC_LIST, - const wxValidator &validator = wxDefaultValidator, - const wxString &name = wxT("filelist") ); - virtual ~FileCtrl(); - - virtual void ChangeToListMode(); - virtual void ChangeToReportMode(); - virtual void ChangeToSmallIconMode(); - virtual void ShowHidden( bool show = true ); - bool GetShowHidden() const { return m_showHidden; } - - virtual long Add( FileData *fd, wxListItem &item ); - virtual void UpdateItem(const wxListItem &item); - virtual void UpdateFiles(); - virtual void MakeDir(); - virtual void GoToParentDir(); - virtual void GoToHomeDir(); - virtual void GoToDir( const wxString &dir ); - virtual void SetWild( const wxString &wild ); - wxString GetWild() const { return m_wild; } - wxString GetDir() const { return m_dirName; } - - void OnListDeleteItem( wxListEvent &event ); - void OnListDeleteAllItems( wxListEvent &event ); - void OnListEndLabelEdit( wxListEvent &event ); - void OnListColClick( wxListEvent &event ); - - virtual void SortItems(FileData::fileListFieldType field, bool foward); - bool GetSortDirection() const { return m_sort_foward; } - FileData::fileListFieldType GetSortField() const { return m_sort_field; } - -protected: - void FreeItemData(wxListItem& item); - void FreeAllItemsData(); - - wxString m_dirName; - bool m_showHidden; - wxString m_wild; - - bool m_sort_foward; - FileData::fileListFieldType m_sort_field; - -private: - DECLARE_DYNAMIC_CLASS(FileCtrl) - DECLARE_EVENT_TABLE() -}; - -#endif // _FILEDIALOGGENERICH_ - diff --git a/lib-src/FileDialog/gtk/FileDialogPrivate.cpp b/lib-src/FileDialog/gtk/FileDialogPrivate.cpp index bb5ee5598..bc6608998 100644 --- a/lib-src/FileDialog/gtk/FileDialogPrivate.cpp +++ b/lib-src/FileDialog/gtk/FileDialogPrivate.cpp @@ -1,507 +1,611 @@ +// +// Copied from wxWidgets 3.0.2 and modified for Audacity +// ///////////////////////////////////////////////////////////////////////////// -// Name: gtk/filedlg.cpp -// Purpose: native implementation of FileDialog +// Name: src/gtk/filedlg.cpp +// Purpose: native implementation of wxFileDialog // Author: Robert Roebling, Zbigniew Zagorski, Mart Raudsepp -// Id: $Id: FileDialogPrivate.cpp,v 1.7 2009-05-25 11:10:00 llucius Exp $ // Copyright: (c) 1998 Robert Roebling, 2004 Zbigniew Zagorski, 2005 Mart Raudsepp // Licence: wxWindows licence -// -// Modified for Audacity to support an additional button on Save dialogs -// ///////////////////////////////////////////////////////////////////////////// -// For compilers that support precompilation, includes "wx.h". -#include "wx/wxprec.h" - -// Include setup.h to get wxUSE flags for compilers that do not support precompilation of headers -#include "wx/setup.h" - #include "../FileDialog.h" -#include -#include "private.h" - -#include // chdir - #include "wx/intl.h" -#include "wx/filename.h" // wxFilename -#include "wx/tokenzr.h" // wxStringTokenizer -#include "wx/filefn.h" // ::wxGetCwd -#include "wx/msgdlg.h" // wxMessageDialog -#include "wx/version.h" +#include "wx/msgdlg.h" -//----------------------------------------------------------------------------- -// Pull in generic file dialog -//----------------------------------------------------------------------------- +#include -#include "../generic/FileDialogPrivate.cpp" +#ifdef __UNIX__ +#include // chdir +#endif -//----------------------------------------------------------------------------- -// idle system -//----------------------------------------------------------------------------- +#include // wxFilename +#include // wxStringTokenizer +#include // ::wxGetCwd +#include +#include -extern void wxapp_install_idle_handler(); +#define wxGTK_CONV(s) (s).utf8_str() +#define wxGTK_CONV_FN(s) (s).fn_str() -//----------------------------------------------------------------------------- -// Open expanders on the dialog (really only the "Browser for other folders") -//----------------------------------------------------------------------------- +// ---------------------------------------------------------------------------- +// Convenience class for g_freeing a gchar* on scope exit automatically +// ---------------------------------------------------------------------------- -extern "C" { - static void SetExpanded(GtkWidget *widget, gpointer data) - { - if (GTK_IS_EXPANDER(widget)) - { - gtk_expander_set_expanded(GTK_EXPANDER(widget), true); - } - else if (GTK_IS_CONTAINER(widget)) - { - gtk_container_forall(GTK_CONTAINER(widget), SetExpanded, data); - } - - return; - } - - static void gtk_filedialog_show_callback(GtkWidget *widget, FileDialog *dialog) - { - gtk_container_forall(GTK_CONTAINER(widget), SetExpanded, NULL); - } -} +class wxGtkString +{ +public: + explicit wxGtkString(gchar *s) : m_str(s) { } + ~wxGtkString() { g_free(m_str); } + + const gchar *c_str() const { return m_str; } + + operator gchar *() const { return m_str; } + +private: + gchar *m_str; + + wxDECLARE_NO_COPY_CLASS(wxGtkString); +}; //----------------------------------------------------------------------------- // "clicked" for OK-button //----------------------------------------------------------------------------- extern "C" { - static void gtk_filedialog_ok_callback(GtkWidget *widget, FileDialog *dialog) - { - int style = dialog->GetWindowStyle(); - gchar* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(widget)); - - // gtk version numbers must be identical with the one in ctor (that calls set_do_overwrite_confirmation) +static void gtk_filedialog_ok_callback(GtkWidget *widget, FileDialog *dialog) +{ + int style = dialog->GetWindowStyle(); + wxGtkString filename(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(widget))); + + // gtk version numbers must be identical with the one in ctor (that calls set_do_overwrite_confirmation) +#ifndef __WXGTK3__ #if GTK_CHECK_VERSION(2,7,3) - if(gtk_check_version(2,7,3) != NULL) + if (gtk_check_version(2, 7, 3) != NULL) #endif - if ((style & wxFD_SAVE) && (style & wxFD_OVERWRITE_PROMPT)) - { + { + if ((style & wxFD_SAVE) && (style & wxFD_OVERWRITE_PROMPT)) + { if ( g_file_test(filename, G_FILE_TEST_EXISTS) ) { - wxString msg; - - msg.Printf( - _("File '%s' already exists, do you really want to overwrite it?"), - wxString(wxConvFileName->cMB2WX(filename)).c_str()); - - wxMessageDialog dlg(dialog, msg, _("Confirm"), + wxString msg; + + msg.Printf( + _("File '%s' already exists, do you really want to overwrite it?"), + wxString::FromUTF8(filename)); + + wxMessageDialog dlg(dialog, msg, _("Confirm"), wxYES_NO | wxICON_QUESTION); - if (dlg.ShowModal() != wxID_YES) - return; + if (dlg.ShowModal() != wxID_YES) + return; } - } - - // change to the directory where the user went if asked - if (style & wxFD_CHANGE_DIR) - { - // Use chdir to not care about filename encodings - gchar* folder = g_path_get_dirname(filename); - chdir(folder); - g_free(folder); - } - - g_free(filename); - - wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK); - event.SetEventObject(dialog); - dialog->GetEventHandler()->ProcessEvent(event); - } + } + } +#endif + + if (style & wxFD_FILE_MUST_EXIST) + { + if ( !g_file_test(filename, G_FILE_TEST_EXISTS) ) + { + wxMessageDialog dlg( dialog, _("Please choose an existing file."), + _("Error"), wxOK| wxICON_ERROR); + dlg.ShowModal(); + return; + } + } + + // change to the directory where the user went if asked + if (style & wxFD_CHANGE_DIR) + { + // Use chdir to not care about filename encodings + wxGtkString folder(g_path_get_dirname(filename)); + chdir(folder); + } + + wxCommandEvent event(wxEVT_BUTTON, wxID_OK); + event.SetEventObject(dialog); + dialog->HandleWindowEvent(event); +} } //----------------------------------------------------------------------------- // "clicked" for Cancel-button //----------------------------------------------------------------------------- -extern "C" { - static void gtk_filedialog_cancel_callback(GtkWidget *WXUNUSED(w), - FileDialog *dialog) - { - wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL); - event.SetEventObject(dialog); - dialog->GetEventHandler()->ProcessEvent(event); - } +extern "C" +{ + +static void +gtk_filedialog_cancel_callback(GtkWidget * WXUNUSED(w), FileDialog *dialog) +{ + wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL); + event.SetEventObject(dialog); + dialog->HandleWindowEvent(event); } -extern "C" { - static void gtk_filedialog_response_callback(GtkWidget *w, - gint response, - FileDialog *dialog) - { -#if !wxCHECK_VERSION(3, 0, 0) - wxapp_install_idle_handler(); -#endif - - if (response == GTK_RESPONSE_ACCEPT) - gtk_filedialog_ok_callback(w, dialog); - else if (response == GTK_RESPONSE_CANCEL) - gtk_filedialog_cancel_callback(w, dialog); - else // "delete" - { - gtk_filedialog_cancel_callback(w, dialog); - dialog->m_destroyed_by_delete = true; - } - } -} - -//----------------------------------------------------------------------------- -// "clicked" for extra-button -//----------------------------------------------------------------------------- - -extern "C" { - static void gtk_filedialog_extra_callback(GtkWidget *WXUNUSED(w), +static void gtk_filedialog_response_callback(GtkWidget *w, + gint response, FileDialog *dialog) - { - dialog->ClickButton(dialog->GetFilterIndex()); - } +{ + if (response == GTK_RESPONSE_ACCEPT) + gtk_filedialog_ok_callback(w, dialog); + else // GTK_RESPONSE_CANCEL or GTK_RESPONSE_NONE + gtk_filedialog_cancel_callback(w, dialog); +} + +static void gtk_filedialog_selchanged_callback(GtkFileChooser *chooser, + FileDialog *dialog) +{ + wxGtkString filename(gtk_file_chooser_get_preview_filename(chooser)); + + dialog->GTKSelectionChanged(wxString::FromUTF8(filename)); +} + +static void gtk_filedialog_update_preview_callback(GtkFileChooser *chooser, + gpointer user_data) +{ + GtkWidget *preview = GTK_WIDGET(user_data); + + wxGtkString filename(gtk_file_chooser_get_preview_filename(chooser)); + + if ( !filename ) + return; + + GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file_at_size(filename, 128, 128, NULL); + gboolean have_preview = pixbuf != NULL; + + gtk_image_set_from_pixbuf(GTK_IMAGE(preview), pixbuf); + if ( pixbuf ) + g_object_unref (pixbuf); + + gtk_file_chooser_set_preview_widget_active(chooser, have_preview); +} + +static void gtk_filedialog_folderchanged_callback(GtkFileChooser *chooser, + FileDialog *dialog) +{ + dialog->GTKFolderChanged(); +} + +static void gtk_filedialog_filterchanged_callback(GtkFileChooser *chooser, + GParamSpec *pspec, + FileDialog *dialog) +{ + dialog->GTKFilterChanged(); +} + +static GtkWidget* find_widget(GtkWidget* parent, const gchar* name, int depth) +{ + // printf("%*.*c%s\n", depth, depth, ' ', gtk_widget_get_name(parent)); + + GtkWidget *widget = NULL; + if (g_strcasecmp(gtk_widget_get_name(parent), name) == 0) + { + return parent; + } + + if (GTK_IS_BIN(parent)) + { + return find_widget(gtk_bin_get_child(GTK_BIN(parent)), name, depth + 1); + } + + if (GTK_IS_CONTAINER(parent)) + { + GList *list = gtk_container_get_children(GTK_CONTAINER(parent)); + for (GList *node = list; node; node = node->next) + { + widget = find_widget(GTK_WIDGET(node->data), name, depth + 1); + if (widget) + { + break; + } + } + g_list_free(list); + } + + return widget; +} + +} // extern "C" + +void FileDialog::AddChildGTK(wxWindowGTK* child) +{ + // allow dialog to be resized smaller horizontally + gtk_widget_set_size_request( + child->m_widget, child->GetMinWidth(), child->m_height); + +// In GTK 3+, adding our container as the extra widget can cause the +// the filter combo to grow to the same height as our container. This +// makes for a very odd looking filter combo. So, we manually add our +// container below the action bar. +#if GTK_CHECK_VERSION(3,0,0) + GtkWidget *actionbar = find_widget(m_widget, "GtkActionBar", 0); + if (actionbar) + { + GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + gtk_container_add(GTK_CONTAINER(vbox), child->m_widget); + gtk_box_set_child_packing(GTK_BOX(vbox), child->m_widget, TRUE, TRUE, 0, GTK_PACK_START); + gtk_widget_show(vbox); + + GtkWidget *abparent = gtk_widget_get_parent(actionbar); + gtk_container_add(GTK_CONTAINER(abparent), vbox); + gtk_box_set_child_packing(GTK_BOX(abparent), vbox, FALSE, FALSE, 0, GTK_PACK_END); + gtk_box_reorder_child(GTK_BOX(abparent), actionbar, -2); + } +#else + gtk_file_chooser_set_extra_widget( + GTK_FILE_CHOOSER(m_widget), child->m_widget); +#endif } //----------------------------------------------------------------------------- // FileDialog //----------------------------------------------------------------------------- -IMPLEMENT_DYNAMIC_CLASS(FileDialog, GenericFileDialog) +IMPLEMENT_DYNAMIC_CLASS(FileDialog,FileDialogBase) -BEGIN_EVENT_TABLE(FileDialog, GenericFileDialog) -EVT_BUTTON(wxID_OK, FileDialog::OnFakeOk) +BEGIN_EVENT_TABLE(FileDialog,FileDialogBase) + EVT_BUTTON(wxID_OK, FileDialog::OnFakeOk) + EVT_SIZE(FileDialog::OnSize) END_EVENT_TABLE() FileDialog::FileDialog(wxWindow *parent, const wxString& message, - const wxString& defaultDir, - const wxString& defaultFileName, - const wxString& wildCard, - long style, const wxPoint& pos) -: GenericFileDialog(parent, message, defaultDir, defaultFileName, - wildCard, style, pos, - wxDefaultSize, - wxFileDialogNameStr, - true ) + const wxString& defaultDir, + const wxString& defaultFileName, + const wxString& wildCard, + long style, const wxPoint& pos, + const wxSize& sz, + const wxString& name) + : FileDialogBase() { - wxASSERT_MSG( !( (style & wxFD_SAVE) && (style & wxFD_MULTIPLE) ), wxT("FileDialog - wxFD_MULTIPLE used on a save dialog" ) ); + Create(parent, message, defaultDir, defaultFileName, wildCard, style, pos, sz, name); +} + +bool FileDialog::Create(wxWindow *parent, const wxString& message, + const wxString& defaultDir, + const wxString& defaultFileName, + const wxString& wildCard, + long style, const wxPoint& pos, + const wxSize& sz, + const wxString& name) +{ + parent = GetParentForModalDialog(parent, style); + + if (!FileDialogBase::Create(parent, message, defaultDir, defaultFileName, + wildCard, style, pos, sz, name)) + { + return false; + } + + if (!PreCreation(parent, pos, wxDefaultSize) || + !CreateBase(parent, wxID_ANY, pos, wxDefaultSize, style, + wxDefaultValidator, wxT("filedialog"))) + { + wxFAIL_MSG( wxT("FileDialog creation failed") ); + return false; + } + + GtkFileChooserAction gtk_action; + GtkWindow* gtk_parent = NULL; + if (parent) + gtk_parent = GTK_WINDOW( gtk_widget_get_toplevel(parent->m_widget) ); + + const gchar* ok_btn_stock; + if ( style & wxFD_SAVE ) + { + gtk_action = GTK_FILE_CHOOSER_ACTION_SAVE; + ok_btn_stock = GTK_STOCK_SAVE; + } + else + { + gtk_action = GTK_FILE_CHOOSER_ACTION_OPEN; + ok_btn_stock = GTK_STOCK_OPEN; + } + + m_widget = gtk_file_chooser_dialog_new( + wxGTK_CONV(m_message), + gtk_parent, + gtk_action, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + ok_btn_stock, GTK_RESPONSE_ACCEPT, + NULL); + g_object_ref(m_widget); + GtkFileChooser* file_chooser = GTK_FILE_CHOOSER(m_widget); + + m_fc.SetWidget(file_chooser); + + gtk_dialog_set_default_response(GTK_DIALOG(m_widget), GTK_RESPONSE_ACCEPT); + + if ( style & wxFD_MULTIPLE ) + gtk_file_chooser_set_select_multiple(file_chooser, true); + + // local-only property could be set to false to allow non-local files to be + // loaded. In that case get/set_uri(s) should be used instead of + // get/set_filename(s) everywhere and the GtkFileChooserDialog should + // probably also be created with a backend, e.g. "gnome-vfs", "default", ... + // (gtk_file_chooser_dialog_new_with_backend). Currently local-only is kept + // as the default - true: + // gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(m_widget), true); + + g_signal_connect (m_widget, "response", + G_CALLBACK (gtk_filedialog_response_callback), this); + + g_signal_connect (m_widget, "selection-changed", + G_CALLBACK (gtk_filedialog_selchanged_callback), this); + + g_signal_connect (m_widget, "current-folder-changed", + G_CALLBACK (gtk_filedialog_folderchanged_callback), this); + + g_signal_connect (m_widget, "notify::filter", + G_CALLBACK (gtk_filedialog_filterchanged_callback), this); + + // deal with extensions/filters + SetWildcard(wildCard); + + wxString defaultFileNameWithExt = defaultFileName; + if ( !wildCard.empty() && !defaultFileName.empty() && + !wxFileName(defaultFileName).HasExt() ) + { + // append the default extension, if any, to the initial file name: GTK + // won't do it for us by default (unlike e.g. MSW) + const wxFileName fnWC(m_fc.GetCurrentWildCard()); + if ( fnWC.HasExt() ) + { + // Notice that we shouldn't append the extension if it's a wildcard + // because this is not useful: the user would need to change it to use + // some fixed extension anyhow. + const wxString& ext = fnWC.GetExt(); + if ( ext.find_first_of("?*") == wxString::npos ) + defaultFileNameWithExt << "." << ext; + } + } + + + // if defaultDir is specified it should contain the directory and + // defaultFileName should contain the default name of the file, however if + // directory is not given, defaultFileName contains both + wxFileName fn; + if ( defaultDir.empty() ) + fn.Assign(defaultFileNameWithExt); + else if ( !defaultFileNameWithExt.empty() ) + fn.Assign(defaultDir, defaultFileNameWithExt); + else + fn.AssignDir(defaultDir); + + // set the initial file name and/or directory + fn.MakeAbsolute(); // GTK+ needs absolute path + const wxString dir = fn.GetPath(); + if ( !dir.empty() ) + { + gtk_file_chooser_set_current_folder(file_chooser, wxGTK_CONV_FN(dir)); + } + + const wxString fname = fn.GetFullName(); + if ( style & wxFD_SAVE ) + { + if ( !fname.empty() ) + { + gtk_file_chooser_set_current_name(file_chooser, wxGTK_CONV_FN(fname)); + } -#if !wxCHECK_VERSION(3, 0, 0) - m_needParent = false; -#endif - m_destroyed_by_delete = false; - - if (!PreCreation(parent, pos, wxDefaultSize) || - !CreateBase(parent, wxID_ANY, pos, wxDefaultSize, style, - wxDefaultValidator, wxT("filedialog"))) - { - wxFAIL_MSG( wxT("FileDialog creation failed") ); - return; - } - - GtkFileChooserAction gtk_action; - GtkWindow* gtk_parent = NULL; - if (parent) - gtk_parent = GTK_WINDOW( gtk_widget_get_toplevel(parent->m_widget) ); - - const gchar* ok_btn_stock; - if ( style & wxFD_SAVE ) - { - gtk_action = GTK_FILE_CHOOSER_ACTION_SAVE; - ok_btn_stock = GTK_STOCK_SAVE; - } - else - { - gtk_action = GTK_FILE_CHOOSER_ACTION_OPEN; - ok_btn_stock = GTK_STOCK_OPEN; - } - - m_widget = gtk_file_chooser_dialog_new( - wxGTK_CONV(m_message), - gtk_parent, - gtk_action, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - ok_btn_stock, GTK_RESPONSE_ACCEPT, - NULL); - - // Allow pressing "Enter" key for default action - gtk_dialog_set_default_response(GTK_DIALOG(m_widget), GTK_RESPONSE_ACCEPT); - - if ( style & wxFD_MULTIPLE ) - gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(m_widget), true); - - // local-only property could be set to false to allow non-local files to be loaded. - // In that case get/set_uri(s) should be used instead of get/set_filename(s) everywhere - // and the GtkFileChooserDialog should probably also be created with a backend, - // e.g "gnome-vfs", "default", ... (gtk_file_chooser_dialog_new_with_backend). - // Currently local-only is kept as the default - true: - // gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(m_widget), true); - - g_signal_connect(G_OBJECT(m_widget), "response", - G_CALLBACK(gtk_filedialog_response_callback), (gpointer)this); - g_signal_connect(G_OBJECT(m_widget), "show", - G_CALLBACK(gtk_filedialog_show_callback), (gpointer)this); - - SetWildcard(wildCard); - - if ( style & wxFD_SAVE ) - { - if ( !defaultDir.empty() ) - gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(m_widget), - wxConvFileName->cWX2MB(defaultDir)); - - gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(m_widget), - wxConvFileName->cWX2MB(defaultFileName)); - #if GTK_CHECK_VERSION(2,7,3) - if (!gtk_check_version(2,7,3)) - gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(m_widget), FALSE); + if ((style & wxFD_OVERWRITE_PROMPT) +#ifndef __WXGTK3__ + && gtk_check_version(2,7,3) == NULL #endif - } - else - { - if ( !defaultFileName.empty() ) - { - wxString dir; - if ( defaultDir.empty() ) - dir = ::wxGetCwd(); - else - dir = defaultDir; - - gtk_file_chooser_set_filename( - GTK_FILE_CHOOSER(m_widget), - wxConvFileName->cWX2MB( wxFileName(dir, defaultFileName).GetFullPath() ) ); - } - else if ( !defaultDir.empty() ) - gtk_file_chooser_set_current_folder( GTK_FILE_CHOOSER(m_widget), - wxConvFileName->cWX2MB(defaultDir) ); - } + ) + { + gtk_file_chooser_set_do_overwrite_confirmation(file_chooser, true); + } +#endif + } + else // wxFD_OPEN + { + if ( !fname.empty() ) + { + gtk_file_chooser_set_filename(file_chooser, + wxGTK_CONV_FN(fn.GetFullPath())); + } + } + + if ( style & wxFD_PREVIEW ) + { + GtkWidget *previewImage = gtk_image_new(); + + gtk_file_chooser_set_preview_widget(file_chooser, previewImage); + g_signal_connect(m_widget, "update-preview", + G_CALLBACK(gtk_filedialog_update_preview_callback), + previewImage); + } + + return true; } FileDialog::~FileDialog() { - if (m_destroyed_by_delete) - m_widget = NULL; + if (m_extraControl) + { + // get chooser to drop its reference right now, allowing wxWindow dtor + // to verify that ref count drops to zero + gtk_file_chooser_set_extra_widget( + GTK_FILE_CHOOSER(m_widget), NULL); + } } -void FileDialog::OnFakeOk( wxCommandEvent &event ) +void FileDialog::OnFakeOk(wxCommandEvent& WXUNUSED(event)) { - if (Validate() && TransferDataFromWindow()) - EndModal(wxID_OK); + // Update the current directory from here, accessing it later may not work + // due to the strange way GtkFileChooser works. + wxGtkString + str(gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(m_widget))); + m_dir = wxString::FromUTF8(str); + + EndDialog(wxID_OK); } int FileDialog::ShowModal() { - if ( !m_buttonlabel.IsEmpty() ) - { - GtkWidget *widget; - wxString label = m_buttonlabel; - - label.Replace(wxT("&"), wxT("_")); + WX_HOOK_MODAL_DIALOG(); - widget = gtk_button_new_with_mnemonic(wxGTK_CONV(label)); - gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER(m_widget), widget); - g_signal_connect(G_OBJECT(widget), "clicked", - G_CALLBACK(gtk_filedialog_extra_callback), (gpointer)this); - } - - return wxDialog::ShowModal(); + // Create the root window + wxBoxSizer *verticalSizer = new wxBoxSizer(wxVERTICAL); + wxPanel *root = new wxPanel(this, wxID_ANY); + + if (HasUserPaneCreator()) + { + wxPanel *userpane = new wxPanel(root, wxID_ANY); + CreateUserPane(userpane); + + wxBoxSizer *horizontalSizer = new wxBoxSizer(wxHORIZONTAL); + horizontalSizer->Add(userpane, 1, wxEXPAND, 0); + verticalSizer->Add(horizontalSizer, 1, wxEXPAND|wxALL, 0); + } + + root->SetSizer(verticalSizer); + root->Layout(); + verticalSizer->SetSizeHints(root); + + return wxDialog::ShowModal(); } -bool FileDialog::Show( bool show ) +void FileDialog::DoSetSize(int WXUNUSED(x), int WXUNUSED(y), + int WXUNUSED(width), int WXUNUSED(height), + int WXUNUSED(sizeFlags)) { - return wxDialog::Show( show ); } -void FileDialog::DoSetSize(int x, int y, int width, int height, int sizeFlags ) +void FileDialog::OnSize(wxSizeEvent&) { - if (!m_wxwindow) - return; - else - GenericFileDialog::DoSetSize( x, y, width, height, sizeFlags ); + // avoid calling DoLayout(), which will set the (wrong) size of + // m_extraControl, its size is managed by GtkFileChooser } wxString FileDialog::GetPath() const { - char *f = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(m_widget)); - wxFileName path(wxConvFileName->cMB2WX(f)); - g_free(f); - - if (!path.HasExt()) - { - if (!(m_dialogStyle & FD_NO_ADD_EXTENSION)) - { - int filterIndex = GetFilterIndex(); - if (filterIndex != -1) - { - wxStringTokenizer tokenizer(m_patterns[filterIndex], wxT(";")); - if (tokenizer.HasMoreTokens()) - { - wxString extension = tokenizer.GetNextToken().AfterFirst(wxT('.')); - if (extension.Right(2) == wxT("*")) - { - extension = wxEmptyString; - } - path.SetExt(extension); - } - } - } - } - - return path.GetFullPath(); + return m_fc.GetPath(); } void FileDialog::GetFilenames(wxArrayString& files) const { - GetPaths(files); - for (size_t n = 0; n < files.GetCount(); ++n ) - { - wxFileName file(files[n]); - files[n] = file.GetFullName(); - } + m_fc.GetFilenames( files ); } void FileDialog::GetPaths(wxArrayString& paths) const { - paths.Empty(); - if (gtk_file_chooser_get_select_multiple(GTK_FILE_CHOOSER(m_widget))) - { - GSList *gpathsi = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(m_widget)); - GSList *gpaths = gpathsi; - while (gpathsi) - { - wxString file(wxConvFileName->cMB2WX((gchar*) gpathsi->data)); - paths.Add(file); - g_free(gpathsi->data); - gpathsi = gpathsi->next; - } - - g_slist_free(gpaths); - } - else - paths.Add(GetPath()); + m_fc.GetPaths( paths ); } void FileDialog::SetMessage(const wxString& message) { - m_message = message; - SetTitle(message); + m_message = message; + SetTitle(message); } void FileDialog::SetPath(const wxString& path) { - if (path.empty()) return; - - gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(m_widget), wxConvFileName->cWX2MB(path)); + FileDialogBase::SetPath(path); + + // Don't do anything if no path is specified, in particular don't set the + // path to m_dir below as this would result in opening the dialog in the + // parent directory of this one instead of m_dir itself. + if ( path.empty() ) + return; + + // we need an absolute path for GTK native chooser so ensure that we have + // it: use the initial directory if it was set or just CWD otherwise (this + // is the default behaviour if m_dir is empty) + wxFileName fn(path); + fn.MakeAbsolute(m_dir); + m_fc.SetPath(fn.GetFullPath()); } void FileDialog::SetDirectory(const wxString& dir) { - if (wxDirExists(dir)) - { - gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(m_widget), wxConvFileName->cWX2MB(dir)); - } -} + FileDialogBase::SetDirectory(dir); -wxString FileDialog::GetDirectory() const -{ - return wxConvFileName->cMB2WX(gtk_file_chooser_get_current_folder( GTK_FILE_CHOOSER(m_widget) ) ); + m_fc.SetDirectory(dir); } void FileDialog::SetFilename(const wxString& name) { - if (GetWindowStyle() & wxFD_SAVE) - gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(m_widget), wxConvFileName->cWX2MB(name)); - else - SetPath(wxFileName(GetDirectory(), name).GetFullPath()); + FileDialogBase::SetFilename(name); + + if (HasFdFlag(wxFD_SAVE)) + { + gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(m_widget), wxGTK_CONV(name)); + } + + else + { + wxString path( GetDirectory() ); + if (path.empty()) + { + // SetPath() fires an assert if fed other than filepaths + return; + } + SetPath(wxFileName(path, name).GetFullPath()); + } } wxString FileDialog::GetFilename() const { - wxFileName name = GetPath(); - return name.GetFullName(); + wxString currentFilename( m_fc.GetFilename() ); + if (currentFilename.empty()) + { + // m_fc.GetFilename() will return empty until the dialog has been shown + // in which case use any previously provided value + currentFilename = m_fileName; + } + return currentFilename; } void FileDialog::SetWildcard(const wxString& wildCard) { - // parse filters - wxArrayString wildDescriptions, wildFilters; - if (!wxParseCommonDialogsFilter(wildCard, wildDescriptions, wildFilters)) - { - wxFAIL_MSG( wxT("FileDialog::SetWildCard - bad wildcard string") ); - } - else - { - // Parsing went fine. Set m_wildCard to be returned by FileDialogBase::GetWildcard - m_wildCard = wildCard; - - GtkFileChooser* chooser = GTK_FILE_CHOOSER(m_widget); - - // empty current filter list: - GSList* ifilters = gtk_file_chooser_list_filters(chooser); - GSList* filters = ifilters; - - while (ifilters) - { - gtk_file_chooser_remove_filter(chooser,GTK_FILE_FILTER(ifilters->data)); - ifilters = ifilters->next; - } - g_slist_free(filters); - - // add parsed to GtkChooser - for (size_t n = 0; n < wildFilters.GetCount(); ++n) - { - GtkFileFilter* filter = gtk_file_filter_new(); - gtk_file_filter_set_name(filter, wxGTK_CONV(wildDescriptions[n])); - - m_patterns.Add(wildFilters[n]); - wxStringTokenizer exttok(wildFilters[n], wxT(";")); - while (exttok.HasMoreTokens()) - { - wxString token = exttok.GetNextToken(); - gtk_file_filter_add_pattern(filter, wxGTK_CONV(token)); - } - - gtk_file_chooser_add_filter(chooser, filter); - } - - // Reset the filter index - SetFilterIndex(0); - } + FileDialogBase::SetWildcard(wildCard); + m_fc.SetWildcard( GetWildcard() ); } void FileDialog::SetFilterIndex(int filterIndex) { - gpointer filter; - GtkFileChooser *chooser = GTK_FILE_CHOOSER(m_widget); - GSList *filters = gtk_file_chooser_list_filters(chooser); - - filter = g_slist_nth_data(filters, filterIndex); - - if (filter != NULL) - { - gtk_file_chooser_set_filter(chooser, GTK_FILE_FILTER(filter)); - } - else - { - wxFAIL_MSG( wxT("FileDialog::SetFilterIndex - bad filter index") ); - } - - g_slist_free(filters); + m_fc.SetFilterIndex( filterIndex); } int FileDialog::GetFilterIndex() const { - GtkFileChooser *chooser = GTK_FILE_CHOOSER(m_widget); - GtkFileFilter *filter = gtk_file_chooser_get_filter(chooser); - GSList *filters = gtk_file_chooser_list_filters(chooser); - gint index = g_slist_index(filters, filter); - g_slist_free(filters); - - if (index == -1) - { - wxFAIL_MSG( wxT("FileDialog::GetFilterIndex - bad filter index returned by gtk+") ); - return 0; - } - else - return index; + return m_fc.GetFilterIndex(); } + +void FileDialog::GTKSelectionChanged(const wxString& filename) +{ + m_currentlySelectedFilename = filename; + + wxFileCtrlEvent event(wxEVT_FILECTRL_SELECTIONCHANGED, this, GetId()); + + wxArrayString filenames; + GetFilenames(filenames); + + event.SetDirectory(GetDirectory()); + event.SetFiles(filenames); + + GetEventHandler()->ProcessEvent(event); +} + +void FileDialog::GTKFolderChanged() +{ + wxFileCtrlEvent event(wxEVT_FILECTRL_FOLDERCHANGED, this, GetId()); + + event.SetDirectory(GetDirectory()); + + GetEventHandler()->ProcessEvent(event); +} + +void FileDialog::GTKFilterChanged() +{ + wxFileCtrlEvent event(wxEVT_FILECTRL_FILTERCHANGED, this, GetId()); + + event.SetFilterIndex(GetFilterIndex()); + + GetEventHandler()->ProcessEvent(event); +} + diff --git a/lib-src/FileDialog/gtk/FileDialogPrivate.h b/lib-src/FileDialog/gtk/FileDialogPrivate.h index 9f033450f..67eb70854 100644 --- a/lib-src/FileDialog/gtk/FileDialogPrivate.h +++ b/lib-src/FileDialog/gtk/FileDialogPrivate.h @@ -1,81 +1,89 @@ +// +// Copied from wxWidgets 3.0.2 and modified for Audacity +// ///////////////////////////////////////////////////////////////////////////// -// Name: filedlg.h +// Name: wx/gtk/filedlg.h // Purpose: // Author: Robert Roebling -// Id: $Id: FileDialogPrivate.h,v 1.2 2008-05-24 02:57:39 llucius Exp $ // Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence -// -// Modified for Audacity to support an additional button on Save dialogs -// ///////////////////////////////////////////////////////////////////////////// +#ifndef _GTK_FILEDIALOGPRIVATE_H_ +#define _GTK_FILEDIALOGPRIVATE_H_ -#ifndef __FILEDIALOGGTKH__ -#define __FILEDIALOGGTKH__ - -#include "wx/defs.h" - -#define GENERIC_FILEDIALOG 1 -#include "../generic/FileDialogPrivate.h" +#include // for wxGtkFileChooser +#include //------------------------------------------------------------------------- // FileDialog //------------------------------------------------------------------------- -class FileDialog: public GenericFileDialog +class WXDLLIMPEXP_CORE FileDialog: public FileDialogBase { public: - FileDialog() { } - - FileDialog(wxWindow *parent, - const wxString& message = wxFileSelectorPromptStr, - const wxString& defaultDir = wxEmptyString, - const wxString& defaultFile = wxEmptyString, - const wxString& wildCard = wxFileSelectorDefaultWildcardStr, - long style = 0, - const wxPoint& pos = wxDefaultPosition); - - virtual ~FileDialog(); - - virtual wxString GetPath() const; - virtual void GetPaths(wxArrayString& paths) const; - virtual wxString GetDirectory() const; - virtual wxString GetFilename() const; - virtual void GetFilenames(wxArrayString& files) const; - virtual int GetFilterIndex() const; - - virtual void SetMessage(const wxString& message); - virtual void SetPath(const wxString& path); - virtual void SetDirectory(const wxString& dir); - virtual void SetFilename(const wxString& name); - virtual void SetWildcard(const wxString& wildCard); - virtual void SetFilterIndex(int filterIndex); - - virtual int ShowModal(); - virtual bool Show( bool show = true ); - - //private: - bool m_destroyed_by_delete; - - // override this from wxTLW since the native - // form doesn't have any m_wxwindow - virtual void DoSetSize(int x, int y, - int width, int height, - int sizeFlags = wxSIZE_AUTO); - - virtual void EnableButton(wxString label, fdCallback cb, void *cbdata); - virtual void ClickButton(int index); - + FileDialog() { } + + FileDialog(wxWindow *parent, + const wxString& message = wxFileSelectorPromptStr, + const wxString& defaultDir = wxEmptyString, + const wxString& defaultFile = wxEmptyString, + const wxString& wildCard = wxFileSelectorDefaultWildcardStr, + long style = wxFD_DEFAULT_STYLE, + const wxPoint& pos = wxDefaultPosition, + const wxSize& sz = wxDefaultSize, + const wxString& name = wxFileDialogNameStr); + bool Create(wxWindow *parent, + const wxString& message = wxFileSelectorPromptStr, + const wxString& defaultDir = wxEmptyString, + const wxString& defaultFile = wxEmptyString, + const wxString& wildCard = wxFileSelectorDefaultWildcardStr, + long style = wxFD_DEFAULT_STYLE, + const wxPoint& pos = wxDefaultPosition, + const wxSize& sz = wxDefaultSize, + const wxString& name = wxFileDialogNameStr); + virtual ~FileDialog(); + + virtual wxString GetPath() const; + virtual void GetPaths(wxArrayString& paths) const; + virtual wxString GetFilename() const; + virtual void GetFilenames(wxArrayString& files) const; + virtual int GetFilterIndex() const; + + virtual void SetMessage(const wxString& message); + virtual void SetPath(const wxString& path); + virtual void SetDirectory(const wxString& dir); + virtual void SetFilename(const wxString& name); + virtual void SetWildcard(const wxString& wildCard); + virtual void SetFilterIndex(int filterIndex); + + virtual int ShowModal(); + + virtual bool SupportsExtraControl() const { return true; } + + // Implementation only. + void GTKSelectionChanged(const wxString& filename); + void GTKFolderChanged(); + void GTKFilterChanged(); + + +protected: + // override this from wxTLW since the native + // form doesn't have any m_wxwindow + virtual void DoSetSize(int x, int y, + int width, int height, + int sizeFlags = wxSIZE_AUTO); + + private: - DECLARE_DYNAMIC_CLASS(FileDialog) - DECLARE_EVENT_TABLE() - void OnFakeOk( wxCommandEvent &event ); - - wxString m_buttonlabel; - fdCallback m_callback; - void *m_cbdata; - wxArrayString m_patterns; + void OnFakeOk( wxCommandEvent &event ); + void OnSize(wxSizeEvent&); + virtual void AddChildGTK(wxWindowGTK* child); + + wxGtkFileChooser m_fc; + + DECLARE_DYNAMIC_CLASS(FileDialog) + DECLARE_EVENT_TABLE() }; #endif diff --git a/lib-src/FileDialog/gtk/private.h b/lib-src/FileDialog/gtk/private.h deleted file mode 100644 index 7c2adf5e0..000000000 --- a/lib-src/FileDialog/gtk/private.h +++ /dev/null @@ -1,156 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// Name: wx/gtk/private.h -// Purpose: wxGTK private macros, functions &c -// Author: Vadim Zeitlin -// Modified by: Leland Lucius -// Created: 12.03.02 -// RCS-ID: $Id: private.h,v 1.3 2008-05-24 02:57:39 llucius Exp $ -// Copyright: (c) 2002 Vadim Zeitlin -// Licence: wxWindows licence -// -// Modified for Audacity to support an additional button on Save dialogs -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef _WX_GTK_PRIVATE_H_ -#define _WX_GTK_PRIVATE_H_ - -#include -#include - -#include "wx/event.h" - -// fail all version tests if the GTK+ version is so ancient that it doesn't -// even have GTK_CHECK_VERSION -#ifndef GTK_CHECK_VERSION -#define GTK_CHECK_VERSION(a, b, c) 0 -#endif - -#if defined(__WXGTK20__) -#if wxUSE_UNICODE -#define wxGTK_CONV(s) wxConvUTF8.cWX2MB(s) -#define wxGTK_CONV_BACK(s) wxConvUTF8.cMB2WX(s) -#else -#define wxGTK_CONV(s) wxConvUTF8.cWC2MB( wxConvLocal.cWX2WC(s) ) -#define wxGTK_CONV_BACK(s) wxConvLocal.cWC2WX( (wxConvUTF8.cMB2WC( s ) ) ) -#endif -#else -#define wxGTK_CONV(s) s.c_str() -#define wxGTK_CONV_BACK(s) s -#endif - - -// GTK+ 2.0 compatibility define is broken when used from C++ as it -// casts enum to int implicitly -#ifdef __WXGTK20__ -#undef gtk_signal_disconnect_by_func -#define gtk_signal_disconnect_by_func(object,func,data) \ -gtk_signal_compat_matched((object), (func), (data), \ -(GSignalMatchType)(G_SIGNAL_MATCH_FUNC | \ -G_SIGNAL_MATCH_DATA), 0) -#endif - -// child is not a member of GTK_BUTTON() any more in GTK+ 2.0 -#ifdef __WXGTK20__ -#define BUTTON_CHILD(w) GTK_BIN((w))->child -#else -#define BUTTON_CHILD(w) GTK_BUTTON((w))->child -#endif - -// event_window has disappeared from GtkToggleButton in GTK+ 2.0 -#ifdef __WXGTK20__ -#define TOGGLE_BUTTON_EVENT_WIN(w) GTK_BUTTON((w))->event_window -#else -#define TOGGLE_BUTTON_EVENT_WIN(w) GTK_TOGGLE_BUTTON((w))->event_window -#endif - -// gtk_editable_{copy|cut|paste}_clipboard() had an extra argument under -// previous GTK+ versions but no more -#if defined(__WXGTK20__) || (GTK_MINOR_VERSION > 0) -#define DUMMY_CLIPBOARD_ARG -#else -#define DUMMY_CLIPBOARD_ARG ,0 -#endif - -// _GtkEditable is now private -#ifdef __WXGTK20__ -#define GET_EDITABLE_POS(w) gtk_editable_get_position(GTK_EDITABLE(w)) -#define SET_EDITABLE_POS(w, pos) \ -gtk_editable_set_position(GTK_EDITABLE(w), (pos)) -#else -#define GET_EDITABLE_POS(w) GTK_EDITABLE((w))->current_pos -#define SET_EDITABLE_POS(w, pos) \ -GTK_EDITABLE((w))->current_pos = (pos) -#endif - -// this GtkNotebook struct field has been renamed -#ifdef __WXGTK20__ -#define NOTEBOOK_PANEL(nb) GTK_NOTEBOOK(nb)->event_window -#else -#define NOTEBOOK_PANEL(nb) GTK_NOTEBOOK(nb)->panel -#endif - -#ifdef __WXGTK20__ -#define SCROLLBAR_CBACK_ARG -#define GET_SCROLL_TYPE(w) GTK_SCROLL_JUMP -#else -#define SCROLLBAR_CBACK_ARG -#define GET_SCROLL_TYPE(w) GTK_RANGE((w))->scroll_type -#endif - -// translate a GTK+ scroll type to a wxEventType -inline wxEventType GtkScrollTypeToWx(guint scrollType) -{ - wxEventType command; - switch ( scrollType ) - { - case GTK_SCROLL_STEP_BACKWARD: - command = wxEVT_SCROLL_LINEUP; - break; - - case GTK_SCROLL_STEP_FORWARD: - command = wxEVT_SCROLL_LINEDOWN; - break; - - case GTK_SCROLL_PAGE_BACKWARD: - command = wxEVT_SCROLL_PAGEUP; - break; - - case GTK_SCROLL_PAGE_FORWARD: - command = wxEVT_SCROLL_PAGEDOWN; - break; - - default: - command = wxEVT_SCROLL_THUMBTRACK; - } - - return command; -} - -inline wxEventType GtkScrollWinTypeToWx(guint scrollType) -{ - // GtkScrollTypeToWx() returns SCROLL_XXX, not SCROLLWIN_XXX as we need - return GtkScrollTypeToWx(scrollType) + - wxEVT_SCROLLWIN_TOP - wxEVT_SCROLL_TOP; -} - -// Needed for implementing e.g. combobox on wxGTK within a modal dialog. -void wxAddGrab(wxWindow* window); -void wxRemoveGrab(wxWindow* window); - -#ifdef __WXGTK20__ -// Escapes string so that it is valid Pango markup XML string: -wxString wxEscapeStringForPangoMarkup(const wxString& str); -#endif - -// The declaration for gtk_icon_size_lookup was accidentally ifdefed out in -// GTK+ 2.1.0 which Sun seem to have shipped with some versions of JDS -// for Solaris 9 x86. -#ifdef NEED_GTK_ICON_SIZE_LOOKUP -extern "C" gboolean gtk_icon_size_lookup (GtkIconSize size, - gint *width, - gint *height); -#endif - -#endif // _WX_GTK_PRIVATE_H_ - diff --git a/lib-src/FileDialog/mac/FileDialog.h b/lib-src/FileDialog/mac/FileDialogPrivate.h similarity index 100% rename from lib-src/FileDialog/mac/FileDialog.h rename to lib-src/FileDialog/mac/FileDialogPrivate.h diff --git a/lib-src/FileDialog/mac/FileDialog.mm b/lib-src/FileDialog/mac/FileDialogPrivate.mm similarity index 100% rename from lib-src/FileDialog/mac/FileDialog.mm rename to lib-src/FileDialog/mac/FileDialogPrivate.mm diff --git a/lib-src/FileDialog/win/FileDialogPrivate.h b/lib-src/FileDialog/win/FileDialogPrivate.h index 76464d811..79beceff1 100644 --- a/lib-src/FileDialog/win/FileDialogPrivate.h +++ b/lib-src/FileDialog/win/FileDialogPrivate.h @@ -12,8 +12,8 @@ // ///////////////////////////////////////////////////////////////////////////// -#ifndef _FILEDIALOGMSW_H_ -#define _FILEDIALOGMSW_H_ +#ifndef _WIN_FILEDIALOGPRIVATE_H_ +#define _WIN_FILEDIALOGPRIVATE_H_ #include @@ -90,9 +90,6 @@ private: wxChar *m_NameBuf; int m_NameBufLen; - fdCallback m_callback; - void *m_cbdata; - HWND mParentDlg; HWND mChildDlg; WNDPROC mParentProc; diff --git a/lib-src/Makefile.in b/lib-src/Makefile.in index e5f363a97..ad69383e6 100644 --- a/lib-src/Makefile.in +++ b/lib-src/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.14.1 from Makefile.am. +# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2013 Free Software Foundation, Inc. +# Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -14,7 +14,17 @@ @SET_MAKE@ VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -77,9 +87,6 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ -DIST_COMMON = $(srcdir)/dist-libsoxr.mk $(srcdir)/dist-libvamp.mk \ - $(srcdir)/dist-portaudio.mk $(srcdir)/Makefile.in \ - $(srcdir)/Makefile.am @USE_LOCAL_EXPAT_TRUE@am__append_1 = expat @USE_LOCAL_LIBID3TAG_TRUE@am__append_2 = libid3tag @USE_LOCAL_LIBMAD_TRUE@am__append_3 = libmad @@ -139,6 +146,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ac_c99_func_lrint.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/src/configwin.h \ $(top_builddir)/src/configunix.h @@ -198,6 +206,8 @@ am__define_uniq_tagged_files = \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/dist-libsoxr.mk \ + $(srcdir)/dist-libvamp.mk $(srcdir)/dist-portaudio.mk DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ @@ -963,7 +973,6 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/di echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib-src/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign lib-src/Makefile -.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ @@ -972,7 +981,7 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; -$(srcdir)/dist-libsoxr.mk $(srcdir)/dist-libvamp.mk $(srcdir)/dist-portaudio.mk: +$(srcdir)/dist-libsoxr.mk $(srcdir)/dist-libvamp.mk $(srcdir)/dist-portaudio.mk $(am__empty): $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh @@ -1240,6 +1249,8 @@ uninstall-am: mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ps ps-am tags tags-am uninstall uninstall-am +.PRECIOUS: Makefile + # Overwrite install* targets from automake. We do not want to install anything # from the lib-src libraries, because we statically link these libraries. diff --git a/lib-src/lib-widget-extra/configure b/lib-src/lib-widget-extra/configure index 9bf58bd9e..05ba2c083 100755 --- a/lib-src/lib-widget-extra/configure +++ b/lib-src/lib-widget-extra/configure @@ -2347,7 +2347,7 @@ ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. -am__api_version='1.14' +am__api_version='1.15' # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or @@ -2519,8 +2519,8 @@ test "$program_suffix" != NONE && ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` -# expand $ac_aux_dir to an absolute path -am_aux_dir=`cd $ac_aux_dir && pwd` +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` if test x"${MISSING+set}" != xset; then case $am_aux_dir in @@ -2539,7 +2539,7 @@ else $as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} fi -if test x"${install_sh}" != xset; then +if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; @@ -2867,8 +2867,8 @@ MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} # mkdir_p='$(MKDIR_P)' -# We need awk for the "check" target. The system "awk" is bad on -# some platforms. +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. # Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AMTAR='$${TAR-tar}' @@ -2926,6 +2926,7 @@ END fi fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5 $as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; } # Check whether --enable-maintainer-mode was given. @@ -16566,8 +16567,10 @@ if test "x$cpp_does_wall" = "xyes" ; then fi -# Extract the first word of "wx-config", so it can be a program name with args. -set dummy wx-config; ac_word=$2 +for ac_prog in wx-config wx-config-3.0 +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_WX_CONFIG+:} false; then : @@ -16594,7 +16597,6 @@ done done IFS=$as_save_IFS - test -z "$ac_cv_path_WX_CONFIG" && ac_cv_path_WX_CONFIG="no" ;; esac fi @@ -16608,6 +16610,10 @@ $as_echo "no" >&6; } fi + test -n "$WX_CONFIG" && break +done +test -n "$WX_CONFIG" || WX_CONFIG="no" + if [ "$WX_CONFIG" = "no" ] ; then as_fn_error $? "\"Could not find wx-config: is wxWidgets installed? is wx-config in your path?\"" "$LINENO" 5 fi diff --git a/lib-src/lib-widget-extra/configure.ac b/lib-src/lib-widget-extra/configure.ac index 583a2be44..686b57348 100644 --- a/lib-src/lib-widget-extra/configure.ac +++ b/lib-src/lib-widget-extra/configure.ac @@ -108,7 +108,7 @@ fi dnl --- check for required libraries --- dnl wxWidgets -- we assume that if wx-config is found, wxWidgets is successfully installed. -AC_PATH_PROG(WX_CONFIG, wx-config, no, $PATH:/usr/local/bin ) +AC_PATH_PROGS(WX_CONFIG, wx-config wx-config-3.0, no, $PATH:/usr/local/bin ) if [[ "$WX_CONFIG" = "no" ]] ; then AC_MSG_ERROR("Could not find wx-config: is wxWidgets installed? is wx-config in your path?") fi diff --git a/lib-src/mod-nyq-bench/configure b/lib-src/mod-nyq-bench/configure index 8c0b7281c..5a0d5752d 100755 --- a/lib-src/mod-nyq-bench/configure +++ b/lib-src/mod-nyq-bench/configure @@ -2296,7 +2296,7 @@ ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. -am__api_version='1.14' +am__api_version='1.15' # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or @@ -2468,8 +2468,8 @@ test "$program_suffix" != NONE && ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` -# expand $ac_aux_dir to an absolute path -am_aux_dir=`cd $ac_aux_dir && pwd` +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` if test x"${MISSING+set}" != xset; then case $am_aux_dir in @@ -2488,7 +2488,7 @@ else $as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} fi -if test x"${install_sh}" != xset; then +if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; @@ -2816,8 +2816,8 @@ MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} # mkdir_p='$(MKDIR_P)' -# We need awk for the "check" target. The system "awk" is bad on -# some platforms. +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. # Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AMTAR='$${TAR-tar}' @@ -2875,6 +2875,7 @@ END fi fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5 $as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; } # Check whether --enable-maintainer-mode was given. @@ -15454,8 +15455,10 @@ else fi -# Extract the first word of "wx-config", so it can be a program name with args. -set dummy wx-config; ac_word=$2 +for ac_prog in wx-config wx-config-3.0 +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_WX_CONFIG+:} false; then : @@ -15482,7 +15485,6 @@ done done IFS=$as_save_IFS - test -z "$ac_cv_path_WX_CONFIG" && ac_cv_path_WX_CONFIG="no" ;; esac fi @@ -15496,6 +15498,10 @@ $as_echo "no" >&6; } fi + test -n "$WX_CONFIG" && break +done +test -n "$WX_CONFIG" || WX_CONFIG="no" + if [ "$WX_CONFIG" = "no" ] ; then as_fn_error $? "\"Could not find wx-config: is wxWidgets installed? is wx-config in your path?\"" "$LINENO" 5 fi diff --git a/lib-src/mod-nyq-bench/configure.ac b/lib-src/mod-nyq-bench/configure.ac index d01c05a67..b796f5a08 100644 --- a/lib-src/mod-nyq-bench/configure.ac +++ b/lib-src/mod-nyq-bench/configure.ac @@ -53,7 +53,7 @@ AC_ARG_WITH(wx-config, wx_config="") dnl wxWidgets -- we assume that if wx-config is found, wxWidgets is successfully installed. -AC_PATH_PROG(WX_CONFIG, wx-config, no, $PATH:/usr/local/bin ) +AC_PATH_PROGS(WX_CONFIG, wx-config wx-config-3.0, no, $PATH:/usr/local/bin ) if [[ "$WX_CONFIG" = "no" ]] ; then AC_MSG_ERROR("Could not find wx-config: is wxWidgets installed? is wx-config in your path?") fi diff --git a/mac/Audacity.xcodeproj/project.pbxproj b/mac/Audacity.xcodeproj/project.pbxproj index 6360cea2c..2877bea29 100644 --- a/mac/Audacity.xcodeproj/project.pbxproj +++ b/mac/Audacity.xcodeproj/project.pbxproj @@ -431,7 +431,7 @@ 2800FE370FF32566005CA9E5 /* MidiIOPrefs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2800FE350FF32566005CA9E5 /* MidiIOPrefs.cpp */; }; 2801127B1943EE0E00D98A16 /* HelpSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 280112791943EE0E00D98A16 /* HelpSystem.cpp */; }; 2801A6460BF9268700648258 /* ImportQT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2801A6430BF9268700648258 /* ImportQT.cpp */; }; - 2806EF7A1B32532A00D1AB9A /* FileDialog.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2806EF791B32532A00D1AB9A /* FileDialog.mm */; }; + 2806EF7A1B32532A00D1AB9A /* FileDialogPrivate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2806EF791B32532A00D1AB9A /* FileDialogPrivate.mm */; }; 280828550A75E0D0000002EF /* LabelDialog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 280828530A75E0D0000002EF /* LabelDialog.cpp */; }; 2808285A0A75E0EA000002EF /* Grid.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 280828580A75E0EA000002EF /* Grid.cpp */; }; 2809C4B80BCB7E560006010F /* FileIO.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2809C4B60BCB7E560006010F /* FileIO.cpp */; }; @@ -2044,8 +2044,8 @@ 2803C8B519F35AA000278526 /* PluginManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PluginManager.h; sourceTree = ""; }; 2803C8B619F35AA000278526 /* TrackPanelListener.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TrackPanelListener.h; sourceTree = ""; }; 2803C8BB19F35B4900278526 /* SelectionBarListener.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SelectionBarListener.h; sourceTree = ""; }; - 2806EF781B32532A00D1AB9A /* FileDialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FileDialog.h; sourceTree = ""; }; - 2806EF791B32532A00D1AB9A /* FileDialog.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FileDialog.mm; sourceTree = ""; }; + 2806EF781B32532A00D1AB9A /* FileDialogPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FileDialogPrivate.h; sourceTree = ""; }; + 2806EF791B32532A00D1AB9A /* FileDialogPrivate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FileDialogPrivate.mm; sourceTree = ""; }; 2808025C0F32C11F0021001D /* dspprims.lsp */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; name = dspprims.lsp; path = ../nyquist/dspprims.lsp; sourceTree = SOURCE_ROOT; }; 2808025D0F32C11F0021001D /* envelopes.lsp */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; name = envelopes.lsp; path = ../nyquist/envelopes.lsp; sourceTree = SOURCE_ROOT; }; 2808025E0F32C11F0021001D /* equalizer.lsp */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; name = equalizer.lsp; path = ../nyquist/equalizer.lsp; sourceTree = SOURCE_ROOT; }; @@ -5485,8 +5485,8 @@ 28F8BBDA0BC5FA6600CDF16E /* mac */ = { isa = PBXGroup; children = ( - 2806EF781B32532A00D1AB9A /* FileDialog.h */, - 2806EF791B32532A00D1AB9A /* FileDialog.mm */, + 2806EF781B32532A00D1AB9A /* FileDialogPrivate.h */, + 2806EF791B32532A00D1AB9A /* FileDialogPrivate.mm */, ); path = mac; sourceTree = ""; @@ -7385,7 +7385,7 @@ 1790B18109883BFD008A330A /* DirectoriesPrefs.cpp in Sources */, 1790B18309883BFD008A330A /* GUIPrefs.cpp in Sources */, 1790B18409883BFD008A330A /* KeyConfigPrefs.cpp in Sources */, - 2806EF7A1B32532A00D1AB9A /* FileDialog.mm in Sources */, + 2806EF7A1B32532A00D1AB9A /* FileDialogPrivate.mm in Sources */, 1790B18509883BFD008A330A /* MousePrefs.cpp in Sources */, 1790B18609883BFD008A330A /* PrefsDialog.cpp in Sources */, 1790B18709883BFD008A330A /* QualityPrefs.cpp in Sources */, diff --git a/src/AudacityApp.cpp b/src/AudacityApp.cpp index 773859105..ac7b940ed 100644 --- a/src/AudacityApp.cpp +++ b/src/AudacityApp.cpp @@ -1,2255 +1,2255 @@ -/********************************************************************** - - Audacity: A Digital Audio Editor - - AudacityApp.cpp - - Dominic Mazzoni - -******************************************************************//** - -\class AudacityApp -\brief AudacityApp is the 'main' class for Audacity - -It handles initialization and termination by subclassing wxApp. - -*//*******************************************************************/ - -#if 0 -// This may be used to debug memory leaks. -// See: Visual Leak Dectector @ http://vld.codeplex.com/ -#include -#endif - -#include "Audacity.h" // This should always be included first - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -#ifdef __WXGTK__ -#include -#endif - -// chmod, lstat, geteuid -#ifdef __UNIX__ -#include -#include -#include -#endif - -#include "AudacityApp.h" - -#include "AudacityLogger.h" -#include "AboutDialog.h" -#include "AColor.h" -#include "AudioIO.h" -#include "Benchmark.h" -#include "DirManager.h" -#include "commands/CommandHandler.h" -#include "commands/AppCommandEvent.h" -#include "effects/Contrast.h" -#include "widgets/ASlider.h" -#include "FFmpeg.h" -#include "Internat.h" -#include "LangChoice.h" -#include "Languages.h" -#include "PluginManager.h" -#include "Prefs.h" -#include "Project.h" -#include "Screenshot.h" -#include "Sequence.h" -#include "WaveTrack.h" -#include "Internat.h" -#include "prefs/PrefsDialog.h" -#include "Theme.h" -#include "PlatformCompatibility.h" -#include "FileNames.h" -#include "AutoRecovery.h" -#include "SplashDialog.h" -#include "FFT.h" -#include "BlockFile.h" -#include "ondemand/ODManager.h" -#include "commands/Keyboard.h" -#include "widgets/ErrorDialog.h" - -//temporarilly commented out till it is added to all projects -//#include "Profiler.h" - -#include "ModuleManager.h" - -#include "import/Import.h" - -#if defined(EXPERIMENTAL_CRASH_REPORT) -#include -#include -#include -#endif - -#ifdef EXPERIMENTAL_SCOREALIGN -#include "effects/ScoreAlignDialog.h" -#endif - -#if 0 -#ifdef _DEBUG - #ifdef _MSC_VER - #undef THIS_FILE - static char*THIS_FILE= __FILE__; - #define new new(_NORMAL_BLOCK, THIS_FILE, __LINE__) - #endif -#endif -#endif - -// Windows specific linker control...only needed once so -// this is a good place (unless we want to add another file). -#if defined(__WXMSW__) -//#if wxCHECK_VERSION(3, 0, 2) && !wxCHECK_VERSION(3, 1, 0) -#include -//#endif -// These lines ensure that Audacity gets WindowsXP themes. -// Without them we get the old-style Windows98/2000 look under XP. -# if !defined(__WXWINCE__) -# pragma comment(linker, "\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='X86' publicKeyToken='6595b64144ccf1df'\"") -# endif - -// These lines allows conditional inclusion of the various libraries -// that Audacity can use. - -# if defined(USE_LIBFLAC) -# pragma comment(lib, "libflac++") -# pragma comment(lib, "libflac") -# endif - -# if defined(USE_LIBID3TAG) -# pragma comment(lib, "libid3tag") -# endif - -# if defined(USE_LIBMAD) -# pragma comment(lib, "libmad") -# endif - -# if defined(USE_LIBTWOLAME) -# pragma comment(lib, "twolame") -# endif - -# if defined(USE_LIBVORBIS) -# pragma comment(lib, "libogg") -# pragma comment(lib, "libvorbis") -# endif - -# if defined(USE_LV2) -# pragma comment(lib, "lv2") -# endif - -# if defined(USE_MIDI) -# pragma comment(lib, "portsmf") -# endif - -# if defined(EXPERIMENTAL_MIDI_OUT) -# pragma comment(lib, "portmidi") -# endif - -# if defined(EXPERIMENTAL_SCOREALIGN) -# pragma comment(lib, "libscorealign") -# endif - -# if defined(USE_NYQUIST) -# pragma comment(lib, "libnyquist") -# endif - -# if defined(USE_PORTMIXER) -# pragma comment(lib, "portmixer") -# endif - -# if defined(USE_SBSMS) -# pragma comment(lib, "sbsms") -# endif - -# if defined(USE_SOUNDTOUCH) -# pragma comment(lib, "soundtouch") -# endif - -# if defined(USE_VAMP) -# pragma comment(lib, "libvamp") -# endif - -# if defined(__WXDEBUG__) -# define D "d" -# else -# define D "" -# endif -# if wxCHECK_VERSION(3, 1, 0) -# define V "31" -# elif wxCHECK_VERSION(3, 0, 0) -# define V "30" -# else -# define V "28" -# endif - -# if defined(EXPERIMENTAL_CRASH_REPORT) -# pragma comment(lib, "wxmsw" V "u" D "_qa") -# endif -# pragma comment(lib, "wxbase" V "u" D) -# pragma comment(lib, "wxbase" V "u" D "_net.lib") -# pragma comment(lib, "wxmsw" V "u" D "_adv.lib") -# pragma comment(lib, "wxmsw" V "u" D "_core.lib") -# pragma comment(lib, "wxmsw" V "u" D "_html.lib") -# pragma comment(lib, "wxpng" D) -# pragma comment(lib, "wxzlib" D) -# pragma comment(lib, "wxjpeg" D) -# pragma comment(lib, "wxtiff" D) - -# undef V -# undef D - -#endif //(__WXMSW__) - -#include "../images/AudacityLogoWithName.xpm" - -//////////////////////////////////////////////////////////// -/// Custom events -//////////////////////////////////////////////////////////// - -DEFINE_EVENT_TYPE(EVT_OPEN_AUDIO_FILE); -DEFINE_EVENT_TYPE(EVT_CAPTURE_KEYBOARD); -DEFINE_EVENT_TYPE(EVT_RELEASE_KEYBOARD); -DEFINE_EVENT_TYPE(EVT_CAPTURE_KEY); - -#ifdef __WXGTK__ -static void wxOnAssert(const wxChar *fileName, int lineNumber, const wxChar *msg) -{ - if (msg) - printf("ASSERTION FAILED: %s\n%s: %d\n", (const char *)wxString(msg).mb_str(), (const char *)wxString(fileName).mb_str(), lineNumber); - else - printf("ASSERTION FAILED!\n%s: %d\n", (const char *)wxString(fileName).mb_str(), lineNumber); - - // Force core dump - int *i = 0; - if (*i) - exit(1); - - exit(0); -} -#endif - -static wxFrame *gParentFrame = NULL; - -static bool gInited = false; -bool gIsQuitting = false; - -void QuitAudacity(bool bForce) -{ - if (gIsQuitting) - return; - - gIsQuitting = true; - - // Try to close each open window. If the user hits Cancel - // in a Save Changes dialog, don't continue. - // BG: unless force is true - - // BG: Are there any projects open? - //- if (!gAudacityProjects.IsEmpty()) -/*start+*/ - if (gAudacityProjects.IsEmpty()) - { -#ifdef __WXMAC__ - AudacityProject::DeleteClipboard(); -#endif - } - else -/*end+*/ - { - SaveWindowSize(); - while (gAudacityProjects.Count()) - { - if (bForce) - { - gAudacityProjects[0]->Close(true); - } - else - { - if (!gAudacityProjects[0]->Close()) - { - gIsQuitting = false; - return; - } - } - } - } - - LWSlider::DeleteSharedTipPanel(); - - ModuleManager::Get().Dispatch(AppQuiting); - - if (gParentFrame) - gParentFrame->Destroy(); - gParentFrame = NULL; - -#ifdef EXPERIMENTAL_SCOREALIGN - CloseScoreAlignDialog(); -#endif - CloseScreenshotTools(); - - //release ODManager Threads - ODManager::Quit(); - - //print out profile if we have one by deleting it - //temporarilly commented out till it is added to all projects - //delete Profiler::Instance(); - - //delete the static lock for audacity projects - AudacityProject::DeleteAllProjectsDeleteLock(); - - //remove our logger - delete wxLog::SetActiveTarget(NULL); - - if (bForce) - { - wxExit(); - } -} - -void QuitAudacity() -{ - QuitAudacity(false); -} - -void SaveWindowSize() -{ - if (wxGetApp().GetWindowRectAlreadySaved()) - { - return; - } - bool validWindowForSaveWindowSize = FALSE; - AudacityProject * validProject = NULL; - bool foundIconizedProject = FALSE; - size_t numProjects = gAudacityProjects.Count(); - for (size_t i = 0; i < numProjects; i++) - { - if (!gAudacityProjects[i]->IsIconized()) { - validWindowForSaveWindowSize = TRUE; - validProject = gAudacityProjects[i]; - i = numProjects; - } - else - foundIconizedProject = TRUE; - - } - if (validWindowForSaveWindowSize) - { - wxRect windowRect = validProject->GetRect(); - wxRect normalRect = validProject->GetNormalizedWindowState(); - bool wndMaximized = validProject->IsMaximized(); - gPrefs->Write(wxT("/Window/X"), windowRect.GetX()); - gPrefs->Write(wxT("/Window/Y"), windowRect.GetY()); - gPrefs->Write(wxT("/Window/Width"), windowRect.GetWidth()); - gPrefs->Write(wxT("/Window/Height"), windowRect.GetHeight()); - gPrefs->Write(wxT("/Window/Maximized"), wndMaximized); - gPrefs->Write(wxT("/Window/Normal_X"), normalRect.GetX()); - gPrefs->Write(wxT("/Window/Normal_Y"), normalRect.GetY()); - gPrefs->Write(wxT("/Window/Normal_Width"), normalRect.GetWidth()); - gPrefs->Write(wxT("/Window/Normal_Height"), normalRect.GetHeight()); - gPrefs->Write(wxT("/Window/Iconized"), FALSE); - } - else - { - if (foundIconizedProject) { - validProject = gAudacityProjects[0]; - bool wndMaximized = validProject->IsMaximized(); - wxRect normalRect = validProject->GetNormalizedWindowState(); - // store only the normal rectangle because the itemized rectangle - // makes no sense for an opening project window - gPrefs->Write(wxT("/Window/X"), normalRect.GetX()); - gPrefs->Write(wxT("/Window/Y"), normalRect.GetY()); - gPrefs->Write(wxT("/Window/Width"), normalRect.GetWidth()); - gPrefs->Write(wxT("/Window/Height"), normalRect.GetHeight()); - gPrefs->Write(wxT("/Window/Maximized"), wndMaximized); - gPrefs->Write(wxT("/Window/Normal_X"), normalRect.GetX()); - gPrefs->Write(wxT("/Window/Normal_Y"), normalRect.GetY()); - gPrefs->Write(wxT("/Window/Normal_Width"), normalRect.GetWidth()); - gPrefs->Write(wxT("/Window/Normal_Height"), normalRect.GetHeight()); - gPrefs->Write(wxT("/Window/Iconized"), TRUE); - } - else { - // this would be a very strange case that might possibly occur on the Mac - // Audacity would have to be running with no projects open - // in this case we are going to write only the default values - wxRect defWndRect; - GetDefaultWindowRect(&defWndRect); - gPrefs->Write(wxT("/Window/X"), defWndRect.GetX()); - gPrefs->Write(wxT("/Window/Y"), defWndRect.GetY()); - gPrefs->Write(wxT("/Window/Width"), defWndRect.GetWidth()); - gPrefs->Write(wxT("/Window/Height"), defWndRect.GetHeight()); - gPrefs->Write(wxT("/Window/Maximized"), FALSE); - gPrefs->Write(wxT("/Window/Normal_X"), defWndRect.GetX()); - gPrefs->Write(wxT("/Window/Normal_Y"), defWndRect.GetY()); - gPrefs->Write(wxT("/Window/Normal_Width"), defWndRect.GetWidth()); - gPrefs->Write(wxT("/Window/Normal_Height"), defWndRect.GetHeight()); - gPrefs->Write(wxT("/Window/Iconized"), FALSE); - } - } - gPrefs->Flush(); - wxGetApp().SetWindowRectAlreadySaved(TRUE); -} - -#if defined(__WXGTK__) && defined(HAVE_GTK) - -/////////////////////////////////////////////////////////////////////////////// -// Provide the ability to receive notification from the session manager -// when the user is logging out or shutting down. -// -// Most of this was taken from nsNativeAppSupportUnix.cpp from Mozilla. -/////////////////////////////////////////////////////////////////////////////// - -// TODO: May need updating. Is this code too obsolete (relying on Gnome2 so's) to be -// worth keeping anymore? -// CB suggests we use libSM directly ref: -// http://www.x.org/archive/X11R7.7/doc/libSM/SMlib.html#The_Save_Yourself_Callback - -#include -/* There is a conflict between the type names used in Glib >= 2.21 and those in - * wxGTK (http://trac.wxwidgets.org/ticket/10883) - * Happily we can avoid the hack, as we only need some of the headers, not - * the full GTK headers - */ -#include - -typedef struct _GnomeProgram GnomeProgram; -typedef struct _GnomeModuleInfo GnomeModuleInfo; -typedef struct _GnomeClient GnomeClient; - -typedef enum -{ - GNOME_SAVE_GLOBAL, - GNOME_SAVE_LOCAL, - GNOME_SAVE_BOTH -} GnomeSaveStyle; - -typedef enum -{ - GNOME_INTERACT_NONE, - GNOME_INTERACT_ERRORS, - GNOME_INTERACT_ANY -} GnomeInteractStyle; - -typedef enum -{ - GNOME_DIALOG_ERROR, - GNOME_DIALOG_NORMAL -} GnomeDialogType; - -typedef GnomeProgram * (*_gnome_program_init_fn)(const char *, - const char *, - const GnomeModuleInfo *, - int, - char **, - const char *, - ...); -typedef const GnomeModuleInfo * (*_libgnomeui_module_info_get_fn)(); -typedef GnomeClient * (*_gnome_master_client_fn)(void); -typedef void (*GnomeInteractFunction)(GnomeClient *, - gint, - GnomeDialogType, - gpointer); -typedef void (*_gnome_client_request_interaction_fn)(GnomeClient *, - GnomeDialogType, - GnomeInteractFunction, - gpointer); -typedef void (*_gnome_interaction_key_return_fn)(gint, gboolean); - -static _gnome_client_request_interaction_fn gnome_client_request_interaction; -static _gnome_interaction_key_return_fn gnome_interaction_key_return; - -static void interact_cb(GnomeClient *client, - gint key, - GnomeDialogType type, - gpointer data) -{ - wxCloseEvent e(wxEVT_QUERY_END_SESSION, wxID_ANY); - e.SetEventObject(&wxGetApp()); - e.SetCanVeto(true); - - wxGetApp().ProcessEvent(e); - - gnome_interaction_key_return(key, e.GetVeto()); -} - -static gboolean save_yourself_cb(GnomeClient *client, - gint phase, - GnomeSaveStyle style, - gboolean shutdown, - GnomeInteractStyle interact, - gboolean fast, - gpointer user_data) -{ - if (!shutdown || interact != GNOME_INTERACT_ANY) { - return TRUE; - } - - if (gAudacityProjects.IsEmpty()) { - return TRUE; - } - - gnome_client_request_interaction(client, - GNOME_DIALOG_NORMAL, - interact_cb, - NULL); - - return TRUE; -} - -class GnomeShutdown -{ - public: - GnomeShutdown() - { - mArgv[0] = strdup("Audacity"); - - mGnomeui = dlopen("libgnomeui-2.so.0", RTLD_NOW); - if (!mGnomeui) { - return; - } - - mGnome = dlopen("libgnome-2.so.0", RTLD_NOW); - if (!mGnome) { - return; - } - - _gnome_program_init_fn gnome_program_init = (_gnome_program_init_fn) - dlsym(mGnome, "gnome_program_init"); - _libgnomeui_module_info_get_fn libgnomeui_module_info_get = (_libgnomeui_module_info_get_fn) - dlsym(mGnomeui, "libgnomeui_module_info_get"); - _gnome_master_client_fn gnome_master_client = (_gnome_master_client_fn) - dlsym(mGnomeui, "gnome_master_client"); - - gnome_client_request_interaction = (_gnome_client_request_interaction_fn) - dlsym(mGnomeui, "gnome_client_request_interaction"); - gnome_interaction_key_return = (_gnome_interaction_key_return_fn) - dlsym(mGnomeui, "gnome_interaction_key_return"); - - - if (!gnome_program_init || !libgnomeui_module_info_get) { - return; - } - - gnome_program_init(mArgv[0], - "1.0", - libgnomeui_module_info_get(), - 1, - mArgv, - NULL); - - mClient = gnome_master_client(); - if (mClient == NULL) { - return; - } - - g_signal_connect(mClient, "save-yourself", G_CALLBACK(save_yourself_cb), NULL); - } - - virtual ~GnomeShutdown() - { - // Do not dlclose() the libraries here lest you want segfaults... - - free(mArgv[0]); - } - - private: - - char *mArgv[1]; - void *mGnomeui; - void *mGnome; - GnomeClient *mClient; -}; - -// This variable exists to call the constructor and -// connect a signal for the 'save-yourself' message. -GnomeShutdown GnomeShutdownInstance; - -#endif - -// Where drag/drop or "Open With" filenames get stored until -// the timer routine gets around to picking them up. -static wxArrayString ofqueue; - -// -// DDE support for opening multiple files with one instance -// of Audacity. -// - -#define IPC_APPL wxT("audacity") -#define IPC_TOPIC wxT("System") - -class IPCConn : public wxConnection -{ -public: - IPCConn() - : wxConnection() - { - }; - - ~IPCConn() - { - }; - - bool OnExec(const wxString & WXUNUSED(topic), - const wxString & data) - { - // Add the filename to the queue. It will be opened by - // the OnTimer() event when it is safe to do so. - ofqueue.Add(data); - - return true; - } - -#if !wxCHECK_VERSION(3, 0, 0) - bool OnExecute(const wxString & topic, - wxChar *data, - int WXUNUSED(size), - wxIPCFormat WXUNUSED(format)) - { - return OnExec(topic, data); - } -#endif -}; - -class IPCServ : public wxServer -{ -public: - IPCServ(const wxString & appl) - : wxServer() - { - Create(appl); - }; - - ~IPCServ() - { - }; - - wxConnectionBase *OnAcceptConnection(const wxString & topic) - { - if (topic != IPC_TOPIC) { - return NULL; - } - - return new IPCConn(); - }; -}; - -#if !defined(__WXMAC__) && !defined(__WXMSW__) -IMPLEMENT_APP(AudacityApp) -/* make the application class known to wxWidgets for dynamic construction */ -#endif - -#if defined(__WXMAC__) || defined(__WXMSW__) -// This should be removed when Lame and FFmpeg support is converted -// from loadable libraries to commands. -// -// The purpose of this is to give the user more control over where libraries -// such as Lame and FFmpeg get loaded from. -// -// Since absolute pathnames are used when loading these libraries, the normal search -// path would be DYLD_LIBRARY_PATH, absolute path, DYLD_FALLBACK_LIBRARY_PATH. This -// means that DYLD_LIBRARY_PATH can override what the user actually wants. -// -// So, we simply clear DYLD_LIBRARY_PATH to allow the users choice to be the first -// one tried. -IMPLEMENT_APP_NO_MAIN(AudacityApp) -IMPLEMENT_WX_THEME_SUPPORT - -#if defined(__WXMAC__) -int main(int argc, char *argv[]) -{ - if (getenv("DYLD_LIBRARY_PATH")) { - extern char **environ; - - unsetenv("DYLD_LIBRARY_PATH"); - execve(argv[0], argv, environ); - } - - wxDISABLE_DEBUG_SUPPORT(); - - return wxEntry(argc, argv); -} - -#elif defined(__WXMSW__) - -extern "C" int WINAPI WinMain(HINSTANCE hInstance, - HINSTANCE hPrevInstance, - wxCmdLineArgType WXUNUSED(lpCmdLine), - int nCmdShow) -{ - wxDISABLE_DEBUG_SUPPORT(); - - // Disable setting of HiDPI aware mode - wxMSWDisableSettingHighDPIAware(); - - /* NB: We pass NULL in place of lpCmdLine to behave the same as */ - /* Borland-specific wWinMain() above. If it becomes needed */ - /* to pass lpCmdLine to wxEntry() here, you'll have to fix */ - /* wWinMain() above too. */ - return wxEntry(hInstance, hPrevInstance, NULL, nCmdShow); -} -#endif -#endif - -#ifdef __WXMAC__ - -// in response of an open-document apple event -void AudacityApp::MacOpenFile(const wxString &fileName) -{ - ofqueue.Add(fileName); -} - -// in response of a print-document apple event -void AudacityApp::MacPrintFile(const wxString &fileName) -{ - ofqueue.Add(fileName); -} - -// in response of a open-application apple event -void AudacityApp::MacNewFile() -{ - if (!gInited) - return; - - // This method should only be used on the Mac platform - // when no project windows are open. - - if (gAudacityProjects.GetCount() == 0) { - CreateNewAudacityProject(); - } -} - -#endif //__WXMAC__ - -typedef int (AudacityApp::*SPECIALKEYEVENT)(wxKeyEvent&); - -#define ID_RECENT_CLEAR 6100 -#define ID_RECENT_FIRST 6101 -#define ID_RECENT_LAST 6112 - -// IPC communication -#define ID_IPC_SERVER 6200 -#define ID_IPC_SOCKET 6201 - -// we don't really care about the timer id, but set this value just in case we do in the future -#define kAudacityAppTimerID 0 - -BEGIN_EVENT_TABLE(AudacityApp, wxApp) - EVT_QUERY_END_SESSION(AudacityApp::OnEndSession) - - EVT_KEY_DOWN(AudacityApp::OnKeyDown) - EVT_CHAR(AudacityApp::OnChar) - EVT_KEY_UP(AudacityApp::OnKeyUp) - EVT_TIMER(kAudacityAppTimerID, AudacityApp::OnTimer) -#ifdef __WXMAC__ - EVT_MENU(wxID_NEW, AudacityApp::OnMenuNew) - EVT_MENU(wxID_OPEN, AudacityApp::OnMenuOpen) - EVT_MENU(wxID_ABOUT, AudacityApp::OnMenuAbout) - EVT_MENU(wxID_PREFERENCES, AudacityApp::OnMenuPreferences) - EVT_MENU(wxID_EXIT, AudacityApp::OnMenuExit) -#endif - -#ifndef __WXMSW__ - EVT_SOCKET(ID_IPC_SERVER, AudacityApp::OnServerEvent) - EVT_SOCKET(ID_IPC_SOCKET, AudacityApp::OnSocketEvent) -#endif - - // Recent file event handlers. - EVT_MENU(ID_RECENT_CLEAR, AudacityApp::OnMRUClear) - EVT_MENU_RANGE(ID_RECENT_FIRST, ID_RECENT_LAST, AudacityApp::OnMRUFile) - - // Handle AppCommandEvents (usually from a script) - EVT_APP_COMMAND(wxID_ANY, AudacityApp::OnReceiveCommand) -END_EVENT_TABLE() - -// backend for OnMRUFile -// TODO: Would be nice to make this handle not opening a file with more panache. -// - Inform the user if DefaultOpenPath not set. -// - Switch focus to correct instance of project window, if already open. -bool AudacityApp::MRUOpen(wxString fullPathStr) { - // Most of the checks below are copied from AudacityProject::OpenFiles. - // - some rationalisation might be possible. - - AudacityProject *proj = GetActiveProject(); - - if (!fullPathStr.IsEmpty()) - { - // verify that the file exists - if (wxFile::Exists(fullPathStr)) - { - if (!gPrefs->Write(wxT("/DefaultOpenPath"), wxPathOnly(fullPathStr)) || - !gPrefs->Flush()) - return false; - - // Make sure it isn't already open. - // Test here even though AudacityProject::OpenFile() also now checks, because - // that method does not return the bad result. - // That itself may be a FIXME. - if (AudacityProject::IsAlreadyOpen(fullPathStr)) - return false; - - // DMM: If the project is dirty, that means it's been touched at - // all, and it's not safe to open a new project directly in its - // place. Only if the project is brand-new clean and the user - // hasn't done any action at all is it safe for Open to take place - // inside the current project. - // - // If you try to Open a new project inside the current window when - // there are no tracks, but there's an Undo history, etc, then - // bad things can happen, including data files moving to the new - // project directory, etc. - if (!proj || proj->GetDirty() || !proj->GetIsEmpty()) { - proj = CreateNewAudacityProject(); - } - // This project is clean; it's never been touched. Therefore - // all relevant member variables are in their initial state, - // and it's okay to open a new project inside this window. - proj->OpenFile(fullPathStr); - } - else { - // File doesn't exist - remove file from history - wxMessageBox(wxString::Format(_("%s could not be found.\n\nIt has been removed from the list of recent files."), - fullPathStr.c_str())); - return(false); - } - } - return(true); -} - -void AudacityApp::OnMRUClear(wxCommandEvent& WXUNUSED(event)) -{ - mRecentFiles->Clear(); -} - -//vvv Basically, anything from Recent Files is treated as a .aup, until proven otherwise, -// then it tries to Import(). Very questionable handling, imo. -// Better, for example, to check the file type early on. -void AudacityApp::OnMRUFile(wxCommandEvent& event) { - int n = event.GetId() - ID_RECENT_FIRST; - wxString fullPathStr = mRecentFiles->GetHistoryFile(n); - - // Try to open only if not already open. - // Test IsAlreadyOpen() here even though AudacityProject::MRUOpen() also now checks, - // because we don't want to RemoveFileFromHistory() just because it already exists, - // and AudacityApp::OnMacOpenFile() calls MRUOpen() directly. - // that method does not return the bad result. - if (!AudacityProject::IsAlreadyOpen(fullPathStr) && !MRUOpen(fullPathStr)) - mRecentFiles->RemoveFileFromHistory(n); -} - -void AudacityApp::OnTimer(wxTimerEvent& WXUNUSED(event)) -{ - // Filenames are queued when Audacity receives the a few of the - // AppleEvent messages (via wxWidgets). So, open any that are - // in the queue and clean the queue. - if (gInited) { - if (ofqueue.GetCount()) { - // Load each file on the queue - while (ofqueue.GetCount()) { - wxString name(ofqueue[0]); - ofqueue.RemoveAt(0); - - // Get the user's attention if no file name was specified - if (name.IsEmpty()) { - // Get the users attention - AudacityProject *project = GetActiveProject(); - if (project) { - project->Maximize(); - project->Raise(); - project->RequestUserAttention(); - } - continue; - } - - // TODO: Handle failures better. - // Some failures are OK, e.g. file not found, just would-be-nices to do better, - // so FAIL_MSG is more a case of an enhancement request than an actual problem. - // LL: In all but one case an appropriate message is already displayed. The - // instance that a message is NOT displayed is when a failure to write - // to the config file has occurred. - if (!MRUOpen(name)) { - wxFAIL_MSG(wxT("MRUOpen failed")); - } - } - } - } - - // Check if a warning for missing aliased files should be displayed - if (ShouldShowMissingAliasedFileWarning()) { - // find which project owns the blockfile - // note: there may be more than 1, but just go with the first one. - size_t numProjects = gAudacityProjects.Count(); - wxString missingFileName; - AudacityProject *offendingProject = NULL; - - m_LastMissingBlockFileLock.Lock(); - if (numProjects == 1) { - // if there is only one project open, no need to search - offendingProject = gAudacityProjects[0]; - } else if (numProjects > 1) { - for (size_t i = 0; i < numProjects; i++) { - // search each project for the blockfile - if (gAudacityProjects[i]->GetDirManager()->ContainsBlockFile(m_LastMissingBlockFile)) { - offendingProject = gAudacityProjects[i]; - break; - } - } - } - missingFileName = ((AliasBlockFile*)m_LastMissingBlockFile)->GetAliasedFileName().GetFullPath(); - m_LastMissingBlockFileLock.Unlock(); - - // if there are no projects open, don't show the warning (user has closed it) - if (offendingProject) { - offendingProject->Iconize(false); - offendingProject->Raise(); - - wxString errorMessage = wxString::Format(_( -"One or more external audio files could not be found.\n\ -It is possible they were moved, deleted, or the drive they \ -were on was unmounted.\n\ -Silence is being substituted for the affected audio.\n\ -The first detected missing file is:\n\ -%s\n\ -There may be additional missing files.\n\ -Choose File > Check Dependencies to view a list of \ -locations of the missing files."), missingFileName.c_str()); - - // if an old dialog exists, raise it if it is - if (offendingProject->GetMissingAliasFileDialog()) { - offendingProject->GetMissingAliasFileDialog()->Raise(); - } else { - ShowAliasMissingDialog(offendingProject, _("Files Missing"), - errorMessage, wxT(""), true); - } - } - // Only show this warning once per event (playback/menu item/etc). - SetMissingAliasedFileWarningShouldShow(false); - } -} - -void AudacityApp::MarkAliasedFilesMissingWarning(BlockFile *b) -{ - // the reference counting provides thread safety. - if (b) - b->Ref(); - - m_LastMissingBlockFileLock.Lock(); - if (m_LastMissingBlockFile) - m_LastMissingBlockFile->Deref(); - - m_LastMissingBlockFile = b; - - m_LastMissingBlockFileLock.Unlock(); -} - -void AudacityApp::SetMissingAliasedFileWarningShouldShow(bool b) -{ - // Note that this is can be called by both the main thread and other threads. - // I don't believe we need a mutex because we are checking zero vs non-zero, - // and the setting from other threads will always be non-zero (true), and the - // setting from the main thread is always false. - m_aliasMissingWarningShouldShow = b; - // reset the warnings as they were probably marked by a previous run - if (m_aliasMissingWarningShouldShow) { - MarkAliasedFilesMissingWarning(NULL); - } -} - -bool AudacityApp::ShouldShowMissingAliasedFileWarning() -{ - bool ret = m_LastMissingBlockFile && m_aliasMissingWarningShouldShow; - - return ret; -} - -AudacityLogger *AudacityApp::GetLogger() -{ - // Use dynamic_cast so that we get a NULL ptr if we haven't yet - // setup our logger. - return dynamic_cast(wxLog::GetActiveTarget()); -} - -#if defined(__WXMSW__) -#define WL(lang, sublang) (lang), (sublang), -#else -#define WL(lang,sublang) -#endif - -#if !wxCHECK_VERSION(3, 0, 1) -wxLanguageInfo userLangs[] = -{ - { wxLANGUAGE_USER_DEFINED, wxT("bs"), WL(0, SUBLANG_DEFAULT) wxT("Bosnian"), wxLayout_LeftToRight } -}; -#endif - -void AudacityApp::InitLang( const wxString & lang ) -{ - if (mLocale) - delete mLocale; - -#if defined(__WXMAC__) - // This should be reviewed again during the wx3 conversion. - - // On OSX, if the LANG environment variable isn't set when - // using a language like Japanese, an assertion will trigger - // because conversion to Japanese from "?" doesn't return a - // valid length, so make OSX happy by defining/overriding - // the LANG environment variable with U.S. English for now. - wxSetEnv(wxT("LANG"), wxT("en_US.UTF-8")); -#endif - -#if wxCHECK_VERSION(3,0,0) - mLocale = new wxLocale(wxT(""), lang, wxT(""), true); -#else - mLocale = new wxLocale(wxT(""), lang, wxT(""), true, true); -#endif - - for(unsigned int i=0; iAddCatalogLookupPathPrefix(audacityPathList[i]); - - // LL: Must add the wxWidgets catalog manually since the search - // paths were not set up when mLocale was created. The - // catalogs are search in LIFO order, so add wxstd first. - mLocale->AddCatalog(wxT("wxstd")); - -// AUDACITY_NAME is legitimately used on some *nix configurations. -#ifdef AUDACITY_NAME - mLocale->AddCatalog(wxT(AUDACITY_NAME)); -#else - mLocale->AddCatalog(IPC_APPL); -#endif - - // Initialize internationalisation (number formats etc.) - // - // This must go _after_ creating the wxLocale instance because - // creating the wxLocale instance sets the application-wide locale. - Internat::Init(); -} - -void AudacityApp::OnFatalException() -{ -#if defined(EXPERIMENTAL_CRASH_REPORT) - GenerateCrashReport(wxDebugReport::Context_Exception); -#endif - - exit(-1); -} - -#if defined(EXPERIMENTAL_CRASH_REPORT) -void AudacityApp::GenerateCrashReport(wxDebugReport::Context ctx) -{ - wxDebugReportCompress rpt; - rpt.AddAll(ctx); - - wxFileName fn(FileNames::DataDir(), wxT("audacity.cfg")); - rpt.AddFile(fn.GetFullPath(), wxT("Audacity Configuration")); - rpt.AddFile(FileNames::PluginRegistry(), wxT("Plugin Registry")); - rpt.AddFile(FileNames::PluginSettings(), wxT("Plugin Settings")); - - if (ctx == wxDebugReport::Context_Current) - { - rpt.AddText(wxT("audiodev.txt"), gAudioIO->GetDeviceInfo(), wxT("Audio Device Info")); - } - - AudacityLogger *logger = GetLogger(); - if (logger) - { - rpt.AddText(wxT("log.txt"), logger->GetLog(), wxT("Audacity Log")); - } - - bool ok = wxDebugReportPreviewStd().Show(rpt); - -#if defined(__WXMSW__) - wxEventLoop::SetCriticalWindow(NULL); -#endif - - if (ok && rpt.Process()) - { - wxTextEntryDialog dlg(NULL, - _("Report generated to:"), - _("Audacity Support Data"), - rpt.GetCompressedFileName(), - wxOK | wxCENTER); - dlg.SetName(dlg.GetTitle()); - dlg.ShowModal(); - - wxLogMessage(wxT("Report generated to: %s"), - rpt.GetCompressedFileName().c_str()); - - rpt.Reset(); - } -} -#endif - -#if defined(__WXGTK__) -// On wxGTK, there's a focus issue where dialogs do not automatically pass focus -// to the first child. This means that you can use the keyboard to navigate within -// the dialog. Watching for the ACTIVATE event allows us to set the focus ourselves -// when each dialog opens. -// -// See bug #57 -// -int AudacityApp::FilterEvent(wxEvent & event) -{ - if (event.GetEventType() == wxEVT_ACTIVATE) - { - wxActivateEvent & e = (wxActivateEvent &) event; - - if (e.GetEventObject() && e.GetActive() && e.GetEventObject()->IsKindOf(CLASSINFO(wxDialog))) - { - ((wxWindow *)e.GetEventObject())->SetFocus(); - } - } - - return -1; -} -#endif - -AudacityApp::AudacityApp() -{ -// Do not capture crashes in debug builds -#if !defined(__WXDEBUG__) -#if defined(EXPERIMENTAL_CRASH_REPORT) -#if defined(wxUSE_ON_FATAL_EXCEPTION) && wxUSE_ON_FATAL_EXCEPTION - wxHandleFatalExceptions(); -#endif -#endif -#endif -} - -// The `main program' equivalent, creating the windows and returning the -// main frame -bool AudacityApp::OnInit() -{ - delete wxLog::SetActiveTarget(new AudacityLogger); - - mLocale = NULL; - - m_aliasMissingWarningShouldShow = true; - m_LastMissingBlockFile = NULL; - - mChecker = NULL; - mIPCServ = NULL; - -#if defined(__WXGTK__) - // Workaround for bug 154 -- initialize to false - inKbdHandler = false; -#endif - -#if defined(__WXMAC__) - // Disable window animation - wxSystemOptions::SetOption( wxMAC_WINDOW_PLAIN_TRANSITION, 1 ); -#endif - -#ifdef AUDACITY_NAME - wxString appName = wxT(AUDACITY_NAME); - wxString vendorName = wxT(AUDACITY_NAME); -#else - wxString vendorName = wxT("Audacity"); - wxString appName = wxT("Audacity"); -#endif - - wxTheApp->SetVendorName(vendorName); - wxTheApp->SetAppName(appName); - - // Unused strings that we want to be translated, even though - // we're not using them yet... - wxString future1 = _("Master Gain Control"); - - ::wxInitAllImageHandlers(); - - wxFileSystem::AddHandler(new wxZipFSHandler); - - // - // Paths: set search path and temp dir path - // - -#ifdef __WXGTK__ - /* Search path (for plug-ins, translations etc) is (in this order): - * The AUDACITY_PATH environment variable - * The current directory - * The user's .audacity-files directory in their home directory - * The "share" and "share/doc" directories in their install path */ - wxString home = wxGetHomeDir(); - - /* On Unix systems, the default temp dir is in /var/tmp. */ - defaultTempDir.Printf(wxT("/var/tmp/audacity-%s"), wxGetUserId().c_str()); - - wxString pathVar = wxGetenv(wxT("AUDACITY_PATH")); - if (pathVar != wxT("")) - AddMultiPathsToPathList(pathVar, audacityPathList); - AddUniquePathToPathList(::wxGetCwd(), audacityPathList); - -#ifdef AUDACITY_NAME - AddUniquePathToPathList(wxString::Format(wxT("%s/.%s-files"), - home.c_str(), wxT(AUDACITY_NAME)), - audacityPathList); - AddUniquePathToPathList(wxString::Format(wxT("%s/share/%s"), - wxT(INSTALL_PREFIX), wxT(AUDACITY_NAME)), - audacityPathList); - AddUniquePathToPathList(wxString::Format(wxT("%s/share/doc/%s"), - wxT(INSTALL_PREFIX), wxT(AUDACITY_NAME)), - audacityPathList); -#else //AUDACITY_NAME - AddUniquePathToPathList(wxString::Format(wxT("%s/.audacity-files"), - home.c_str()), - audacityPathList); - AddUniquePathToPathList(wxString::Format(wxT("%s/share/audacity"), - wxT(INSTALL_PREFIX)), - audacityPathList); - AddUniquePathToPathList(wxString::Format(wxT("%s/share/doc/audacity"), - wxT(INSTALL_PREFIX)), - audacityPathList); -#endif //AUDACITY_NAME - - AddUniquePathToPathList(wxString::Format(wxT("%s/share/locale"), - wxT(INSTALL_PREFIX)), - audacityPathList); - - AddUniquePathToPathList(wxString::Format(wxT("./locale")), - audacityPathList); - -#endif //__WXGTK__ - - wxFileName tmpFile; - tmpFile.AssignTempFileName(wxT("nn")); - wxString tmpDirLoc = tmpFile.GetPath(wxPATH_GET_VOLUME); - ::wxRemoveFile(tmpFile.GetFullPath()); - - // On Mac and Windows systems, use the directory which contains Audacity. -#ifdef __WXMSW__ - // On Windows, the path to the Audacity program is in argv[0] - wxString progPath = wxPathOnly(argv[0]); - AddUniquePathToPathList(progPath, audacityPathList); - AddUniquePathToPathList(progPath+wxT("\\Languages"), audacityPathList); - - defaultTempDir.Printf(wxT("%s\\audacity_temp"), - tmpDirLoc.c_str()); -#endif //__WXWSW__ - -#ifdef __WXMAC__ - // On Mac OS X, the path to the Audacity program is in argv[0] - wxString progPath = wxPathOnly(argv[0]); - - AddUniquePathToPathList(progPath, audacityPathList); - // If Audacity is a "bundle" package, then the root directory is - // the great-great-grandparent of the directory containing the executable. - AddUniquePathToPathList(progPath+wxT("/../../../"), audacityPathList); - - // These allow for searching the "bundle" - AddUniquePathToPathList(progPath+wxT("/../"), audacityPathList); - AddUniquePathToPathList(progPath+wxT("/../Resources"), audacityPathList); - - defaultTempDir.Printf(wxT("%s/audacity-%s"), - tmpDirLoc.c_str(), - wxGetUserId().c_str()); -#endif //__WXMAC__ - - // Define languanges for which we have translations, but that are not yet - // supported by wxWidgets. - // - // TODO: The whole Language initialization really need to be reworked. - // It's all over the place. -#if !wxCHECK_VERSION(3, 0, 1) - for (size_t i = 0, cnt = WXSIZEOF(userLangs); i < cnt; i++) - { - wxLocale::AddLanguage(userLangs[i]); - } -#endif - - // Initialize preferences and language - InitPreferences(); - - #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) && !defined(__CYGWIN__) - this->AssociateFileTypes(); - #endif - - // TODO - read the number of files to store in history from preferences - mRecentFiles = new FileHistory(ID_RECENT_LAST - ID_RECENT_FIRST + 1, ID_RECENT_CLEAR); - mRecentFiles->Load(*gPrefs, wxT("RecentFiles")); - - theTheme.EnsureInitialised(); - - // AColor depends on theTheme. - AColor::Init(); - - // Init DirManager, which initializes the temp directory - // If this fails, we must exit the program. - if (!InitTempDir()) { - FinishPreferences(); - return false; - } - -//<<<< Try to avoid dialogs before this point. -// The reason is that InitTempDir starts the single instance checker. -// If we're waiitng in a dialog before then we can very easily -// start multiple instances, defeating the single instance checker. - - - - - //JKC We'd like to initialise the module manager WHILE showing the splash screen. - //Can't in wx3.0.1 as MultiDialog interacts poorly with the splash screen. So we do it before. - //TODO: Find out why opening a multidialog wrecks the splash screen. - //best current guess is that it's something to do with doing a DoModal this early - //in the program. - - // Initialize the CommandHandler - InitCommandHandler(); - - // Initialize the PluginManager - PluginManager::Get().Initialize(); - - // Initialize the ModuleManager, including loading found modules - ModuleManager::Get().Initialize(*mCmdHandler); - - // Parse command line and handle options that might require - // immediate exit...no need to initialize all of the audio - // stuff to display the version string. - wxCmdLineParser *parser = ParseCommandLine(); - if (!parser) - { - delete parser; - - // Either user requested help or a parsing error occured - exit(1); - } - - if (parser->Found(wxT("v"))) - { - delete parser; - - wxFprintf(stderr, wxT("Audacity v%s\n"), AUDACITY_VERSION_STRING); - exit(0); - } - - long lval; - if (parser->Found(wxT("b"), &lval)) - { - if (lval < 256 || lval > 100000000) - { - delete parser; - - wxPrintf(_("Block size must be within 256 to 100000000\n")); - exit(1); - } - - Sequence::SetMaxDiskBlockSize(lval); - } - - wxString fileName; - if (parser->Found(wxT("d"), &fileName)) - { - AutoSaveFile asf; - if (asf.Decode(fileName)) - { - wxPrintf(_("File decoded successfully\n")); - } - else - { - wxPrintf(_("Decoding failed\n")); - } - exit(1); - } - -// No Splash screen on wx3 whislt we sort out the problem -// with showing a dialog AND a splash screen during inits. -#if !wxCHECK_VERSION(3, 0, 0) - // BG: Create a temporary window to set as the top window - wxImage logoimage((const char **) AudacityLogoWithName_xpm); - logoimage.Rescale(logoimage.GetWidth() / 2, logoimage.GetHeight() / 2); - wxBitmap logo(logoimage); - - wxSplashScreen *temporarywindow = - new wxSplashScreen(logo, - wxSPLASH_CENTRE_ON_SCREEN | wxSPLASH_NO_TIMEOUT, - 0, - NULL, - wxID_ANY, - wxDefaultPosition, - wxDefaultSize, - wxSTAY_ON_TOP); - temporarywindow->SetTitle(_("Audacity is starting up...")); - SetTopWindow(temporarywindow); -#endif - - //JKC: Would like to put module loading here. - - // More initialization - - InitDitherers(); - InitAudioIO(); - -#ifdef __WXMAC__ - - // On the Mac, users don't expect a program to quit when you close the last window. - // Create a menubar that will show when all project windows are closed. - - wxMenu *fileMenu = new wxMenu(); - wxMenu *recentMenu = new wxMenu(); - fileMenu->Append(wxID_NEW, wxString(_("&New")) + wxT("\tCtrl+N")); - fileMenu->Append(wxID_OPEN, wxString(_("&Open...")) + wxT("\tCtrl+O")); - fileMenu->AppendSubMenu(recentMenu, _("Open &Recent...")); - fileMenu->Append(wxID_ABOUT, _("&About Audacity...")); - fileMenu->Append(wxID_PREFERENCES, wxString(_("&Preferences...")) + wxT("\tCtrl+,")); - - wxMenuBar *menuBar = new wxMenuBar(); - menuBar->Append(fileMenu, _("&File")); - - wxMenuBar::MacSetCommonMenuBar(menuBar); - - mRecentFiles->UseMenu(recentMenu); - mRecentFiles->AddFilesToMenu(recentMenu); - - // This invisibale frame will be the "root" of all other frames and will - // become the active frame when no projects are open. - gParentFrame = new wxFrame(NULL, -1, wxEmptyString, wxPoint(0, 0), wxSize(0, 0), 0); - -#endif //__WXMAC__ - - SetExitOnFrameDelete(true); - - - AudacityProject *project = CreateNewAudacityProject(); - mCmdHandler->SetProject(project); - wxWindow * pWnd = MakeHijackPanel() ; - if( pWnd ) - { - project->Show( false ); - pWnd->SetParent( project ); - SetTopWindow(pWnd); - pWnd->Show( true ); - } - - -#if !wxCHECK_VERSION(3, 0, 0) - temporarywindow->Show(false); - delete temporarywindow; -#endif - - if( project->mShowSplashScreen ) - project->OnHelpWelcome(); - - // JKC 10-Sep-2007: Enable monitoring from the start. - // (recommended by lprod.org). - // Monitoring stops again after any - // PLAY or RECORD completes. - // So we also call StartMonitoring when STOP is called. - project->MayStartMonitoring(); - - #ifdef USE_FFMPEG - FFmpegStartup(); - #endif - - Importer::Get().Initialize(); - - // - // Auto-recovery - // - bool didRecoverAnything = false; - if (!ShowAutoRecoveryDialogIfNeeded(&project, &didRecoverAnything)) - { - // Important: Prevent deleting any temporary files! - DirManager::SetDontDeleteTempFiles(); - delete parser; - QuitAudacity(true); - return false; - } - - // - // Remainder of command line parsing, but only if we didn't recover - // - if (!didRecoverAnything) - { - if (parser->Found(wxT("t"))) - { - delete parser; - - RunBenchmark(NULL); - return false; - } - - for (size_t i = 0, cnt = parser->GetParamCount(); i < cnt; i++) - { - MRUOpen(parser->GetParam(i)); - } - } - - delete parser; - - gInited = true; - - ModuleManager::Get().Dispatch(AppInitialized); - - mWindowRectAlreadySaved = FALSE; - - mTimer.SetOwner(this, kAudacityAppTimerID); - mTimer.Start(200); - - return TRUE; -} - -void AudacityApp::InitCommandHandler() -{ - mCmdHandler = new CommandHandler(*this); - //SetNextHandler(mCmdHandler); -} - -void AudacityApp::DeInitCommandHandler() -{ - wxASSERT(NULL != mCmdHandler); - delete mCmdHandler; - mCmdHandler = NULL; -} - -// AppCommandEvent callback - just pass the event on to the CommandHandler -void AudacityApp::OnReceiveCommand(AppCommandEvent &event) -{ - wxASSERT(NULL != mCmdHandler); - mCmdHandler->OnReceiveCommand(event); -} - -bool AudacityApp::InitTempDir() -{ - // We need to find a temp directory location. - - wxString tempFromPrefs = gPrefs->Read(wxT("/Directories/TempDir"), wxT("")); - wxString tempDefaultLoc = wxGetApp().defaultTempDir; - - wxString temp = wxT(""); - - #ifdef __WXGTK__ - if (tempFromPrefs.Length() > 0 && tempFromPrefs[0] != wxT('/')) - tempFromPrefs = wxT(""); - #endif - - // Stop wxWidgets from printing its own error messages - - wxLogNull logNo; - - // Try temp dir that was stored in prefs first - - if (tempFromPrefs != wxT("")) { - if (wxDirExists(tempFromPrefs)) - temp = tempFromPrefs; - else if (wxMkdir(tempFromPrefs, 0755)) - temp = tempFromPrefs; - } - - // If that didn't work, try the default location - - if (temp==wxT("") && tempDefaultLoc != wxT("")) { - if (wxDirExists(tempDefaultLoc)) - temp = tempDefaultLoc; - else if (wxMkdir(tempDefaultLoc, 0755)) - temp = tempDefaultLoc; - } - - // Check temp directory ownership on *nix systems only - #ifdef __UNIX__ - struct stat tempStatBuf; - if ( lstat(temp.mb_str(), &tempStatBuf) != 0 ) { - temp.clear(); - } - else { - if ( geteuid() != tempStatBuf.st_uid ) { - temp.clear(); - } - } - #endif - - if (temp == wxT("")) { - // Failed - wxMessageBox(_("Audacity could not find a place to store temporary files.\nPlease enter an appropriate directory in the preferences dialog.")); - - PrefsDialog dialog(NULL); - dialog.ShowTempDirPage(); - dialog.ShowModal(); - - wxMessageBox(_("Audacity is now going to exit. Please launch Audacity again to use the new temporary directory.")); - return false; - } - - // The permissions don't always seem to be set on - // some platforms. Hopefully this fixes it... - #ifdef __UNIX__ - chmod(OSFILENAME(temp), 0755); - #endif - - bool bSuccess = gPrefs->Write(wxT("/Directories/TempDir"), temp) && gPrefs->Flush(); - DirManager::SetTempDir(temp); - - // Make sure the temp dir isn't locked by another process. - if (!CreateSingleInstanceChecker(temp)) - return false; - - return bSuccess; -} - -// Return true if there are no other instances of Audacity running, -// false otherwise. -// -// Use "dir" for creating lockfiles (on OS X and Unix). - -bool AudacityApp::CreateSingleInstanceChecker(wxString dir) -{ - wxString name = wxString::Format(wxT("audacity-lock-%s"), wxGetUserId().c_str()); - mChecker = new wxSingleInstanceChecker(); - -#if defined(__UNIX__) - wxString sockFile(defaultTempDir + wxT("/.audacity.sock")); -#endif - - wxString runningTwoCopiesStr = _("Running two copies of Audacity simultaneously may cause\ndata loss or cause your system to crash.\n\n"); - - if (!mChecker->Create(name, dir)) { - // Error initializing the wxSingleInstanceChecker. We don't know - // whether there is another instance running or not. - - wxString prompt = - _("Audacity was not able to lock the temporary files directory.\nThis folder may be in use by another copy of Audacity.\n") + - runningTwoCopiesStr + - _("Do you still want to start Audacity?"); - int action = wxMessageBox(prompt, - _("Error Locking Temporary Folder"), - wxYES_NO | wxICON_EXCLAMATION, - NULL); - if (action == wxNO) { - delete mChecker; - return false; - } - } - else if ( mChecker->IsAnotherRunning() ) { - // Parse the command line to ensure correct syntax, but - // ignore options and only use the filenames, if any. - wxCmdLineParser *parser = ParseCommandLine(); - if (!parser) - { - // Complaints have already been made - return false; - } - -#if defined(__WXMSW__) - // On Windows, we attempt to make a connection - // to an already active Audacity. If successful, we send - // the first command line argument (the audio file name) - // to that Audacity for processing. - wxClient client; - - // We try up to 50 times since there's a small window - // where the server may not have been fully initialized. - for (int i = 0; i < 50; i++) - { - wxConnectionBase *conn = client.MakeConnection(wxEmptyString, IPC_APPL, IPC_TOPIC); - if (conn) - { - bool ok = false; - if (parser->GetParamCount() > 0) - { - // Send each parameter to existing Audacity - for (size_t i = 0, cnt = parser->GetParamCount(); i < cnt; i++) - { - ok = conn->Execute(parser->GetParam(i)); - } - } - else - { - // Send an empty string to force existing Audacity to front - ok = conn->Execute(wxEmptyString); - } - - delete conn; - - if (ok) - { - delete parser; - return false; - } - } - - wxMilliSleep(10); - } -#else - // On Unix-like machines, we use a local (file based) socket to - // send the first command line argument to an already running - // Audacity. - wxUNIXaddress addr; - addr.Filename(sockFile); - - // Setup the socket - wxSocketClient *sock = new wxSocketClient(); - sock->SetFlags(wxSOCKET_WAITALL); - - // We try up to 50 times since there's a small window - // where the server may not have been fully initialized. - for (int i = 0; i < 50; i++) - { - // Connect to the existing Audacity - sock->Connect(addr, true); - if (sock->IsConnected()) - { - for (size_t i = 0, cnt = parser->GetParamCount(); i < cnt; i++) - { - // Send the filename - wxString param = parser->GetParam(i); - sock->WriteMsg((const wxChar *) param.c_str(), (param.Len() + 1) * sizeof(wxChar)); - } - - sock->Destroy(); - delete parser; - return false; - } - - wxMilliSleep(100); - } - - sock->Destroy(); -#endif - // There is another copy of Audacity running. Force quit. - - wxString prompt = - _("The system has detected that another copy of Audacity is running.\n") + - runningTwoCopiesStr + - _("Use the New or Open commands in the currently running Audacity\nprocess to open multiple projects simultaneously.\n"); - wxMessageBox(prompt, _("Audacity is already running"), - wxOK | wxICON_ERROR); - delete parser; - delete mChecker; - return false; - } - -#if defined(__WXMSW__) - // Create the DDE IPC server - mIPCServ = new IPCServ(IPC_APPL); -#else - int mask = umask(077); - remove(OSFILENAME(sockFile)); - wxUNIXaddress addr; - addr.Filename(sockFile); - mIPCServ = new wxSocketServer(addr, wxSOCKET_NOWAIT); - umask(mask); - - if (!mIPCServ || !mIPCServ->IsOk()) - { - // TODO: Complain here - return false; - } - - mIPCServ->SetEventHandler(*this, ID_IPC_SERVER); - mIPCServ->SetNotify(wxSOCKET_CONNECTION_FLAG); - mIPCServ->Notify(true); -#endif - return true; -} - -#if defined(__UNIX__) -void AudacityApp::OnServerEvent(wxSocketEvent & evt) -{ - wxSocketBase *sock; - - // Accept all pending connection requests - do - { - sock = mIPCServ->Accept(false); - if (sock) - { - // Setup the socket - sock->SetEventHandler(*this, ID_IPC_SOCKET); - sock->SetNotify(wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG); - sock->Notify(true); - } - } while (sock); -} - -void AudacityApp::OnSocketEvent(wxSocketEvent & evt) -{ - wxSocketBase *sock = evt.GetSocket(); - - if (evt.GetSocketEvent() == wxSOCKET_LOST) - { - sock->Destroy(); - return; - } - - // Read the length of the filename and bail if we have a short read - wxChar name[PATH_MAX]; - sock->ReadMsg(&name, sizeof(name)); - if (!sock->Error()) - { - // Add the filename to the queue. It will be opened by - // the OnTimer() event when it is safe to do so. - ofqueue.Add(name); - } -} - -#endif - -wxCmdLineParser *AudacityApp::ParseCommandLine() -{ - wxCmdLineParser *parser = new wxCmdLineParser(argc, argv); - if (!parser) - { - return NULL; - } - - /*i18n-hint: This controls the number of bytes that Audacity will - * use when writing files to the disk */ - parser->AddOption(wxT("b"), wxT("blocksize"), _("set max disk block size in bytes"), - wxCMD_LINE_VAL_NUMBER); - - /*i18n-hint: This decodes an autosave file */ - parser->AddOption(wxT("d"), wxT("decode"), _("decode an autosave file"), - wxCMD_LINE_VAL_STRING); - - /*i18n-hint: This displays a list of available options */ - parser->AddSwitch(wxT("h"), wxT("help"), _("this help message"), - wxCMD_LINE_OPTION_HELP); - - /*i18n-hint: This runs a set of automatic tests on Audacity itself */ - parser->AddSwitch(wxT("t"), wxT("test"), _("run self diagnostics")); - - /*i18n-hint: This displays the Audacity version */ - parser->AddSwitch(wxT("v"), wxT("version"), _("display Audacity version")); - - /*i18n-hint: This is a list of one or more files that Audacity - * should open upon startup */ - parser->AddParam(_("audio or project file name"), - wxCMD_LINE_VAL_STRING, - wxCMD_LINE_PARAM_MULTIPLE | wxCMD_LINE_PARAM_OPTIONAL); - - // Run the parser - if (parser->Parse() == 0) - { - return parser; - } - - delete parser; - - return NULL; -} - -// static -void AudacityApp::AddUniquePathToPathList(wxString path, - wxArrayString &pathList) -{ - wxFileName pathNorm = path; - pathNorm.Normalize(); - path = pathNorm.GetFullPath(); - - for(unsigned int i=0; iClose(true); - } - else if (!gAudacityProjects[0]->Close()) { - gIsQuitting = false; - event.Veto(); - break; - } - } - } -} - -void AudacityApp::OnKeyDown(wxKeyEvent & event) -{ - // Not handled - event.Skip(true); - - // Make sure this event is destined for a project window - AudacityProject *prj = GetActiveProject(); - - // TODO: I don't know how it can happen, but it did on 2006-07-06. - // I was switching between apps fairly quickly so maybe that has something - // to do with it. - if (!prj) - return; - - if (prj->HandleKeyDown(event)) - event.Skip(false); -} - -void AudacityApp::OnChar(wxKeyEvent & event) -{ - // Not handled - event.Skip(true); - - // Make sure this event is destined for a project window - AudacityProject *prj = GetActiveProject(); - - // TODO: I don't know how it can happen, but it did on 2006-07-06. - // I was switching between apps fairly quickly so maybe that has something - // to do with it. - if (!prj) - return; - - if (prj->HandleChar(event)) - event.Skip(false); -} - -void AudacityApp::OnKeyUp(wxKeyEvent & event) -{ - // Not handled - event.Skip(true); - - // Make sure this event is destined for a project window - AudacityProject *prj = GetActiveProject(); - - // TODO: I don't know how it can happen, but it did on 2006-07-06. - // I was switching between apps fairly quickly so maybe that has something - // to do with it. - if (!prj) - return; - - if (prj != wxGetTopLevelParent(wxWindow::FindFocus())) - return; - - if (prj->HandleKeyUp(event)) - event.Skip(false); -} - -void AudacityApp::AddFileToHistory(const wxString & name) -{ - mRecentFiles->AddFileToHistory(name); -} - -int AudacityApp::OnExit() -{ - gIsQuitting = true; - while(Pending()) - { - Dispatch(); - } - - Importer::Get().Terminate(); - - if(gPrefs) - { - bool bFalse = false; - //Should we change the commands.cfg location next startup? - if(gPrefs->Read(wxT("/QDeleteCmdCfgLocation"), &bFalse)) - { - gPrefs->DeleteEntry(wxT("/QDeleteCmdCfgLocation")); - gPrefs->Write(wxT("/DeleteCmdCfgLocation"), true); - gPrefs->Flush(); - } - } - - DeInitCommandHandler(); - - mRecentFiles->Save(*gPrefs, wxT("RecentFiles")); - delete mRecentFiles; - - FinishPreferences(); - -#ifdef USE_FFMPEG - DropFFmpegLibs(); -#endif - - DeinitFFT(); - BlockFile::Deinit(); - - DeinitAudioIO(); - - // Terminate the PluginManager (must be done before deleting the locale) - PluginManager::Get().Terminate(); - - // Done with plugins and modules - PluginManager::Destroy(); - ModuleManager::Destroy(); - - if (mLocale) - delete mLocale; - - if (mIPCServ) - { -#if defined(__UNIX__) - wxUNIXaddress addr; - if (mIPCServ->GetLocal(addr)) - { - remove(OSFILENAME(addr.Filename())); - } -#endif - delete mIPCServ; - } - - if (mChecker) - delete mChecker; - - return 0; -} - -// The following five methods are currently only used on Mac OS, -// where it's possible to have a menu bar but no windows open. -// It doesn't hurt any other platforms, though. - -// ...That is, as long as you check to see if no windows are open -// before executing the stuff. -// To fix this, check to see how many project windows are open, -// and skip the event unless none are open (which should only happen -// on the Mac, at least currently.) - -void AudacityApp::OnMenuAbout(wxCommandEvent & event) -{ - // This function shadows a similar function - // in Menus.cpp, but should only be used on the Mac platform - // when no project windows are open. This check assures that - // this happens, and enable the same code to be present on - // all platforms. - if(gAudacityProjects.GetCount() == 0) { - AboutDialog dlog(NULL); - dlog.ShowModal(); - } - else - event.Skip(); -} - -void AudacityApp::OnMenuNew(wxCommandEvent & event) -{ - // This function shadows a similar function - // in Menus.cpp, but should only be used on the Mac platform - // when no project windows are open. This check assures that - // this happens, and enable the same code to be present on - // all platforms. - - if(gAudacityProjects.GetCount() == 0) - CreateNewAudacityProject(); - else - event.Skip(); -} - - -void AudacityApp::OnMenuOpen(wxCommandEvent & event) -{ - // This function shadows a similar function - // in Menus.cpp, but should only be used on the Mac platform - // when no project windows are open. This check assures that - // this happens, and enable the same code to be present on - // all platforms. - - - if(gAudacityProjects.GetCount() == 0) - AudacityProject::OpenFiles(NULL); - else - event.Skip(); - - -} - -void AudacityApp::OnMenuPreferences(wxCommandEvent & event) -{ - // This function shadows a similar function - // in Menus.cpp, but should only be used on the Mac platform - // when no project windows are open. This check assures that - // this happens, and enable the same code to be present on - // all platforms. - - if(gAudacityProjects.GetCount() == 0) { - PrefsDialog dialog(NULL /* parent */ ); - dialog.ShowModal(); - } - else - event.Skip(); - -} - -void AudacityApp::OnMenuExit(wxCommandEvent & event) -{ - // This function shadows a similar function - // in Menus.cpp, but should only be used on the Mac platform - // when no project windows are open. This check assures that - // this happens, and enable the same code to be present on - // all platforms. - - // LL: Removed "if" to allow closing based on final project count. - // if(gAudacityProjects.GetCount() == 0) - QuitAudacity(); - - // LL: Veto quit if projects are still open. This can happen - // if the user selected Cancel in a Save dialog. - event.Skip(gAudacityProjects.GetCount() == 0); - -} - -//BG: On Windows, associate the aup file type with Audacity -/* We do this in the Windows installer now, - to avoid issues where user doesn't have admin privileges, but - in case that didn't work, allow the user to decide at startup. - - //v Should encapsulate this & allow access from Prefs, too, - // if people want to manually change associations. -*/ -#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) && !defined(__CYGWIN__) -void AudacityApp::AssociateFileTypes() -{ - wxRegKey associateFileTypes; - associateFileTypes.SetName(wxT("HKCR\\.AUP")); - bool bKeyExists = associateFileTypes.Exists(); - if (!bKeyExists) { - // Not at HKEY_CLASSES_ROOT. Try HKEY_CURRENT_USER. - associateFileTypes.SetName(wxT("HKCU\\Software\\Classes\\.AUP")); - bKeyExists = associateFileTypes.Exists(); - } - if (!bKeyExists) { - // File types are not currently associated. - // Check pref in case user has already decided against it. - bool bWantAssociateFiles = true; - if (!gPrefs->Read(wxT("/WantAssociateFiles"), &bWantAssociateFiles) || - bWantAssociateFiles) { - // Either there's no pref or user does want associations - // and they got stepped on, so ask. - int wantAssoc = - wxMessageBox( - _("Audacity project (.AUP) files are not currently \nassociated with Audacity. \n\nAssociate them, so they open on double-click?"), - _("Audacity Project Files"), - wxYES_NO | wxICON_QUESTION); - if (wantAssoc == wxYES) { - gPrefs->Write(wxT("/WantAssociateFiles"), true); - gPrefs->Flush(); - - wxString root_key; - - root_key = wxT("HKCU\\Software\\Classes\\"); - associateFileTypes.SetName(root_key + wxT(".AUP")); // Start again with HKEY_CLASSES_ROOT. - if (!associateFileTypes.Create(true)) { - // Not at HKEY_CLASSES_USER. Try HKEY_CURRENT_ROOT. - root_key = wxT("HKCR\\"); - associateFileTypes.SetName(root_key + wxT(".AUP")); - if (!associateFileTypes.Create(true)) { - // Actually, can't create keys. Empty root_key to flag failure. - root_key.Empty(); - } - } - if (root_key.IsEmpty()) { - //v Warn that we can't set keys. Ask whether to set pref for no retry? - } else { - associateFileTypes = wxT("Audacity.Project"); // Finally set value for .AUP key - - associateFileTypes.SetName(root_key + wxT("Audacity.Project")); - if(!associateFileTypes.Exists()) { - associateFileTypes.Create(true); - associateFileTypes = wxT("Audacity Project File"); - } - - associateFileTypes.SetName(root_key + wxT("Audacity.Project\\shell")); - if(!associateFileTypes.Exists()) { - associateFileTypes.Create(true); - associateFileTypes = wxT(""); - } - - associateFileTypes.SetName(root_key + wxT("Audacity.Project\\shell\\open")); - if(!associateFileTypes.Exists()) { - associateFileTypes.Create(true); - } - - associateFileTypes.SetName(root_key + wxT("Audacity.Project\\shell\\open\\command")); - wxString tmpRegAudPath; - if(associateFileTypes.Exists()) { - tmpRegAudPath = wxString(associateFileTypes).Lower(); - } - if (!associateFileTypes.Exists() || - (tmpRegAudPath.Find(wxT("audacity.exe")) >= 0)) { - associateFileTypes.Create(true); - associateFileTypes = (wxString)argv[0] + (wxString)wxT(" \"%1\""); - } - -#if 0 - // These can be use later to support more startup messages - // like maybe "Import into existing project" or some such. - // Leaving here for an example... - associateFileTypes.SetName(root_key + wxT("Audacity.Project\\shell\\open\\ddeexec")); - if(!associateFileTypes.Exists()) { - associateFileTypes.Create(true); - associateFileTypes = wxT("%1"); - } - - associateFileTypes.SetName(root_key + wxT("Audacity.Project\\shell\\open\\ddeexec\\Application")); - if(!associateFileTypes.Exists()) { - associateFileTypes.Create(true); - associateFileTypes = IPC_APPL; - } - - associateFileTypes.SetName(root_key + wxT("Audacity.Project\\shell\\open\\ddeexec\\Topic")); - if(!associateFileTypes.Exists()) { - associateFileTypes.Create(true); - associateFileTypes = IPC_TOPIC; - } -#endif - } - } else { - // User said no. Set a pref so we don't keep asking. - gPrefs->Write(wxT("/WantAssociateFiles"), false); - gPrefs->Flush(); - } - } - } -} -#endif - +/********************************************************************** + + Audacity: A Digital Audio Editor + + AudacityApp.cpp + + Dominic Mazzoni + +******************************************************************//** + +\class AudacityApp +\brief AudacityApp is the 'main' class for Audacity + +It handles initialization and termination by subclassing wxApp. + +*//*******************************************************************/ + +#if 0 +// This may be used to debug memory leaks. +// See: Visual Leak Dectector @ http://vld.codeplex.com/ +#include +#endif + +#include "Audacity.h" // This should always be included first + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#ifdef __WXGTK__ +#include +#endif + +// chmod, lstat, geteuid +#ifdef __UNIX__ +#include +#include +#include +#endif + +#include "AudacityApp.h" + +#include "AudacityLogger.h" +#include "AboutDialog.h" +#include "AColor.h" +#include "AudioIO.h" +#include "Benchmark.h" +#include "DirManager.h" +#include "commands/CommandHandler.h" +#include "commands/AppCommandEvent.h" +#include "effects/Contrast.h" +#include "widgets/ASlider.h" +#include "FFmpeg.h" +#include "Internat.h" +#include "LangChoice.h" +#include "Languages.h" +#include "PluginManager.h" +#include "Prefs.h" +#include "Project.h" +#include "Screenshot.h" +#include "Sequence.h" +#include "WaveTrack.h" +#include "Internat.h" +#include "prefs/PrefsDialog.h" +#include "Theme.h" +#include "PlatformCompatibility.h" +#include "FileNames.h" +#include "AutoRecovery.h" +#include "SplashDialog.h" +#include "FFT.h" +#include "BlockFile.h" +#include "ondemand/ODManager.h" +#include "commands/Keyboard.h" +#include "widgets/ErrorDialog.h" + +//temporarilly commented out till it is added to all projects +//#include "Profiler.h" + +#include "ModuleManager.h" + +#include "import/Import.h" + +#if defined(EXPERIMENTAL_CRASH_REPORT) +#include +#include +#include +#endif + +#ifdef EXPERIMENTAL_SCOREALIGN +#include "effects/ScoreAlignDialog.h" +#endif + +#if 0 +#ifdef _DEBUG + #ifdef _MSC_VER + #undef THIS_FILE + static char*THIS_FILE= __FILE__; + #define new new(_NORMAL_BLOCK, THIS_FILE, __LINE__) + #endif +#endif +#endif + +// Windows specific linker control...only needed once so +// this is a good place (unless we want to add another file). +#if defined(__WXMSW__) +//#if wxCHECK_VERSION(3, 0, 2) && !wxCHECK_VERSION(3, 1, 0) +#include +//#endif +// These lines ensure that Audacity gets WindowsXP themes. +// Without them we get the old-style Windows98/2000 look under XP. +# if !defined(__WXWINCE__) +# pragma comment(linker, "\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='X86' publicKeyToken='6595b64144ccf1df'\"") +# endif + +// These lines allows conditional inclusion of the various libraries +// that Audacity can use. + +# if defined(USE_LIBFLAC) +# pragma comment(lib, "libflac++") +# pragma comment(lib, "libflac") +# endif + +# if defined(USE_LIBID3TAG) +# pragma comment(lib, "libid3tag") +# endif + +# if defined(USE_LIBMAD) +# pragma comment(lib, "libmad") +# endif + +# if defined(USE_LIBTWOLAME) +# pragma comment(lib, "twolame") +# endif + +# if defined(USE_LIBVORBIS) +# pragma comment(lib, "libogg") +# pragma comment(lib, "libvorbis") +# endif + +# if defined(USE_LV2) +# pragma comment(lib, "lv2") +# endif + +# if defined(USE_MIDI) +# pragma comment(lib, "portsmf") +# endif + +# if defined(EXPERIMENTAL_MIDI_OUT) +# pragma comment(lib, "portmidi") +# endif + +# if defined(EXPERIMENTAL_SCOREALIGN) +# pragma comment(lib, "libscorealign") +# endif + +# if defined(USE_NYQUIST) +# pragma comment(lib, "libnyquist") +# endif + +# if defined(USE_PORTMIXER) +# pragma comment(lib, "portmixer") +# endif + +# if defined(USE_SBSMS) +# pragma comment(lib, "sbsms") +# endif + +# if defined(USE_SOUNDTOUCH) +# pragma comment(lib, "soundtouch") +# endif + +# if defined(USE_VAMP) +# pragma comment(lib, "libvamp") +# endif + +# if defined(__WXDEBUG__) +# define D "d" +# else +# define D "" +# endif +# if wxCHECK_VERSION(3, 1, 0) +# define V "31" +# elif wxCHECK_VERSION(3, 0, 0) +# define V "30" +# else +# define V "28" +# endif + +# if defined(EXPERIMENTAL_CRASH_REPORT) +# pragma comment(lib, "wxmsw" V "u" D "_qa") +# endif +# pragma comment(lib, "wxbase" V "u" D) +# pragma comment(lib, "wxbase" V "u" D "_net.lib") +# pragma comment(lib, "wxmsw" V "u" D "_adv.lib") +# pragma comment(lib, "wxmsw" V "u" D "_core.lib") +# pragma comment(lib, "wxmsw" V "u" D "_html.lib") +# pragma comment(lib, "wxpng" D) +# pragma comment(lib, "wxzlib" D) +# pragma comment(lib, "wxjpeg" D) +# pragma comment(lib, "wxtiff" D) + +# undef V +# undef D + +#endif //(__WXMSW__) + +#include "../images/AudacityLogoWithName.xpm" + +//////////////////////////////////////////////////////////// +/// Custom events +//////////////////////////////////////////////////////////// + +DEFINE_EVENT_TYPE(EVT_OPEN_AUDIO_FILE); +DEFINE_EVENT_TYPE(EVT_CAPTURE_KEYBOARD); +DEFINE_EVENT_TYPE(EVT_RELEASE_KEYBOARD); +DEFINE_EVENT_TYPE(EVT_CAPTURE_KEY); + +#ifdef __WXGTK__ +static void wxOnAssert(const wxChar *fileName, int lineNumber, const wxChar *msg) +{ + if (msg) + printf("ASSERTION FAILED: %s\n%s: %d\n", (const char *)wxString(msg).mb_str(), (const char *)wxString(fileName).mb_str(), lineNumber); + else + printf("ASSERTION FAILED!\n%s: %d\n", (const char *)wxString(fileName).mb_str(), lineNumber); + + // Force core dump + int *i = 0; + if (*i) + exit(1); + + exit(0); +} +#endif + +static wxFrame *gParentFrame = NULL; + +static bool gInited = false; +bool gIsQuitting = false; + +void QuitAudacity(bool bForce) +{ + if (gIsQuitting) + return; + + gIsQuitting = true; + + // Try to close each open window. If the user hits Cancel + // in a Save Changes dialog, don't continue. + // BG: unless force is true + + // BG: Are there any projects open? + //- if (!gAudacityProjects.IsEmpty()) +/*start+*/ + if (gAudacityProjects.IsEmpty()) + { +#ifdef __WXMAC__ + AudacityProject::DeleteClipboard(); +#endif + } + else +/*end+*/ + { + SaveWindowSize(); + while (gAudacityProjects.Count()) + { + if (bForce) + { + gAudacityProjects[0]->Close(true); + } + else + { + if (!gAudacityProjects[0]->Close()) + { + gIsQuitting = false; + return; + } + } + } + } + + LWSlider::DeleteSharedTipPanel(); + + ModuleManager::Get().Dispatch(AppQuiting); + + if (gParentFrame) + gParentFrame->Destroy(); + gParentFrame = NULL; + +#ifdef EXPERIMENTAL_SCOREALIGN + CloseScoreAlignDialog(); +#endif + CloseScreenshotTools(); + + //release ODManager Threads + ODManager::Quit(); + + //print out profile if we have one by deleting it + //temporarilly commented out till it is added to all projects + //delete Profiler::Instance(); + + //delete the static lock for audacity projects + AudacityProject::DeleteAllProjectsDeleteLock(); + + //remove our logger + delete wxLog::SetActiveTarget(NULL); + + if (bForce) + { + wxExit(); + } +} + +void QuitAudacity() +{ + QuitAudacity(false); +} + +void SaveWindowSize() +{ + if (wxGetApp().GetWindowRectAlreadySaved()) + { + return; + } + bool validWindowForSaveWindowSize = FALSE; + AudacityProject * validProject = NULL; + bool foundIconizedProject = FALSE; + size_t numProjects = gAudacityProjects.Count(); + for (size_t i = 0; i < numProjects; i++) + { + if (!gAudacityProjects[i]->IsIconized()) { + validWindowForSaveWindowSize = TRUE; + validProject = gAudacityProjects[i]; + i = numProjects; + } + else + foundIconizedProject = TRUE; + + } + if (validWindowForSaveWindowSize) + { + wxRect windowRect = validProject->GetRect(); + wxRect normalRect = validProject->GetNormalizedWindowState(); + bool wndMaximized = validProject->IsMaximized(); + gPrefs->Write(wxT("/Window/X"), windowRect.GetX()); + gPrefs->Write(wxT("/Window/Y"), windowRect.GetY()); + gPrefs->Write(wxT("/Window/Width"), windowRect.GetWidth()); + gPrefs->Write(wxT("/Window/Height"), windowRect.GetHeight()); + gPrefs->Write(wxT("/Window/Maximized"), wndMaximized); + gPrefs->Write(wxT("/Window/Normal_X"), normalRect.GetX()); + gPrefs->Write(wxT("/Window/Normal_Y"), normalRect.GetY()); + gPrefs->Write(wxT("/Window/Normal_Width"), normalRect.GetWidth()); + gPrefs->Write(wxT("/Window/Normal_Height"), normalRect.GetHeight()); + gPrefs->Write(wxT("/Window/Iconized"), FALSE); + } + else + { + if (foundIconizedProject) { + validProject = gAudacityProjects[0]; + bool wndMaximized = validProject->IsMaximized(); + wxRect normalRect = validProject->GetNormalizedWindowState(); + // store only the normal rectangle because the itemized rectangle + // makes no sense for an opening project window + gPrefs->Write(wxT("/Window/X"), normalRect.GetX()); + gPrefs->Write(wxT("/Window/Y"), normalRect.GetY()); + gPrefs->Write(wxT("/Window/Width"), normalRect.GetWidth()); + gPrefs->Write(wxT("/Window/Height"), normalRect.GetHeight()); + gPrefs->Write(wxT("/Window/Maximized"), wndMaximized); + gPrefs->Write(wxT("/Window/Normal_X"), normalRect.GetX()); + gPrefs->Write(wxT("/Window/Normal_Y"), normalRect.GetY()); + gPrefs->Write(wxT("/Window/Normal_Width"), normalRect.GetWidth()); + gPrefs->Write(wxT("/Window/Normal_Height"), normalRect.GetHeight()); + gPrefs->Write(wxT("/Window/Iconized"), TRUE); + } + else { + // this would be a very strange case that might possibly occur on the Mac + // Audacity would have to be running with no projects open + // in this case we are going to write only the default values + wxRect defWndRect; + GetDefaultWindowRect(&defWndRect); + gPrefs->Write(wxT("/Window/X"), defWndRect.GetX()); + gPrefs->Write(wxT("/Window/Y"), defWndRect.GetY()); + gPrefs->Write(wxT("/Window/Width"), defWndRect.GetWidth()); + gPrefs->Write(wxT("/Window/Height"), defWndRect.GetHeight()); + gPrefs->Write(wxT("/Window/Maximized"), FALSE); + gPrefs->Write(wxT("/Window/Normal_X"), defWndRect.GetX()); + gPrefs->Write(wxT("/Window/Normal_Y"), defWndRect.GetY()); + gPrefs->Write(wxT("/Window/Normal_Width"), defWndRect.GetWidth()); + gPrefs->Write(wxT("/Window/Normal_Height"), defWndRect.GetHeight()); + gPrefs->Write(wxT("/Window/Iconized"), FALSE); + } + } + gPrefs->Flush(); + wxGetApp().SetWindowRectAlreadySaved(TRUE); +} + +#if defined(__WXGTK__) && defined(HAVE_GTK) + +/////////////////////////////////////////////////////////////////////////////// +// Provide the ability to receive notification from the session manager +// when the user is logging out or shutting down. +// +// Most of this was taken from nsNativeAppSupportUnix.cpp from Mozilla. +/////////////////////////////////////////////////////////////////////////////// + +// TODO: May need updating. Is this code too obsolete (relying on Gnome2 so's) to be +// worth keeping anymore? +// CB suggests we use libSM directly ref: +// http://www.x.org/archive/X11R7.7/doc/libSM/SMlib.html#The_Save_Yourself_Callback + +#include +/* There is a conflict between the type names used in Glib >= 2.21 and those in + * wxGTK (http://trac.wxwidgets.org/ticket/10883) + * Happily we can avoid the hack, as we only need some of the headers, not + * the full GTK headers + */ +#include + +typedef struct _GnomeProgram GnomeProgram; +typedef struct _GnomeModuleInfo GnomeModuleInfo; +typedef struct _GnomeClient GnomeClient; + +typedef enum +{ + GNOME_SAVE_GLOBAL, + GNOME_SAVE_LOCAL, + GNOME_SAVE_BOTH +} GnomeSaveStyle; + +typedef enum +{ + GNOME_INTERACT_NONE, + GNOME_INTERACT_ERRORS, + GNOME_INTERACT_ANY +} GnomeInteractStyle; + +typedef enum +{ + GNOME_DIALOG_ERROR, + GNOME_DIALOG_NORMAL +} GnomeDialogType; + +typedef GnomeProgram * (*_gnome_program_init_fn)(const char *, + const char *, + const GnomeModuleInfo *, + int, + char **, + const char *, + ...); +typedef const GnomeModuleInfo * (*_libgnomeui_module_info_get_fn)(); +typedef GnomeClient * (*_gnome_master_client_fn)(void); +typedef void (*GnomeInteractFunction)(GnomeClient *, + gint, + GnomeDialogType, + gpointer); +typedef void (*_gnome_client_request_interaction_fn)(GnomeClient *, + GnomeDialogType, + GnomeInteractFunction, + gpointer); +typedef void (*_gnome_interaction_key_return_fn)(gint, gboolean); + +static _gnome_client_request_interaction_fn gnome_client_request_interaction; +static _gnome_interaction_key_return_fn gnome_interaction_key_return; + +static void interact_cb(GnomeClient *client, + gint key, + GnomeDialogType type, + gpointer data) +{ + wxCloseEvent e(wxEVT_QUERY_END_SESSION, wxID_ANY); + e.SetEventObject(&wxGetApp()); + e.SetCanVeto(true); + + wxGetApp().ProcessEvent(e); + + gnome_interaction_key_return(key, e.GetVeto()); +} + +static gboolean save_yourself_cb(GnomeClient *client, + gint phase, + GnomeSaveStyle style, + gboolean shutdown, + GnomeInteractStyle interact, + gboolean fast, + gpointer user_data) +{ + if (!shutdown || interact != GNOME_INTERACT_ANY) { + return TRUE; + } + + if (gAudacityProjects.IsEmpty()) { + return TRUE; + } + + gnome_client_request_interaction(client, + GNOME_DIALOG_NORMAL, + interact_cb, + NULL); + + return TRUE; +} + +class GnomeShutdown +{ + public: + GnomeShutdown() + { + mArgv[0] = strdup("Audacity"); + + mGnomeui = dlopen("libgnomeui-2.so.0", RTLD_NOW); + if (!mGnomeui) { + return; + } + + mGnome = dlopen("libgnome-2.so.0", RTLD_NOW); + if (!mGnome) { + return; + } + + _gnome_program_init_fn gnome_program_init = (_gnome_program_init_fn) + dlsym(mGnome, "gnome_program_init"); + _libgnomeui_module_info_get_fn libgnomeui_module_info_get = (_libgnomeui_module_info_get_fn) + dlsym(mGnomeui, "libgnomeui_module_info_get"); + _gnome_master_client_fn gnome_master_client = (_gnome_master_client_fn) + dlsym(mGnomeui, "gnome_master_client"); + + gnome_client_request_interaction = (_gnome_client_request_interaction_fn) + dlsym(mGnomeui, "gnome_client_request_interaction"); + gnome_interaction_key_return = (_gnome_interaction_key_return_fn) + dlsym(mGnomeui, "gnome_interaction_key_return"); + + + if (!gnome_program_init || !libgnomeui_module_info_get) { + return; + } + + gnome_program_init(mArgv[0], + "1.0", + libgnomeui_module_info_get(), + 1, + mArgv, + NULL); + + mClient = gnome_master_client(); + if (mClient == NULL) { + return; + } + + g_signal_connect(mClient, "save-yourself", G_CALLBACK(save_yourself_cb), NULL); + } + + virtual ~GnomeShutdown() + { + // Do not dlclose() the libraries here lest you want segfaults... + + free(mArgv[0]); + } + + private: + + char *mArgv[1]; + void *mGnomeui; + void *mGnome; + GnomeClient *mClient; +}; + +// This variable exists to call the constructor and +// connect a signal for the 'save-yourself' message. +GnomeShutdown GnomeShutdownInstance; + +#endif + +// Where drag/drop or "Open With" filenames get stored until +// the timer routine gets around to picking them up. +static wxArrayString ofqueue; + +// +// DDE support for opening multiple files with one instance +// of Audacity. +// + +#define IPC_APPL wxT("audacity") +#define IPC_TOPIC wxT("System") + +class IPCConn : public wxConnection +{ +public: + IPCConn() + : wxConnection() + { + }; + + ~IPCConn() + { + }; + + bool OnExec(const wxString & WXUNUSED(topic), + const wxString & data) + { + // Add the filename to the queue. It will be opened by + // the OnTimer() event when it is safe to do so. + ofqueue.Add(data); + + return true; + } + +#if !wxCHECK_VERSION(3, 0, 0) + bool OnExecute(const wxString & topic, + wxChar *data, + int WXUNUSED(size), + wxIPCFormat WXUNUSED(format)) + { + return OnExec(topic, data); + } +#endif +}; + +class IPCServ : public wxServer +{ +public: + IPCServ(const wxString & appl) + : wxServer() + { + Create(appl); + }; + + ~IPCServ() + { + }; + + wxConnectionBase *OnAcceptConnection(const wxString & topic) + { + if (topic != IPC_TOPIC) { + return NULL; + } + + return new IPCConn(); + }; +}; + +#if !defined(__WXMAC__) && !defined(__WXMSW__) +IMPLEMENT_APP(AudacityApp) +/* make the application class known to wxWidgets for dynamic construction */ +#endif + +#if defined(__WXMAC__) || defined(__WXMSW__) +// This should be removed when Lame and FFmpeg support is converted +// from loadable libraries to commands. +// +// The purpose of this is to give the user more control over where libraries +// such as Lame and FFmpeg get loaded from. +// +// Since absolute pathnames are used when loading these libraries, the normal search +// path would be DYLD_LIBRARY_PATH, absolute path, DYLD_FALLBACK_LIBRARY_PATH. This +// means that DYLD_LIBRARY_PATH can override what the user actually wants. +// +// So, we simply clear DYLD_LIBRARY_PATH to allow the users choice to be the first +// one tried. +IMPLEMENT_APP_NO_MAIN(AudacityApp) +IMPLEMENT_WX_THEME_SUPPORT + +#if defined(__WXMAC__) +int main(int argc, char *argv[]) +{ + if (getenv("DYLD_LIBRARY_PATH")) { + extern char **environ; + + unsetenv("DYLD_LIBRARY_PATH"); + execve(argv[0], argv, environ); + } + + wxDISABLE_DEBUG_SUPPORT(); + + return wxEntry(argc, argv); +} + +#elif defined(__WXMSW__) + +extern "C" int WINAPI WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + wxCmdLineArgType WXUNUSED(lpCmdLine), + int nCmdShow) +{ + wxDISABLE_DEBUG_SUPPORT(); + + // Disable setting of HiDPI aware mode + wxMSWDisableSettingHighDPIAware(); + + /* NB: We pass NULL in place of lpCmdLine to behave the same as */ + /* Borland-specific wWinMain() above. If it becomes needed */ + /* to pass lpCmdLine to wxEntry() here, you'll have to fix */ + /* wWinMain() above too. */ + return wxEntry(hInstance, hPrevInstance, NULL, nCmdShow); +} +#endif +#endif + +#ifdef __WXMAC__ + +// in response of an open-document apple event +void AudacityApp::MacOpenFile(const wxString &fileName) +{ + ofqueue.Add(fileName); +} + +// in response of a print-document apple event +void AudacityApp::MacPrintFile(const wxString &fileName) +{ + ofqueue.Add(fileName); +} + +// in response of a open-application apple event +void AudacityApp::MacNewFile() +{ + if (!gInited) + return; + + // This method should only be used on the Mac platform + // when no project windows are open. + + if (gAudacityProjects.GetCount() == 0) { + CreateNewAudacityProject(); + } +} + +#endif //__WXMAC__ + +typedef int (AudacityApp::*SPECIALKEYEVENT)(wxKeyEvent&); + +#define ID_RECENT_CLEAR 6100 +#define ID_RECENT_FIRST 6101 +#define ID_RECENT_LAST 6112 + +// IPC communication +#define ID_IPC_SERVER 6200 +#define ID_IPC_SOCKET 6201 + +// we don't really care about the timer id, but set this value just in case we do in the future +#define kAudacityAppTimerID 0 + +BEGIN_EVENT_TABLE(AudacityApp, wxApp) + EVT_QUERY_END_SESSION(AudacityApp::OnEndSession) + + EVT_KEY_DOWN(AudacityApp::OnKeyDown) + EVT_CHAR(AudacityApp::OnChar) + EVT_KEY_UP(AudacityApp::OnKeyUp) + EVT_TIMER(kAudacityAppTimerID, AudacityApp::OnTimer) +#ifdef __WXMAC__ + EVT_MENU(wxID_NEW, AudacityApp::OnMenuNew) + EVT_MENU(wxID_OPEN, AudacityApp::OnMenuOpen) + EVT_MENU(wxID_ABOUT, AudacityApp::OnMenuAbout) + EVT_MENU(wxID_PREFERENCES, AudacityApp::OnMenuPreferences) + EVT_MENU(wxID_EXIT, AudacityApp::OnMenuExit) +#endif + +#ifndef __WXMSW__ + EVT_SOCKET(ID_IPC_SERVER, AudacityApp::OnServerEvent) + EVT_SOCKET(ID_IPC_SOCKET, AudacityApp::OnSocketEvent) +#endif + + // Recent file event handlers. + EVT_MENU(ID_RECENT_CLEAR, AudacityApp::OnMRUClear) + EVT_MENU_RANGE(ID_RECENT_FIRST, ID_RECENT_LAST, AudacityApp::OnMRUFile) + + // Handle AppCommandEvents (usually from a script) + EVT_APP_COMMAND(wxID_ANY, AudacityApp::OnReceiveCommand) +END_EVENT_TABLE() + +// backend for OnMRUFile +// TODO: Would be nice to make this handle not opening a file with more panache. +// - Inform the user if DefaultOpenPath not set. +// - Switch focus to correct instance of project window, if already open. +bool AudacityApp::MRUOpen(wxString fullPathStr) { + // Most of the checks below are copied from AudacityProject::OpenFiles. + // - some rationalisation might be possible. + + AudacityProject *proj = GetActiveProject(); + + if (!fullPathStr.IsEmpty()) + { + // verify that the file exists + if (wxFile::Exists(fullPathStr)) + { + if (!gPrefs->Write(wxT("/DefaultOpenPath"), wxPathOnly(fullPathStr)) || + !gPrefs->Flush()) + return false; + + // Make sure it isn't already open. + // Test here even though AudacityProject::OpenFile() also now checks, because + // that method does not return the bad result. + // That itself may be a FIXME. + if (AudacityProject::IsAlreadyOpen(fullPathStr)) + return false; + + // DMM: If the project is dirty, that means it's been touched at + // all, and it's not safe to open a new project directly in its + // place. Only if the project is brand-new clean and the user + // hasn't done any action at all is it safe for Open to take place + // inside the current project. + // + // If you try to Open a new project inside the current window when + // there are no tracks, but there's an Undo history, etc, then + // bad things can happen, including data files moving to the new + // project directory, etc. + if (!proj || proj->GetDirty() || !proj->GetIsEmpty()) { + proj = CreateNewAudacityProject(); + } + // This project is clean; it's never been touched. Therefore + // all relevant member variables are in their initial state, + // and it's okay to open a new project inside this window. + proj->OpenFile(fullPathStr); + } + else { + // File doesn't exist - remove file from history + wxMessageBox(wxString::Format(_("%s could not be found.\n\nIt has been removed from the list of recent files."), + fullPathStr.c_str())); + return(false); + } + } + return(true); +} + +void AudacityApp::OnMRUClear(wxCommandEvent& WXUNUSED(event)) +{ + mRecentFiles->Clear(); +} + +//vvv Basically, anything from Recent Files is treated as a .aup, until proven otherwise, +// then it tries to Import(). Very questionable handling, imo. +// Better, for example, to check the file type early on. +void AudacityApp::OnMRUFile(wxCommandEvent& event) { + int n = event.GetId() - ID_RECENT_FIRST; + wxString fullPathStr = mRecentFiles->GetHistoryFile(n); + + // Try to open only if not already open. + // Test IsAlreadyOpen() here even though AudacityProject::MRUOpen() also now checks, + // because we don't want to RemoveFileFromHistory() just because it already exists, + // and AudacityApp::OnMacOpenFile() calls MRUOpen() directly. + // that method does not return the bad result. + if (!AudacityProject::IsAlreadyOpen(fullPathStr) && !MRUOpen(fullPathStr)) + mRecentFiles->RemoveFileFromHistory(n); +} + +void AudacityApp::OnTimer(wxTimerEvent& WXUNUSED(event)) +{ + // Filenames are queued when Audacity receives the a few of the + // AppleEvent messages (via wxWidgets). So, open any that are + // in the queue and clean the queue. + if (gInited) { + if (ofqueue.GetCount()) { + // Load each file on the queue + while (ofqueue.GetCount()) { + wxString name(ofqueue[0]); + ofqueue.RemoveAt(0); + + // Get the user's attention if no file name was specified + if (name.IsEmpty()) { + // Get the users attention + AudacityProject *project = GetActiveProject(); + if (project) { + project->Maximize(); + project->Raise(); + project->RequestUserAttention(); + } + continue; + } + + // TODO: Handle failures better. + // Some failures are OK, e.g. file not found, just would-be-nices to do better, + // so FAIL_MSG is more a case of an enhancement request than an actual problem. + // LL: In all but one case an appropriate message is already displayed. The + // instance that a message is NOT displayed is when a failure to write + // to the config file has occurred. + if (!MRUOpen(name)) { + wxFAIL_MSG(wxT("MRUOpen failed")); + } + } + } + } + + // Check if a warning for missing aliased files should be displayed + if (ShouldShowMissingAliasedFileWarning()) { + // find which project owns the blockfile + // note: there may be more than 1, but just go with the first one. + size_t numProjects = gAudacityProjects.Count(); + wxString missingFileName; + AudacityProject *offendingProject = NULL; + + m_LastMissingBlockFileLock.Lock(); + if (numProjects == 1) { + // if there is only one project open, no need to search + offendingProject = gAudacityProjects[0]; + } else if (numProjects > 1) { + for (size_t i = 0; i < numProjects; i++) { + // search each project for the blockfile + if (gAudacityProjects[i]->GetDirManager()->ContainsBlockFile(m_LastMissingBlockFile)) { + offendingProject = gAudacityProjects[i]; + break; + } + } + } + missingFileName = ((AliasBlockFile*)m_LastMissingBlockFile)->GetAliasedFileName().GetFullPath(); + m_LastMissingBlockFileLock.Unlock(); + + // if there are no projects open, don't show the warning (user has closed it) + if (offendingProject) { + offendingProject->Iconize(false); + offendingProject->Raise(); + + wxString errorMessage = wxString::Format(_( +"One or more external audio files could not be found.\n\ +It is possible they were moved, deleted, or the drive they \ +were on was unmounted.\n\ +Silence is being substituted for the affected audio.\n\ +The first detected missing file is:\n\ +%s\n\ +There may be additional missing files.\n\ +Choose File > Check Dependencies to view a list of \ +locations of the missing files."), missingFileName.c_str()); + + // if an old dialog exists, raise it if it is + if (offendingProject->GetMissingAliasFileDialog()) { + offendingProject->GetMissingAliasFileDialog()->Raise(); + } else { + ShowAliasMissingDialog(offendingProject, _("Files Missing"), + errorMessage, wxT(""), true); + } + } + // Only show this warning once per event (playback/menu item/etc). + SetMissingAliasedFileWarningShouldShow(false); + } +} + +void AudacityApp::MarkAliasedFilesMissingWarning(BlockFile *b) +{ + // the reference counting provides thread safety. + if (b) + b->Ref(); + + m_LastMissingBlockFileLock.Lock(); + if (m_LastMissingBlockFile) + m_LastMissingBlockFile->Deref(); + + m_LastMissingBlockFile = b; + + m_LastMissingBlockFileLock.Unlock(); +} + +void AudacityApp::SetMissingAliasedFileWarningShouldShow(bool b) +{ + // Note that this is can be called by both the main thread and other threads. + // I don't believe we need a mutex because we are checking zero vs non-zero, + // and the setting from other threads will always be non-zero (true), and the + // setting from the main thread is always false. + m_aliasMissingWarningShouldShow = b; + // reset the warnings as they were probably marked by a previous run + if (m_aliasMissingWarningShouldShow) { + MarkAliasedFilesMissingWarning(NULL); + } +} + +bool AudacityApp::ShouldShowMissingAliasedFileWarning() +{ + bool ret = m_LastMissingBlockFile && m_aliasMissingWarningShouldShow; + + return ret; +} + +AudacityLogger *AudacityApp::GetLogger() +{ + // Use dynamic_cast so that we get a NULL ptr if we haven't yet + // setup our logger. + return dynamic_cast(wxLog::GetActiveTarget()); +} + +#if defined(__WXMSW__) +#define WL(lang, sublang) (lang), (sublang), +#else +#define WL(lang,sublang) +#endif + +#if !wxCHECK_VERSION(3, 0, 1) +wxLanguageInfo userLangs[] = +{ + { wxLANGUAGE_USER_DEFINED, wxT("bs"), WL(0, SUBLANG_DEFAULT) wxT("Bosnian"), wxLayout_LeftToRight } +}; +#endif + +void AudacityApp::InitLang( const wxString & lang ) +{ + if (mLocale) + delete mLocale; + +#if defined(__WXMAC__) + // This should be reviewed again during the wx3 conversion. + + // On OSX, if the LANG environment variable isn't set when + // using a language like Japanese, an assertion will trigger + // because conversion to Japanese from "?" doesn't return a + // valid length, so make OSX happy by defining/overriding + // the LANG environment variable with U.S. English for now. + wxSetEnv(wxT("LANG"), wxT("en_US.UTF-8")); +#endif + +#if wxCHECK_VERSION(3,0,0) + mLocale = new wxLocale(wxT(""), lang, wxT(""), true); +#else + mLocale = new wxLocale(wxT(""), lang, wxT(""), true, true); +#endif + + for(unsigned int i=0; iAddCatalogLookupPathPrefix(audacityPathList[i]); + + // LL: Must add the wxWidgets catalog manually since the search + // paths were not set up when mLocale was created. The + // catalogs are search in LIFO order, so add wxstd first. + mLocale->AddCatalog(wxT("wxstd")); + +// AUDACITY_NAME is legitimately used on some *nix configurations. +#ifdef AUDACITY_NAME + mLocale->AddCatalog(wxT(AUDACITY_NAME)); +#else + mLocale->AddCatalog(IPC_APPL); +#endif + + // Initialize internationalisation (number formats etc.) + // + // This must go _after_ creating the wxLocale instance because + // creating the wxLocale instance sets the application-wide locale. + Internat::Init(); +} + +void AudacityApp::OnFatalException() +{ +#if defined(EXPERIMENTAL_CRASH_REPORT) + GenerateCrashReport(wxDebugReport::Context_Exception); +#endif + + exit(-1); +} + +#if defined(EXPERIMENTAL_CRASH_REPORT) +void AudacityApp::GenerateCrashReport(wxDebugReport::Context ctx) +{ + wxDebugReportCompress rpt; + rpt.AddAll(ctx); + + wxFileName fn(FileNames::DataDir(), wxT("audacity.cfg")); + rpt.AddFile(fn.GetFullPath(), wxT("Audacity Configuration")); + rpt.AddFile(FileNames::PluginRegistry(), wxT("Plugin Registry")); + rpt.AddFile(FileNames::PluginSettings(), wxT("Plugin Settings")); + + if (ctx == wxDebugReport::Context_Current) + { + rpt.AddText(wxT("audiodev.txt"), gAudioIO->GetDeviceInfo(), wxT("Audio Device Info")); + } + + AudacityLogger *logger = GetLogger(); + if (logger) + { + rpt.AddText(wxT("log.txt"), logger->GetLog(), wxT("Audacity Log")); + } + + bool ok = wxDebugReportPreviewStd().Show(rpt); + +#if defined(__WXMSW__) + wxEventLoop::SetCriticalWindow(NULL); +#endif + + if (ok && rpt.Process()) + { + wxTextEntryDialog dlg(NULL, + _("Report generated to:"), + _("Audacity Support Data"), + rpt.GetCompressedFileName(), + wxOK | wxCENTER); + dlg.SetName(dlg.GetTitle()); + dlg.ShowModal(); + + wxLogMessage(wxT("Report generated to: %s"), + rpt.GetCompressedFileName().c_str()); + + rpt.Reset(); + } +} +#endif + +#if defined(__WXGTK__) +// On wxGTK, there's a focus issue where dialogs do not automatically pass focus +// to the first child. This means that you can use the keyboard to navigate within +// the dialog. Watching for the ACTIVATE event allows us to set the focus ourselves +// when each dialog opens. +// +// See bug #57 +// +int AudacityApp::FilterEvent(wxEvent & event) +{ + if (event.GetEventType() == wxEVT_ACTIVATE) + { + wxActivateEvent & e = (wxActivateEvent &) event; + + if (e.GetEventObject() && e.GetActive() && e.GetEventObject()->IsKindOf(CLASSINFO(wxDialog))) + { + ((wxWindow *)e.GetEventObject())->SetFocus(); + } + } + + return -1; +} +#endif + +AudacityApp::AudacityApp() +{ +// Do not capture crashes in debug builds +#if !defined(__WXDEBUG__) +#if defined(EXPERIMENTAL_CRASH_REPORT) +#if defined(wxUSE_ON_FATAL_EXCEPTION) && wxUSE_ON_FATAL_EXCEPTION + wxHandleFatalExceptions(); +#endif +#endif +#endif +} + +// The `main program' equivalent, creating the windows and returning the +// main frame +bool AudacityApp::OnInit() +{ + delete wxLog::SetActiveTarget(new AudacityLogger); + + mLocale = NULL; + + m_aliasMissingWarningShouldShow = true; + m_LastMissingBlockFile = NULL; + + mChecker = NULL; + mIPCServ = NULL; + +#if defined(__WXGTK__) + // Workaround for bug 154 -- initialize to false + inKbdHandler = false; +#endif + +#if defined(__WXMAC__) + // Disable window animation + wxSystemOptions::SetOption( wxMAC_WINDOW_PLAIN_TRANSITION, 1 ); +#endif + +#ifdef AUDACITY_NAME + wxString appName = wxT(AUDACITY_NAME); + wxString vendorName = wxT(AUDACITY_NAME); +#else + wxString vendorName = wxT("Audacity"); + wxString appName = wxT("Audacity"); +#endif + + wxTheApp->SetVendorName(vendorName); + wxTheApp->SetAppName(appName); + + // Unused strings that we want to be translated, even though + // we're not using them yet... + wxString future1 = _("Master Gain Control"); + + ::wxInitAllImageHandlers(); + + wxFileSystem::AddHandler(new wxZipFSHandler); + + // + // Paths: set search path and temp dir path + // + +#ifdef __WXGTK__ + /* Search path (for plug-ins, translations etc) is (in this order): + * The AUDACITY_PATH environment variable + * The current directory + * The user's .audacity-files directory in their home directory + * The "share" and "share/doc" directories in their install path */ + wxString home = wxGetHomeDir(); + + /* On Unix systems, the default temp dir is in /var/tmp. */ + defaultTempDir.Printf(wxT("/var/tmp/audacity-%s"), wxGetUserId().c_str()); + + wxString pathVar = wxGetenv(wxT("AUDACITY_PATH")); + if (pathVar != wxT("")) + AddMultiPathsToPathList(pathVar, audacityPathList); + AddUniquePathToPathList(::wxGetCwd(), audacityPathList); + +#ifdef AUDACITY_NAME + AddUniquePathToPathList(wxString::Format(wxT("%s/.%s-files"), + home.c_str(), wxT(AUDACITY_NAME)), + audacityPathList); + AddUniquePathToPathList(wxString::Format(wxT("%s/share/%s"), + wxT(INSTALL_PREFIX), wxT(AUDACITY_NAME)), + audacityPathList); + AddUniquePathToPathList(wxString::Format(wxT("%s/share/doc/%s"), + wxT(INSTALL_PREFIX), wxT(AUDACITY_NAME)), + audacityPathList); +#else //AUDACITY_NAME + AddUniquePathToPathList(wxString::Format(wxT("%s/.audacity-files"), + home.c_str()), + audacityPathList); + AddUniquePathToPathList(wxString::Format(wxT("%s/share/audacity"), + wxT(INSTALL_PREFIX)), + audacityPathList); + AddUniquePathToPathList(wxString::Format(wxT("%s/share/doc/audacity"), + wxT(INSTALL_PREFIX)), + audacityPathList); +#endif //AUDACITY_NAME + + AddUniquePathToPathList(wxString::Format(wxT("%s/share/locale"), + wxT(INSTALL_PREFIX)), + audacityPathList); + + AddUniquePathToPathList(wxString::Format(wxT("./locale")), + audacityPathList); + +#endif //__WXGTK__ + + wxFileName tmpFile; + tmpFile.AssignTempFileName(wxT("nn")); + wxString tmpDirLoc = tmpFile.GetPath(wxPATH_GET_VOLUME); + ::wxRemoveFile(tmpFile.GetFullPath()); + + // On Mac and Windows systems, use the directory which contains Audacity. +#ifdef __WXMSW__ + // On Windows, the path to the Audacity program is in argv[0] + wxString progPath = wxPathOnly(argv[0]); + AddUniquePathToPathList(progPath, audacityPathList); + AddUniquePathToPathList(progPath+wxT("\\Languages"), audacityPathList); + + defaultTempDir.Printf(wxT("%s\\audacity_temp"), + tmpDirLoc.c_str()); +#endif //__WXWSW__ + +#ifdef __WXMAC__ + // On Mac OS X, the path to the Audacity program is in argv[0] + wxString progPath = wxPathOnly(argv[0]); + + AddUniquePathToPathList(progPath, audacityPathList); + // If Audacity is a "bundle" package, then the root directory is + // the great-great-grandparent of the directory containing the executable. + AddUniquePathToPathList(progPath+wxT("/../../../"), audacityPathList); + + // These allow for searching the "bundle" + AddUniquePathToPathList(progPath+wxT("/../"), audacityPathList); + AddUniquePathToPathList(progPath+wxT("/../Resources"), audacityPathList); + + defaultTempDir.Printf(wxT("%s/audacity-%s"), + tmpDirLoc.c_str(), + wxGetUserId().c_str()); +#endif //__WXMAC__ + + // Define languanges for which we have translations, but that are not yet + // supported by wxWidgets. + // + // TODO: The whole Language initialization really need to be reworked. + // It's all over the place. +#if !wxCHECK_VERSION(3, 0, 1) + for (size_t i = 0, cnt = WXSIZEOF(userLangs); i < cnt; i++) + { + wxLocale::AddLanguage(userLangs[i]); + } +#endif + + // Initialize preferences and language + InitPreferences(); + + #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) && !defined(__CYGWIN__) + this->AssociateFileTypes(); + #endif + + // TODO - read the number of files to store in history from preferences + mRecentFiles = new FileHistory(ID_RECENT_LAST - ID_RECENT_FIRST + 1, ID_RECENT_CLEAR); + mRecentFiles->Load(*gPrefs, wxT("RecentFiles")); + + theTheme.EnsureInitialised(); + + // AColor depends on theTheme. + AColor::Init(); + + // Init DirManager, which initializes the temp directory + // If this fails, we must exit the program. + if (!InitTempDir()) { + FinishPreferences(); + return false; + } + +//<<<< Try to avoid dialogs before this point. +// The reason is that InitTempDir starts the single instance checker. +// If we're waiitng in a dialog before then we can very easily +// start multiple instances, defeating the single instance checker. + + + + + //JKC We'd like to initialise the module manager WHILE showing the splash screen. + //Can't in wx3.0.1 as MultiDialog interacts poorly with the splash screen. So we do it before. + //TODO: Find out why opening a multidialog wrecks the splash screen. + //best current guess is that it's something to do with doing a DoModal this early + //in the program. + + // Initialize the CommandHandler + InitCommandHandler(); + + // Initialize the PluginManager + PluginManager::Get().Initialize(); + + // Initialize the ModuleManager, including loading found modules + ModuleManager::Get().Initialize(*mCmdHandler); + + // Parse command line and handle options that might require + // immediate exit...no need to initialize all of the audio + // stuff to display the version string. + wxCmdLineParser *parser = ParseCommandLine(); + if (!parser) + { + delete parser; + + // Either user requested help or a parsing error occured + exit(1); + } + + if (parser->Found(wxT("v"))) + { + delete parser; + + wxFprintf(stderr, wxT("Audacity v%s\n"), AUDACITY_VERSION_STRING); + exit(0); + } + + long lval; + if (parser->Found(wxT("b"), &lval)) + { + if (lval < 256 || lval > 100000000) + { + delete parser; + + wxPrintf(_("Block size must be within 256 to 100000000\n")); + exit(1); + } + + Sequence::SetMaxDiskBlockSize(lval); + } + + wxString fileName; + if (parser->Found(wxT("d"), &fileName)) + { + AutoSaveFile asf; + if (asf.Decode(fileName)) + { + wxPrintf(_("File decoded successfully\n")); + } + else + { + wxPrintf(_("Decoding failed\n")); + } + exit(1); + } + +// No Splash screen on wx3 whislt we sort out the problem +// with showing a dialog AND a splash screen during inits. +#if !wxCHECK_VERSION(3, 0, 0) + // BG: Create a temporary window to set as the top window + wxImage logoimage((const char **) AudacityLogoWithName_xpm); + logoimage.Rescale(logoimage.GetWidth() / 2, logoimage.GetHeight() / 2); + wxBitmap logo(logoimage); + + wxSplashScreen *temporarywindow = + new wxSplashScreen(logo, + wxSPLASH_CENTRE_ON_SCREEN | wxSPLASH_NO_TIMEOUT, + 0, + NULL, + wxID_ANY, + wxDefaultPosition, + wxDefaultSize, + wxSTAY_ON_TOP); + temporarywindow->SetTitle(_("Audacity is starting up...")); + SetTopWindow(temporarywindow); +#endif + + //JKC: Would like to put module loading here. + + // More initialization + + InitDitherers(); + InitAudioIO(); + +#ifdef __WXMAC__ + + // On the Mac, users don't expect a program to quit when you close the last window. + // Create a menubar that will show when all project windows are closed. + + wxMenu *fileMenu = new wxMenu(); + wxMenu *recentMenu = new wxMenu(); + fileMenu->Append(wxID_NEW, wxString(_("&New")) + wxT("\tCtrl+N")); + fileMenu->Append(wxID_OPEN, wxString(_("&Open...")) + wxT("\tCtrl+O")); + fileMenu->AppendSubMenu(recentMenu, _("Open &Recent...")); + fileMenu->Append(wxID_ABOUT, _("&About Audacity...")); + fileMenu->Append(wxID_PREFERENCES, wxString(_("&Preferences...")) + wxT("\tCtrl+,")); + + wxMenuBar *menuBar = new wxMenuBar(); + menuBar->Append(fileMenu, _("&File")); + + wxMenuBar::MacSetCommonMenuBar(menuBar); + + mRecentFiles->UseMenu(recentMenu); + mRecentFiles->AddFilesToMenu(recentMenu); + + // This invisibale frame will be the "root" of all other frames and will + // become the active frame when no projects are open. + gParentFrame = new wxFrame(NULL, -1, wxEmptyString, wxPoint(0, 0), wxSize(0, 0), 0); + +#endif //__WXMAC__ + + SetExitOnFrameDelete(true); + + + AudacityProject *project = CreateNewAudacityProject(); + mCmdHandler->SetProject(project); + wxWindow * pWnd = MakeHijackPanel() ; + if( pWnd ) + { + project->Show( false ); + pWnd->SetParent( project ); + SetTopWindow(pWnd); + pWnd->Show( true ); + } + + +#if !wxCHECK_VERSION(3, 0, 0) + temporarywindow->Show(false); + delete temporarywindow; +#endif + + if( project->mShowSplashScreen ) + project->OnHelpWelcome(); + + // JKC 10-Sep-2007: Enable monitoring from the start. + // (recommended by lprod.org). + // Monitoring stops again after any + // PLAY or RECORD completes. + // So we also call StartMonitoring when STOP is called. + project->MayStartMonitoring(); + + #ifdef USE_FFMPEG + FFmpegStartup(); + #endif + + Importer::Get().Initialize(); + + // + // Auto-recovery + // + bool didRecoverAnything = false; + if (!ShowAutoRecoveryDialogIfNeeded(&project, &didRecoverAnything)) + { + // Important: Prevent deleting any temporary files! + DirManager::SetDontDeleteTempFiles(); + delete parser; + QuitAudacity(true); + return false; + } + + // + // Remainder of command line parsing, but only if we didn't recover + // + if (!didRecoverAnything) + { + if (parser->Found(wxT("t"))) + { + delete parser; + + RunBenchmark(NULL); + return false; + } + + for (size_t i = 0, cnt = parser->GetParamCount(); i < cnt; i++) + { + MRUOpen(parser->GetParam(i)); + } + } + + delete parser; + + gInited = true; + + ModuleManager::Get().Dispatch(AppInitialized); + + mWindowRectAlreadySaved = FALSE; + + mTimer.SetOwner(this, kAudacityAppTimerID); + mTimer.Start(200); + + return TRUE; +} + +void AudacityApp::InitCommandHandler() +{ + mCmdHandler = new CommandHandler(*this); + //SetNextHandler(mCmdHandler); +} + +void AudacityApp::DeInitCommandHandler() +{ + wxASSERT(NULL != mCmdHandler); + delete mCmdHandler; + mCmdHandler = NULL; +} + +// AppCommandEvent callback - just pass the event on to the CommandHandler +void AudacityApp::OnReceiveCommand(AppCommandEvent &event) +{ + wxASSERT(NULL != mCmdHandler); + mCmdHandler->OnReceiveCommand(event); +} + +bool AudacityApp::InitTempDir() +{ + // We need to find a temp directory location. + + wxString tempFromPrefs = gPrefs->Read(wxT("/Directories/TempDir"), wxT("")); + wxString tempDefaultLoc = wxGetApp().defaultTempDir; + + wxString temp = wxT(""); + + #ifdef __WXGTK__ + if (tempFromPrefs.Length() > 0 && tempFromPrefs[0] != wxT('/')) + tempFromPrefs = wxT(""); + #endif + + // Stop wxWidgets from printing its own error messages + + wxLogNull logNo; + + // Try temp dir that was stored in prefs first + + if (tempFromPrefs != wxT("")) { + if (wxDirExists(tempFromPrefs)) + temp = tempFromPrefs; + else if (wxMkdir(tempFromPrefs, 0755)) + temp = tempFromPrefs; + } + + // If that didn't work, try the default location + + if (temp==wxT("") && tempDefaultLoc != wxT("")) { + if (wxDirExists(tempDefaultLoc)) + temp = tempDefaultLoc; + else if (wxMkdir(tempDefaultLoc, 0755)) + temp = tempDefaultLoc; + } + + // Check temp directory ownership on *nix systems only + #ifdef __UNIX__ + struct stat tempStatBuf; + if ( lstat(temp.mb_str(), &tempStatBuf) != 0 ) { + temp.clear(); + } + else { + if ( geteuid() != tempStatBuf.st_uid ) { + temp.clear(); + } + } + #endif + + if (temp == wxT("")) { + // Failed + wxMessageBox(_("Audacity could not find a place to store temporary files.\nPlease enter an appropriate directory in the preferences dialog.")); + + PrefsDialog dialog(NULL); + dialog.ShowTempDirPage(); + dialog.ShowModal(); + + wxMessageBox(_("Audacity is now going to exit. Please launch Audacity again to use the new temporary directory.")); + return false; + } + + // The permissions don't always seem to be set on + // some platforms. Hopefully this fixes it... + #ifdef __UNIX__ + chmod(OSFILENAME(temp), 0755); + #endif + + bool bSuccess = gPrefs->Write(wxT("/Directories/TempDir"), temp) && gPrefs->Flush(); + DirManager::SetTempDir(temp); + + // Make sure the temp dir isn't locked by another process. + if (!CreateSingleInstanceChecker(temp)) + return false; + + return bSuccess; +} + +// Return true if there are no other instances of Audacity running, +// false otherwise. +// +// Use "dir" for creating lockfiles (on OS X and Unix). + +bool AudacityApp::CreateSingleInstanceChecker(wxString dir) +{ + wxString name = wxString::Format(wxT("audacity-lock-%s"), wxGetUserId().c_str()); + mChecker = new wxSingleInstanceChecker(); + +#if defined(__UNIX__) + wxString sockFile(defaultTempDir + wxT("/.audacity.sock")); +#endif + + wxString runningTwoCopiesStr = _("Running two copies of Audacity simultaneously may cause\ndata loss or cause your system to crash.\n\n"); + + if (!mChecker->Create(name, dir)) { + // Error initializing the wxSingleInstanceChecker. We don't know + // whether there is another instance running or not. + + wxString prompt = + _("Audacity was not able to lock the temporary files directory.\nThis folder may be in use by another copy of Audacity.\n") + + runningTwoCopiesStr + + _("Do you still want to start Audacity?"); + int action = wxMessageBox(prompt, + _("Error Locking Temporary Folder"), + wxYES_NO | wxICON_EXCLAMATION, + NULL); + if (action == wxNO) { + delete mChecker; + return false; + } + } + else if ( mChecker->IsAnotherRunning() ) { + // Parse the command line to ensure correct syntax, but + // ignore options and only use the filenames, if any. + wxCmdLineParser *parser = ParseCommandLine(); + if (!parser) + { + // Complaints have already been made + return false; + } + +#if defined(__WXMSW__) + // On Windows, we attempt to make a connection + // to an already active Audacity. If successful, we send + // the first command line argument (the audio file name) + // to that Audacity for processing. + wxClient client; + + // We try up to 50 times since there's a small window + // where the server may not have been fully initialized. + for (int i = 0; i < 50; i++) + { + wxConnectionBase *conn = client.MakeConnection(wxEmptyString, IPC_APPL, IPC_TOPIC); + if (conn) + { + bool ok = false; + if (parser->GetParamCount() > 0) + { + // Send each parameter to existing Audacity + for (size_t i = 0, cnt = parser->GetParamCount(); i < cnt; i++) + { + ok = conn->Execute(parser->GetParam(i)); + } + } + else + { + // Send an empty string to force existing Audacity to front + ok = conn->Execute(wxEmptyString); + } + + delete conn; + + if (ok) + { + delete parser; + return false; + } + } + + wxMilliSleep(10); + } +#else + // On Unix-like machines, we use a local (file based) socket to + // send the first command line argument to an already running + // Audacity. + wxUNIXaddress addr; + addr.Filename(sockFile); + + // Setup the socket + wxSocketClient *sock = new wxSocketClient(); + sock->SetFlags(wxSOCKET_WAITALL); + + // We try up to 50 times since there's a small window + // where the server may not have been fully initialized. + for (int i = 0; i < 50; i++) + { + // Connect to the existing Audacity + sock->Connect(addr, true); + if (sock->IsConnected()) + { + for (size_t i = 0, cnt = parser->GetParamCount(); i < cnt; i++) + { + // Send the filename + wxString param = parser->GetParam(i); + sock->WriteMsg((const wxChar *) param.c_str(), (param.Len() + 1) * sizeof(wxChar)); + } + + sock->Destroy(); + delete parser; + return false; + } + + wxMilliSleep(100); + } + + sock->Destroy(); +#endif + // There is another copy of Audacity running. Force quit. + + wxString prompt = + _("The system has detected that another copy of Audacity is running.\n") + + runningTwoCopiesStr + + _("Use the New or Open commands in the currently running Audacity\nprocess to open multiple projects simultaneously.\n"); + wxMessageBox(prompt, _("Audacity is already running"), + wxOK | wxICON_ERROR); + delete parser; + delete mChecker; + return false; + } + +#if defined(__WXMSW__) + // Create the DDE IPC server + mIPCServ = new IPCServ(IPC_APPL); +#else + int mask = umask(077); + remove(OSFILENAME(sockFile)); + wxUNIXaddress addr; + addr.Filename(sockFile); + mIPCServ = new wxSocketServer(addr, wxSOCKET_NOWAIT); + umask(mask); + + if (!mIPCServ || !mIPCServ->IsOk()) + { + // TODO: Complain here + return false; + } + + mIPCServ->SetEventHandler(*this, ID_IPC_SERVER); + mIPCServ->SetNotify(wxSOCKET_CONNECTION_FLAG); + mIPCServ->Notify(true); +#endif + return true; +} + +#if defined(__UNIX__) +void AudacityApp::OnServerEvent(wxSocketEvent & evt) +{ + wxSocketBase *sock; + + // Accept all pending connection requests + do + { + sock = mIPCServ->Accept(false); + if (sock) + { + // Setup the socket + sock->SetEventHandler(*this, ID_IPC_SOCKET); + sock->SetNotify(wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG); + sock->Notify(true); + } + } while (sock); +} + +void AudacityApp::OnSocketEvent(wxSocketEvent & evt) +{ + wxSocketBase *sock = evt.GetSocket(); + + if (evt.GetSocketEvent() == wxSOCKET_LOST) + { + sock->Destroy(); + return; + } + + // Read the length of the filename and bail if we have a short read + wxChar name[PATH_MAX]; + sock->ReadMsg(&name, sizeof(name)); + if (!sock->Error()) + { + // Add the filename to the queue. It will be opened by + // the OnTimer() event when it is safe to do so. + ofqueue.Add(name); + } +} + +#endif + +wxCmdLineParser *AudacityApp::ParseCommandLine() +{ + wxCmdLineParser *parser = new wxCmdLineParser(argc, argv); + if (!parser) + { + return NULL; + } + + /*i18n-hint: This controls the number of bytes that Audacity will + * use when writing files to the disk */ + parser->AddOption(wxT("b"), wxT("blocksize"), _("set max disk block size in bytes"), + wxCMD_LINE_VAL_NUMBER); + + /*i18n-hint: This decodes an autosave file */ + parser->AddOption(wxT("d"), wxT("decode"), _("decode an autosave file"), + wxCMD_LINE_VAL_STRING); + + /*i18n-hint: This displays a list of available options */ + parser->AddSwitch(wxT("h"), wxT("help"), _("this help message"), + wxCMD_LINE_OPTION_HELP); + + /*i18n-hint: This runs a set of automatic tests on Audacity itself */ + parser->AddSwitch(wxT("t"), wxT("test"), _("run self diagnostics")); + + /*i18n-hint: This displays the Audacity version */ + parser->AddSwitch(wxT("v"), wxT("version"), _("display Audacity version")); + + /*i18n-hint: This is a list of one or more files that Audacity + * should open upon startup */ + parser->AddParam(_("audio or project file name"), + wxCMD_LINE_VAL_STRING, + wxCMD_LINE_PARAM_MULTIPLE | wxCMD_LINE_PARAM_OPTIONAL); + + // Run the parser + if (parser->Parse() == 0) + { + return parser; + } + + delete parser; + + return NULL; +} + +// static +void AudacityApp::AddUniquePathToPathList(wxString path, + wxArrayString &pathList) +{ + wxFileName pathNorm = path; + pathNorm.Normalize(); + path = pathNorm.GetFullPath(); + + for(unsigned int i=0; iClose(true); + } + else if (!gAudacityProjects[0]->Close()) { + gIsQuitting = false; + event.Veto(); + break; + } + } + } +} + +void AudacityApp::OnKeyDown(wxKeyEvent & event) +{ + // Not handled + event.Skip(true); + + // Make sure this event is destined for a project window + AudacityProject *prj = GetActiveProject(); + + // TODO: I don't know how it can happen, but it did on 2006-07-06. + // I was switching between apps fairly quickly so maybe that has something + // to do with it. + if (!prj) + return; + + if (prj->HandleKeyDown(event)) + event.Skip(false); +} + +void AudacityApp::OnChar(wxKeyEvent & event) +{ + // Not handled + event.Skip(true); + + // Make sure this event is destined for a project window + AudacityProject *prj = GetActiveProject(); + + // TODO: I don't know how it can happen, but it did on 2006-07-06. + // I was switching between apps fairly quickly so maybe that has something + // to do with it. + if (!prj) + return; + + if (prj->HandleChar(event)) + event.Skip(false); +} + +void AudacityApp::OnKeyUp(wxKeyEvent & event) +{ + // Not handled + event.Skip(true); + + // Make sure this event is destined for a project window + AudacityProject *prj = GetActiveProject(); + + // TODO: I don't know how it can happen, but it did on 2006-07-06. + // I was switching between apps fairly quickly so maybe that has something + // to do with it. + if (!prj) + return; + + if (prj != wxGetTopLevelParent(wxWindow::FindFocus())) + return; + + if (prj->HandleKeyUp(event)) + event.Skip(false); +} + +void AudacityApp::AddFileToHistory(const wxString & name) +{ + mRecentFiles->AddFileToHistory(name); +} + +int AudacityApp::OnExit() +{ + gIsQuitting = true; + while(Pending()) + { + Dispatch(); + } + + Importer::Get().Terminate(); + + if(gPrefs) + { + bool bFalse = false; + //Should we change the commands.cfg location next startup? + if(gPrefs->Read(wxT("/QDeleteCmdCfgLocation"), &bFalse)) + { + gPrefs->DeleteEntry(wxT("/QDeleteCmdCfgLocation")); + gPrefs->Write(wxT("/DeleteCmdCfgLocation"), true); + gPrefs->Flush(); + } + } + + DeInitCommandHandler(); + + mRecentFiles->Save(*gPrefs, wxT("RecentFiles")); + delete mRecentFiles; + + FinishPreferences(); + +#ifdef USE_FFMPEG + DropFFmpegLibs(); +#endif + + DeinitFFT(); + BlockFile::Deinit(); + + DeinitAudioIO(); + + // Terminate the PluginManager (must be done before deleting the locale) + PluginManager::Get().Terminate(); + + // Done with plugins and modules + PluginManager::Destroy(); + ModuleManager::Destroy(); + + if (mLocale) + delete mLocale; + + if (mIPCServ) + { +#if defined(__UNIX__) + wxUNIXaddress addr; + if (mIPCServ->GetLocal(addr)) + { + remove(OSFILENAME(addr.Filename())); + } +#endif + delete mIPCServ; + } + + if (mChecker) + delete mChecker; + + return 0; +} + +// The following five methods are currently only used on Mac OS, +// where it's possible to have a menu bar but no windows open. +// It doesn't hurt any other platforms, though. + +// ...That is, as long as you check to see if no windows are open +// before executing the stuff. +// To fix this, check to see how many project windows are open, +// and skip the event unless none are open (which should only happen +// on the Mac, at least currently.) + +void AudacityApp::OnMenuAbout(wxCommandEvent & event) +{ + // This function shadows a similar function + // in Menus.cpp, but should only be used on the Mac platform + // when no project windows are open. This check assures that + // this happens, and enable the same code to be present on + // all platforms. + if(gAudacityProjects.GetCount() == 0) { + AboutDialog dlog(NULL); + dlog.ShowModal(); + } + else + event.Skip(); +} + +void AudacityApp::OnMenuNew(wxCommandEvent & event) +{ + // This function shadows a similar function + // in Menus.cpp, but should only be used on the Mac platform + // when no project windows are open. This check assures that + // this happens, and enable the same code to be present on + // all platforms. + + if(gAudacityProjects.GetCount() == 0) + CreateNewAudacityProject(); + else + event.Skip(); +} + + +void AudacityApp::OnMenuOpen(wxCommandEvent & event) +{ + // This function shadows a similar function + // in Menus.cpp, but should only be used on the Mac platform + // when no project windows are open. This check assures that + // this happens, and enable the same code to be present on + // all platforms. + + + if(gAudacityProjects.GetCount() == 0) + AudacityProject::OpenFiles(NULL); + else + event.Skip(); + + +} + +void AudacityApp::OnMenuPreferences(wxCommandEvent & event) +{ + // This function shadows a similar function + // in Menus.cpp, but should only be used on the Mac platform + // when no project windows are open. This check assures that + // this happens, and enable the same code to be present on + // all platforms. + + if(gAudacityProjects.GetCount() == 0) { + PrefsDialog dialog(NULL /* parent */ ); + dialog.ShowModal(); + } + else + event.Skip(); + +} + +void AudacityApp::OnMenuExit(wxCommandEvent & event) +{ + // This function shadows a similar function + // in Menus.cpp, but should only be used on the Mac platform + // when no project windows are open. This check assures that + // this happens, and enable the same code to be present on + // all platforms. + + // LL: Removed "if" to allow closing based on final project count. + // if(gAudacityProjects.GetCount() == 0) + QuitAudacity(); + + // LL: Veto quit if projects are still open. This can happen + // if the user selected Cancel in a Save dialog. + event.Skip(gAudacityProjects.GetCount() == 0); + +} + +//BG: On Windows, associate the aup file type with Audacity +/* We do this in the Windows installer now, + to avoid issues where user doesn't have admin privileges, but + in case that didn't work, allow the user to decide at startup. + + //v Should encapsulate this & allow access from Prefs, too, + // if people want to manually change associations. +*/ +#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) && !defined(__CYGWIN__) +void AudacityApp::AssociateFileTypes() +{ + wxRegKey associateFileTypes; + associateFileTypes.SetName(wxT("HKCR\\.AUP")); + bool bKeyExists = associateFileTypes.Exists(); + if (!bKeyExists) { + // Not at HKEY_CLASSES_ROOT. Try HKEY_CURRENT_USER. + associateFileTypes.SetName(wxT("HKCU\\Software\\Classes\\.AUP")); + bKeyExists = associateFileTypes.Exists(); + } + if (!bKeyExists) { + // File types are not currently associated. + // Check pref in case user has already decided against it. + bool bWantAssociateFiles = true; + if (!gPrefs->Read(wxT("/WantAssociateFiles"), &bWantAssociateFiles) || + bWantAssociateFiles) { + // Either there's no pref or user does want associations + // and they got stepped on, so ask. + int wantAssoc = + wxMessageBox( + _("Audacity project (.AUP) files are not currently \nassociated with Audacity. \n\nAssociate them, so they open on double-click?"), + _("Audacity Project Files"), + wxYES_NO | wxICON_QUESTION); + if (wantAssoc == wxYES) { + gPrefs->Write(wxT("/WantAssociateFiles"), true); + gPrefs->Flush(); + + wxString root_key; + + root_key = wxT("HKCU\\Software\\Classes\\"); + associateFileTypes.SetName(root_key + wxT(".AUP")); // Start again with HKEY_CLASSES_ROOT. + if (!associateFileTypes.Create(true)) { + // Not at HKEY_CLASSES_USER. Try HKEY_CURRENT_ROOT. + root_key = wxT("HKCR\\"); + associateFileTypes.SetName(root_key + wxT(".AUP")); + if (!associateFileTypes.Create(true)) { + // Actually, can't create keys. Empty root_key to flag failure. + root_key.Empty(); + } + } + if (root_key.IsEmpty()) { + //v Warn that we can't set keys. Ask whether to set pref for no retry? + } else { + associateFileTypes = wxT("Audacity.Project"); // Finally set value for .AUP key + + associateFileTypes.SetName(root_key + wxT("Audacity.Project")); + if(!associateFileTypes.Exists()) { + associateFileTypes.Create(true); + associateFileTypes = wxT("Audacity Project File"); + } + + associateFileTypes.SetName(root_key + wxT("Audacity.Project\\shell")); + if(!associateFileTypes.Exists()) { + associateFileTypes.Create(true); + associateFileTypes = wxT(""); + } + + associateFileTypes.SetName(root_key + wxT("Audacity.Project\\shell\\open")); + if(!associateFileTypes.Exists()) { + associateFileTypes.Create(true); + } + + associateFileTypes.SetName(root_key + wxT("Audacity.Project\\shell\\open\\command")); + wxString tmpRegAudPath; + if(associateFileTypes.Exists()) { + tmpRegAudPath = wxString(associateFileTypes).Lower(); + } + if (!associateFileTypes.Exists() || + (tmpRegAudPath.Find(wxT("audacity.exe")) >= 0)) { + associateFileTypes.Create(true); + associateFileTypes = (wxString)argv[0] + (wxString)wxT(" \"%1\""); + } + +#if 0 + // These can be use later to support more startup messages + // like maybe "Import into existing project" or some such. + // Leaving here for an example... + associateFileTypes.SetName(root_key + wxT("Audacity.Project\\shell\\open\\ddeexec")); + if(!associateFileTypes.Exists()) { + associateFileTypes.Create(true); + associateFileTypes = wxT("%1"); + } + + associateFileTypes.SetName(root_key + wxT("Audacity.Project\\shell\\open\\ddeexec\\Application")); + if(!associateFileTypes.Exists()) { + associateFileTypes.Create(true); + associateFileTypes = IPC_APPL; + } + + associateFileTypes.SetName(root_key + wxT("Audacity.Project\\shell\\open\\ddeexec\\Topic")); + if(!associateFileTypes.Exists()) { + associateFileTypes.Create(true); + associateFileTypes = IPC_TOPIC; + } +#endif + } + } else { + // User said no. Set a pref so we don't keep asking. + gPrefs->Write(wxT("/WantAssociateFiles"), false); + gPrefs->Flush(); + } + } + } +} +#endif + diff --git a/src/Benchmark.cpp b/src/Benchmark.cpp index be4c1c39b..f47c4b610 100644 --- a/src/Benchmark.cpp +++ b/src/Benchmark.cpp @@ -247,7 +247,12 @@ void BenchmarkDialog::OnSave( wxCommandEvent & WXUNUSED(event)) wxString fName = wxT("benchmark.txt"); fName = FileSelector(wxT("Export Benchmark Data As:"), - wxEmptyString, fName, wxT("txt"), wxT("*.txt"), wxFD_SAVE | wxRESIZE_BORDER, this); + wxEmptyString, + fName, + wxT("txt"), + wxT("*.txt"), + wxFD_SAVE | wxRESIZE_BORDER, + this); if (fName == wxT("")) return; diff --git a/src/CaptureEvents.cpp b/src/CaptureEvents.cpp deleted file mode 100644 index 9ddefdc2a..000000000 --- a/src/CaptureEvents.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/********************************************************************** - - Audacity: A Digital Audio Editor - Audacity(R) is copyright (c) 1999-2008 Audacity Team. - License: GPL v2. See License.txt. - - CaptureEvents.h - Created by Al Dimond, Oct. 2009 (from code by someone else) - -******************************************************************//** - -\class CaptureEvents -\brief RAII-style class to work around a bug in wxGTK 2.8.9-? - -*//*******************************************************************/ - -#include -#include "Audacity.h" -#include "CaptureEvents.h" - -#if defined(__WXGTK__) && defined(HAVE_GTK) && !wxCHECK_VERSION(3, 0, 0) -// As of wxGTK 2.8.9, there is a problem in the wxClipboard class that -// allows recursive event processing. This problem has been corrected -// by wxWidgets 2.9+. However, this han't made it into a release yet, -// so we have to work around it. -// -// This is done by pulling/merging in some code from wx29 and creating -// the following class to capture events while accessing the clipboard -// to prevent the asynchronous clipboard access from causing recursive -// event processing. - -#include -#include -#include -#include - -extern GtkWidget *wxGetRootWindow(); - -static void main_do_event(GdkEvent *event, wxArrayPtrVoid *queue) -{ - switch (event->type) - { - case GDK_NOTHING: - // Ignore it - break; - - case GDK_SELECTION_REQUEST: - case GDK_SELECTION_NOTIFY: - case GDK_SELECTION_CLEAR: -#if GTK_CHECK_VERSION(2,6,0) - case GDK_OWNER_CHANGE: -#endif - // process it now - gtk_main_do_event(event); - break; - - default: - // process it later (but make a copy; the caller will free the event pointer) - queue->Add(gdk_event_copy(event)); - break; - } - - // don't allow idle callbacks while we're active - wxTheApp->SuspendIdleCallback(); - - return; -} - -CaptureEvents::CaptureEvents() -{ -#if wxUSE_LOG - // disable log flushing from here because a call to wxTheApp->Yield() shouldn't - // normally result in message boxes popping up &c - wxLog::Suspend(); -#endif - - // temporarily replace the global GDK event handler with our function - gdk_event_handler_set((GdkEventFunc)main_do_event, &queue, NULL); - - // temporarily suspend idle callbacks - wxTheApp->SuspendIdleCallback(); -} - -CaptureEvents::~CaptureEvents() -{ - gdk_event_handler_set((GdkEventFunc)gtk_main_do_event, NULL, NULL); - - // put all unprocessed GDK events back in the queue - GdkDisplay* disp = gtk_widget_get_display(wxGetRootWindow()); - size_t cnt = queue.GetCount(); - for (size_t i = 0; i < cnt; i++) { - GdkEvent* event = (GdkEvent*)queue[i]; - // NOTE: gdk_display_put_event makes a copy of the event passed to it - gdk_display_put_event(disp, event); - gdk_event_free(event); - } - -#if wxUSE_LOG - // let the logs be flashed again - wxLog::Resume(); -#endif -} - - -#endif diff --git a/src/CaptureEvents.h b/src/CaptureEvents.h deleted file mode 100644 index 96fa36ce5..000000000 --- a/src/CaptureEvents.h +++ /dev/null @@ -1,45 +0,0 @@ -/********************************************************************** - - Audacity: A Digital Audio Editor - Audacity(R) is copyright (c) 1999-2008 Audacity Team. - License: GPL v2. See License.txt. - - CaptureEvents.h - Created by Al Dimond, Oct. 2009 (from code by someone else) - -******************************************************************//** - -\class CaptureEvents -\brief RAII-style class to work around a bug in wxGTK 2.8.9-? - -*//*******************************************************************/ - -#ifndef _AUDACITY_CAPTURE_EVENTS_ -#define _AUDACITY_CAPTURE_EVENTS_ - -#if defined(__WXGTK__) && defined(HAVE_GTK) -// As of wxGTK 2.8.9, there is a problem in the wxClipboard class that -// allows recursive event processing. This problem has been corrected -// by wxWidgets 2.9+. However, this han't made it into a release yet, -// so we have to work around it. -// -// This is done by pulling/merging in some code from wx29 and creating -// the following class to capture events while accessing the clipboard -// to prevent the asynchronous clipboard access from causing recursive -// event processing. - -#include - -class CaptureEvents -{ - public: - CaptureEvents(); - - virtual ~CaptureEvents(); - - private: - wxArrayPtrVoid queue; -}; -#endif - -#endif diff --git a/src/FreqWindow.cpp b/src/FreqWindow.cpp index 0ad678476..1a86fa23e 100644 --- a/src/FreqWindow.cpp +++ b/src/FreqWindow.cpp @@ -42,15 +42,6 @@ and in the spectrogram spectral selection. #include "Audacity.h" -// For compilers that support precompilation, includes "wx/wx.h". -#include - - - -#ifdef __BORLANDC__ -#pragma hdrstop -#endif - #include #include #include @@ -84,10 +75,10 @@ and in the spectrogram spectral selection. #include "FileDialog.h" -#if defined(__WXGTK__) -#define GSocket GSocketHack -#include -#endif +//#if defined(__WXGTK__) +//#define GSocket GSocketHack +//#include +//#endif DEFINE_EVENT_TYPE(EVT_FREQWINDOW_RECALC); @@ -516,7 +507,7 @@ FreqWindow::FreqWindow(wxWindow * parent, wxWindowID id, // // I guess the only way round it would be to handle key actions // ourselves, but we'll leave that for a future date. - gtk_widget_set_can_focus(mPanScroller->m_widget, true); +// gtk_widget_set_can_focus(mPanScroller->m_widget, true); #endif } diff --git a/src/FreqWindow.h b/src/FreqWindow.h index 11b1ea13d..8fb59bd45 100644 --- a/src/FreqWindow.h +++ b/src/FreqWindow.h @@ -29,7 +29,6 @@ #include #include #include - #include "widgets/Ruler.h" class wxStatusBar; diff --git a/src/LabelTrack.cpp b/src/LabelTrack.cpp index c5250d47d..ade23d3f7 100644 --- a/src/LabelTrack.cpp +++ b/src/LabelTrack.cpp @@ -59,7 +59,6 @@ for drawing different aspects of the label and its text box. #include "TrackArtist.h" #include "commands/CommandManager.h" -#include "CaptureEvents.h" #include "effects/TimeWarper.h" wxFont LabelTrack::msFont; @@ -974,9 +973,6 @@ bool LabelTrack::CutSelectedText() // copy data onto clipboard if (wxTheClipboard->Open()) { -#if defined(__WXGTK__) && defined(HAVE_GTK) && !wxCHECK_VERSION(3, 0, 0) - CaptureEvents capture; -#endif wxTheClipboard->SetData(new wxTextDataObject(data)); wxTheClipboard->Close(); } @@ -1009,9 +1005,6 @@ bool LabelTrack::CopySelectedText() // copy the data on clipboard if (wxTheClipboard->Open()) { -#if defined(__WXGTK__) && defined(HAVE_GTK) && !wxCHECK_VERSION(3, 0, 0) - CaptureEvents capture; -#endif wxTheClipboard->SetData(new wxTextDataObject(data)); wxTheClipboard->Close(); } @@ -1035,9 +1028,6 @@ bool LabelTrack::PasteSelectedText(double sel0, double sel1) // if text data is available if (IsTextClipSupported()) { if (wxTheClipboard->Open()) { -#if defined(__WXGTK__) && defined(HAVE_GTK) && !wxCHECK_VERSION(3, 0, 0) - CaptureEvents capture; -#endif wxTextDataObject data; wxTheClipboard->GetData(data); wxTheClipboard->Close(); @@ -1092,10 +1082,6 @@ bool LabelTrack::PasteSelectedText(double sel0, double sel1) /// @return true if the text data is available in the clipboard, false otherwise bool LabelTrack::IsTextClipSupported() { -#if defined(__WXGTK__) && defined(HAVE_GTK) && !wxCHECK_VERSION(3, 0, 0) - CaptureEvents capture; -#endif - #if defined(__WXGTK__) // AWD: work-around for bug 154: do not call wxClipboard::IsSupported() // when handling a keyboard event diff --git a/src/Makefile.am b/src/Makefile.am index fbd9f749c..550fb905e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -114,8 +114,6 @@ audacity_SOURCES = \ BatchProcessDialog.h \ Benchmark.cpp \ Benchmark.h \ - CaptureEvents.cpp \ - CaptureEvents.h \ Dependencies.cpp \ Dependencies.h \ DeviceChange.cpp \ diff --git a/src/Makefile.in b/src/Makefile.in index 4a078b92d..ef88ae9f9 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.14.1 from Makefile.am. +# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2013 Free Software Foundation, Inc. +# Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -16,7 +16,17 @@ VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -186,9 +196,6 @@ bin_PROGRAMS = audacity$(EXEEXT) @USE_VST_TRUE@ $(NULL) subdir = src -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(srcdir)/configtemplate.h $(srcdir)/audacity.desktop.in \ - $(top_srcdir)/autotools/depcomp $(dist_mime_DATA) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_c99_func_lrint.m4 \ $(top_srcdir)/m4/ac_c99_func_lrintf.m4 \ @@ -229,6 +236,8 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ac_c99_func_lrint.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(dist_mime_DATA) \ + $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = configwin.h configunix.h CONFIG_CLEAN_FILES = audacity.desktop @@ -277,13 +286,12 @@ am__audacity_SOURCES_DIST = BlockFile.cpp BlockFile.h DirManager.cpp \ AutoRecovery.cpp AutoRecovery.h BatchCommandDialog.cpp \ BatchCommandDialog.h BatchCommands.cpp BatchCommands.h \ BatchProcessDialog.cpp BatchProcessDialog.h Benchmark.cpp \ - Benchmark.h CaptureEvents.cpp CaptureEvents.h Dependencies.cpp \ - Dependencies.h DeviceChange.cpp DeviceChange.h \ - DeviceManager.cpp DeviceManager.h Diags.cpp Diags.h \ - Envelope.cpp Envelope.h Experimental.h FFmpeg.cpp FFmpeg.h \ - FFT.cpp FFT.h FileIO.cpp FileIO.h FileNames.cpp FileNames.h \ - float_cast.h FreqWindow.cpp FreqWindow.h HelpText.cpp \ - HelpText.h HistoryWindow.cpp HistoryWindow.h \ + Benchmark.h Dependencies.cpp Dependencies.h DeviceChange.cpp \ + DeviceChange.h DeviceManager.cpp DeviceManager.h Diags.cpp \ + Diags.h Envelope.cpp Envelope.h Experimental.h FFmpeg.cpp \ + FFmpeg.h FFT.cpp FFT.h FileIO.cpp FileIO.h FileNames.cpp \ + FileNames.h float_cast.h FreqWindow.cpp FreqWindow.h \ + HelpText.cpp HelpText.h HistoryWindow.cpp HistoryWindow.h \ ImageManipulation.cpp ImageManipulation.h InterpolateAudio.cpp \ InterpolateAudio.h LabelDialog.cpp LabelDialog.h \ LabelTrack.cpp LabelTrack.h LangChoice.cpp LangChoice.h \ @@ -513,8 +521,7 @@ am_audacity_OBJECTS = $(am__objects_1) audacity-AboutDialog.$(OBJEXT) \ audacity-BatchCommandDialog.$(OBJEXT) \ audacity-BatchCommands.$(OBJEXT) \ audacity-BatchProcessDialog.$(OBJEXT) \ - audacity-Benchmark.$(OBJEXT) audacity-CaptureEvents.$(OBJEXT) \ - audacity-Dependencies.$(OBJEXT) \ + audacity-Benchmark.$(OBJEXT) audacity-Dependencies.$(OBJEXT) \ audacity-DeviceChange.$(OBJEXT) \ audacity-DeviceManager.$(OBJEXT) audacity-Diags.$(OBJEXT) \ audacity-Envelope.$(OBJEXT) audacity-FFmpeg.$(OBJEXT) \ @@ -845,6 +852,8 @@ am__define_uniq_tagged_files = \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/audacity.desktop.in \ + $(srcdir)/configtemplate.h $(top_srcdir)/autotools/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ @@ -1138,13 +1147,12 @@ audacity_SOURCES = $(libaudacity_la_SOURCES) AboutDialog.cpp \ AutoRecovery.cpp AutoRecovery.h BatchCommandDialog.cpp \ BatchCommandDialog.h BatchCommands.cpp BatchCommands.h \ BatchProcessDialog.cpp BatchProcessDialog.h Benchmark.cpp \ - Benchmark.h CaptureEvents.cpp CaptureEvents.h Dependencies.cpp \ - Dependencies.h DeviceChange.cpp DeviceChange.h \ - DeviceManager.cpp DeviceManager.h Diags.cpp Diags.h \ - Envelope.cpp Envelope.h Experimental.h FFmpeg.cpp FFmpeg.h \ - FFT.cpp FFT.h FileIO.cpp FileIO.h FileNames.cpp FileNames.h \ - float_cast.h FreqWindow.cpp FreqWindow.h HelpText.cpp \ - HelpText.h HistoryWindow.cpp HistoryWindow.h \ + Benchmark.h Dependencies.cpp Dependencies.h DeviceChange.cpp \ + DeviceChange.h DeviceManager.cpp DeviceManager.h Diags.cpp \ + Diags.h Envelope.cpp Envelope.h Experimental.h FFmpeg.cpp \ + FFmpeg.h FFT.cpp FFT.h FileIO.cpp FileIO.h FileNames.cpp \ + FileNames.h float_cast.h FreqWindow.cpp FreqWindow.h \ + HelpText.cpp HelpText.h HistoryWindow.cpp HistoryWindow.h \ ImageManipulation.cpp ImageManipulation.h InterpolateAudio.cpp \ InterpolateAudio.h LabelDialog.cpp LabelDialog.h \ LabelTrack.cpp LabelTrack.h LangChoice.cpp LangChoice.h \ @@ -1346,7 +1354,6 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/Makefile -.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ @@ -1964,7 +1971,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audacity-BatchProcessDialog.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audacity-Benchmark.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audacity-BlockFile.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audacity-CaptureEvents.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audacity-Dependencies.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audacity-DeviceChange.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audacity-DeviceManager.Po@am__quote@ @@ -2728,20 +2734,6 @@ audacity-Benchmark.obj: Benchmark.cpp @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -c -o audacity-Benchmark.obj `if test -f 'Benchmark.cpp'; then $(CYGPATH_W) 'Benchmark.cpp'; else $(CYGPATH_W) '$(srcdir)/Benchmark.cpp'; fi` -audacity-CaptureEvents.o: CaptureEvents.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -MT audacity-CaptureEvents.o -MD -MP -MF $(DEPDIR)/audacity-CaptureEvents.Tpo -c -o audacity-CaptureEvents.o `test -f 'CaptureEvents.cpp' || echo '$(srcdir)/'`CaptureEvents.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/audacity-CaptureEvents.Tpo $(DEPDIR)/audacity-CaptureEvents.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CaptureEvents.cpp' object='audacity-CaptureEvents.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -c -o audacity-CaptureEvents.o `test -f 'CaptureEvents.cpp' || echo '$(srcdir)/'`CaptureEvents.cpp - -audacity-CaptureEvents.obj: CaptureEvents.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -MT audacity-CaptureEvents.obj -MD -MP -MF $(DEPDIR)/audacity-CaptureEvents.Tpo -c -o audacity-CaptureEvents.obj `if test -f 'CaptureEvents.cpp'; then $(CYGPATH_W) 'CaptureEvents.cpp'; else $(CYGPATH_W) '$(srcdir)/CaptureEvents.cpp'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/audacity-CaptureEvents.Tpo $(DEPDIR)/audacity-CaptureEvents.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CaptureEvents.cpp' object='audacity-CaptureEvents.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -c -o audacity-CaptureEvents.obj `if test -f 'CaptureEvents.cpp'; then $(CYGPATH_W) 'CaptureEvents.cpp'; else $(CYGPATH_W) '$(srcdir)/CaptureEvents.cpp'; fi` - audacity-Dependencies.o: Dependencies.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -MT audacity-Dependencies.o -MD -MP -MF $(DEPDIR)/audacity-Dependencies.Tpo -c -o audacity-Dependencies.o `test -f 'Dependencies.cpp' || echo '$(srcdir)/'`Dependencies.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/audacity-Dependencies.Tpo $(DEPDIR)/audacity-Dependencies.Po @@ -6269,6 +6261,8 @@ uninstall-am: uninstall-binPROGRAMS uninstall-desktopDATA \ tags tags-am uninstall uninstall-am uninstall-binPROGRAMS \ uninstall-desktopDATA uninstall-dist_mimeDATA +.PRECIOUS: Makefile + # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff --git a/src/Menus.cpp b/src/Menus.cpp index b969785ce..558e4bf1b 100644 --- a/src/Menus.cpp +++ b/src/Menus.cpp @@ -117,7 +117,6 @@ simplifies construction of menu items. #include "widgets/HelpSystem.h" #include "DeviceManager.h" -#include "CaptureEvents.h" #include "Snap.h" #if defined(EXPERIMENTAL_CRASH_REPORT) diff --git a/src/Project.cpp b/src/Project.cpp index 854503a14..279971a6e 100644 --- a/src/Project.cpp +++ b/src/Project.cpp @@ -160,8 +160,6 @@ scroll information. It also has some status flags. #include "commands/Command.h" #include "commands/CommandType.h" -#include "CaptureEvents.h" - #include "../images/AudacityLogoAlpha.xpm" TrackList *AudacityProject::msClipboard = new TrackList(); diff --git a/src/WaveTrack.cpp b/src/WaveTrack.cpp index fd7902858..02f2c183f 100644 --- a/src/WaveTrack.cpp +++ b/src/WaveTrack.cpp @@ -2561,7 +2561,7 @@ constSamplePtr WaveTrackCache::Get(sampleFormat format, const sampleCount len0 = mPTrack->GetBestBlockSize(start0); wxASSERT(len0 <= mBufferSize); if (!mPTrack->Get(samplePtr(mBuffers[0].data), floatSample, start0, len0)) - return false; + return 0; mBuffers[0].start = start0; mBuffers[0].len = len0; if (!fillSecond && @@ -2587,7 +2587,7 @@ constSamplePtr WaveTrackCache::Get(sampleFormat format, const sampleCount len1 = mPTrack->GetBestBlockSize(start1); wxASSERT(len1 <= mBufferSize); if (!mPTrack->Get(samplePtr(mBuffers[1].data), floatSample, start1, len1)) - return false; + return 0; mBuffers[1].start = start1; mBuffers[1].len = len1; mNValidBuffers = 2; @@ -2637,7 +2637,7 @@ constSamplePtr WaveTrackCache::Get(sampleFormat format, // Very big request! // Fall back to direct fetch if (!mPTrack->Get(buffer, format, start, remaining)) - return false; + return 0; } return mOverlapBuffer.ptr(); diff --git a/src/effects/Contrast.cpp b/src/effects/Contrast.cpp index ab55f324e..11e51d6a4 100644 --- a/src/effects/Contrast.cpp +++ b/src/effects/Contrast.cpp @@ -464,7 +464,12 @@ void ContrastDialog::OnExport(wxCommandEvent & WXUNUSED(event)) wxString fName = wxT("contrast.txt"); fName = FileSelector(_("Export Contrast Result As:"), - wxEmptyString, fName, wxT("txt"), wxT("*.txt"), wxFD_SAVE | wxRESIZE_BORDER, this); + wxEmptyString, + fName, + wxT("txt"), + wxT("*.txt"), + wxFD_SAVE | wxRESIZE_BORDER, + this); if (fName == wxT("")) return; diff --git a/src/effects/Reverb.cpp b/src/effects/Reverb.cpp index 7ccd3e9e1..f282c2bec 100644 --- a/src/effects/Reverb.cpp +++ b/src/effects/Reverb.cpp @@ -220,7 +220,7 @@ sampleCount EffectReverb::ProcessBlock(float **inBlock, float **outBlock, sample while (remaining) { - size_t len = min((size_t) remaining, (size_t) BLOCK); + sampleCount len = wxMin(remaining, BLOCK); for (int c = 0; c < mNumChans; c++) { // Write the input samples to the reverb fifo. Returned value is the address of the @@ -311,7 +311,7 @@ wxArrayString EffectReverb::GetFactoryPresets() { wxArrayString names; - for (int i = 0; i < WXSIZEOF(FactoryPresets); i++) + for (size_t i = 0; i < WXSIZEOF(FactoryPresets); i++) { names.Add(wxGetTranslation(FactoryPresets[i].name)); } diff --git a/src/effects/lv2/LV2Effect.cpp b/src/effects/lv2/LV2Effect.cpp index f592e2ee0..22ce5c54b 100644 --- a/src/effects/lv2/LV2Effect.cpp +++ b/src/effects/lv2/LV2Effect.cpp @@ -46,13 +46,8 @@ #include "lv2/lv2plug.in/ns/extensions/ui/ui.h" #if defined(__WXGTK__) -#if wxCHECK_VERSION(3, 0, 0) #include #include "win_gtk.h" -#else -#include -#include -#endif #endif #if defined(__WXMSW__) @@ -1489,7 +1484,7 @@ bool LV2Effect::BuildFancy() //wxWindow *mContainer = mParent; #if defined(__WXGTK__) // Make sure the parent has a window - if (!GTK_WIDGET(mContainer->m_wxwindow)->window) + if (!gtk_widget_get_window(GTK_WIDGET(mContainer->m_wxwindow))) { gtk_widget_realize(GTK_WIDGET(mContainer->m_wxwindow)); } @@ -1545,7 +1540,6 @@ bool LV2Effect::BuildFancy() gtk_widget_set_size_request(widget, 1, 1); gtk_widget_set_size_request(widget, sz.width, sz.height); -#if wxCHECK_VERSION(3, 0, 0) wxPizza *pizza = WX_PIZZA(mContainer->m_wxwindow); pizza->put(widget, 0, //gtk_pizza_get_xoffset(pizza), @@ -1553,16 +1547,6 @@ bool LV2Effect::BuildFancy() sz.width, sz.height); gtk_widget_show_all(GTK_WIDGET(pizza)); -#else - GtkPizza *pizza = GTK_PIZZA(mContainer->m_wxwindow); - gtk_pizza_put(pizza, - widget, - 0, //gtk_pizza_get_xoffset(pizza), - 0, //gtk_pizza_get_yoffset(pizza), - sz.width, - sz.height); - gtk_widget_show_all(GTK_WIDGET(pizza)); -#endif si->SetMinSize(wxSize(sz.width, sz.height)); #elif defined(__WXMSW__) HWND widget = (HWND) suil_instance_get_widget(mSuilInstance); diff --git a/src/export/Export.cpp b/src/export/Export.cpp index 736994822..3a9938904 100644 --- a/src/export/Export.cpp +++ b/src/export/Export.cpp @@ -28,13 +28,6 @@ *//********************************************************************/ -// For compilers that support precompilation, includes "wx/wx.h". -#include - -#ifndef WX_PRECOMP -#include -#endif - #include #include #include @@ -48,6 +41,7 @@ #include #include #include +#include #include "Export.h" #include "ExportPCM.h" @@ -932,6 +926,11 @@ void Exporter::CreateUserPane(wxWindow *parent) void Exporter::OnFilterChanged(wxFileCtrlEvent & evt) { int index = evt.GetFilterIndex(); +printf("index = %d\n", index); + if (index < 0 || index >= (int) mPages.GetCount()) + { + return; + } if (mActivePage) { diff --git a/src/prefs/KeyConfigPrefs.cpp b/src/prefs/KeyConfigPrefs.cpp index dbd71e275..103795f04 100644 --- a/src/prefs/KeyConfigPrefs.cpp +++ b/src/prefs/KeyConfigPrefs.cpp @@ -75,8 +75,8 @@ END_EVENT_TABLE() KeyConfigPrefs::KeyConfigPrefs(wxWindow * parent) : PrefsPanel(parent, _("Keyboard")), mView(NULL), - mFilter(NULL), mKey(NULL), + mFilter(NULL), mFilterTimer(this, FilterTimerID), mFilterPending(false) { diff --git a/tests/Makefile.in b/tests/Makefile.in index 245e0660d..1bd2af450 100644 --- a/tests/Makefile.in +++ b/tests/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.14.1 from Makefile.am. +# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2013 Free Software Foundation, Inc. +# Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -14,7 +14,17 @@ @SET_MAKE@ VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -79,9 +89,6 @@ build_triplet = @build@ host_triplet = @host@ check_PROGRAMS = SequenceTest$(EXEEXT) SimpleBlockFileTest$(EXEEXT) subdir = tests -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(top_srcdir)/autotools/depcomp \ - $(top_srcdir)/autotools/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_c99_func_lrint.m4 \ $(top_srcdir)/m4/ac_c99_func_lrintf.m4 \ @@ -122,6 +129,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ac_c99_func_lrint.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/src/configwin.h \ $(top_builddir)/src/configunix.h @@ -405,6 +413,9 @@ TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/autotools/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(top_srcdir)/autotools/depcomp \ + $(top_srcdir)/autotools/test-driver DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ @@ -645,7 +656,6 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign tests/Makefile -.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ @@ -830,7 +840,7 @@ $(TEST_SUITE_LOG): $(TEST_LOGS) if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ - else \ + elif test -n "$$redo_logs"; then \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ @@ -1126,6 +1136,8 @@ uninstall-am: mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ recheck tags tags-am uninstall uninstall-am +.PRECIOUS: Makefile + # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded.