1 // -*- c-basic-offset: 4 -*-
2 
3 /** @file hugin1/base_wx/platform.cpp
4  *
5  *  @brief various platfrom specific wxWidgets functions
6  *
7  *  @author Pablo d'Angelo <pablo.dangelo@web.de>
8  *
9  *  $Id: huginApp.cpp 2510 2007-10-28 22:24:11Z dangelo $
10  *
11  *  This program is free software; you can redistribute it and/or
12  *  modify it under the terms of the GNU General Public
13  *  License as published by the Free Software Foundation; either
14  *  version 2 of the License, or (at your option) any later version.
15  *
16  *  This software is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  *  General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public
22  *  License along with this software. If not, see
23  *  <http://www.gnu.org/licenses/>.
24  *
25  */
26 
27 #include "platform.h"
28 
29 #include <hugin_utils/utils.h>
30 #include <vigra/imageinfo.hxx>
31 
32 /** return vector of known extensions of raw files */
GetRawExtensions()33 std::vector<std::string> GetRawExtensions()
34 {
35     std::vector<std::string> rawExt{ "dng", "crw", "cr2","cr3","raw","erf","raf","mrw","nef","orf","rw2","pef","srw","arw" };
36     return rawExt;
37 };
38 
39 /** build filter string "*.ext", adds also upper case version for UNIX paths when needed */
GetFilterExtensions(const wxString & ext)40 wxString GetFilterExtensions(const wxString& ext)
41 {
42     wxString extensionString("*.");
43     extensionString.Append(ext);
44     if (wxFileName::IsCaseSensitive())
45     {
46         extensionString.Append(";*.").Append(ext.Upper());
47     };
48     return extensionString;
49 };
50 
GetVigraImageFilter()51 wxString GetVigraImageFilter()
52 {
53     wxString filterString;
54     const std::string extensions = vigra::impexListExtensions();
55     std::vector<std::string> exts = hugin_utils::SplitString(extensions, " ");
56     if (exts.empty())
57     {
58         // if something goes wrong, add some defaults
59         exts.push_back("tif");
60         exts.push_back("tiff");
61         exts.push_back("jpg");
62         exts.push_back("jpeg");
63         exts.push_back("png");
64     }
65     filterString.Append(_("All Image files")).Append("|");
66     for (auto& ext : exts)
67     {
68         filterString.Append(GetFilterExtensions(ext)).Append(";");
69     };
70     // remove last character == ";"
71     filterString.RemoveLast();
72     filterString.Append("|");
73     return filterString;
74 };
75 
GetFileDialogImageFilters()76 wxString GetFileDialogImageFilters()
77 {
78     wxString filterString=GetVigraImageFilter();
79     filterString.Append(_("JPEG files (*.jpg,*.jpeg)")).Append("|").Append(GetFilterExtensions("jpg")).Append(";").Append(GetFilterExtensions("jpeg"));
80     filterString.Append("|").Append(_("TIFF files (*.tif,*.tiff)")).Append("|").Append(GetFilterExtensions("tif")).Append(";").Append(GetFilterExtensions("tiff"));
81     filterString.Append("|").Append(_("PNG files (*.png)")).Append("|").Append(GetFilterExtensions("png"));
82     filterString.Append("|").Append(_("HDR files (*.hdr)")).Append("|").Append(GetFilterExtensions("hdr"));
83     filterString.Append("|").Append(_("EXR files (*.exr)")).Append("|").Append(GetFilterExtensions("exr"));
84     filterString.Append("|").Append(_("All files (*)")).Append("|*");
85     return filterString;
86 }
87 
GetFileDialogImageAndRawFilters()88 wxString GetFileDialogImageAndRawFilters()
89 {
90     wxString filterString = GetVigraImageFilter();
91     // now the raw formats
92     std::vector<std::string> exts = GetRawExtensions();
93     filterString.Append(_("Raw files")).Append("|");
94     for (auto& ext : exts)
95     {
96         filterString.Append(GetFilterExtensions(ext)).Append(";");
97     };
98     // remove last character == ";"
99     filterString.RemoveLast();
100     filterString.Append("|");
101     // now add some image format at its own
102     filterString.Append(_("JPEG files (*.jpg,*.jpeg)")).Append("|").Append(GetFilterExtensions("jpg")).Append(";").Append(GetFilterExtensions("jpeg"));
103     filterString.Append("|").Append(_("TIFF files (*.tif,*.tiff)")).Append("|").Append(GetFilterExtensions("tif")).Append(";").Append(GetFilterExtensions("tiff"));
104     filterString.Append("|").Append(_("PNG files (*.png)")).Append("|").Append(GetFilterExtensions("png"));
105     filterString.Append("|").Append(_("HDR files (*.hdr)")).Append("|").Append(GetFilterExtensions("hdr"));
106     filterString.Append("|").Append(_("EXR files (*.exr)")).Append("|").Append(GetFilterExtensions("exr"));
107     return filterString;
108 };
109 
IsRawExtension(const wxString & testExt)110 bool IsRawExtension(const wxString& testExt)
111 {
112     std::vector<std::string> rawExts = GetRawExtensions();
113     for (auto& ext : rawExts)
114     {
115         if (testExt.CmpNoCase(wxString(ext.c_str(), wxConvLocal)) == 0)
116         {
117             return true;
118         };
119     };
120     return false;
121 };
122 
123 #if defined __WXMAC__ || defined __WXOSX_COCOA__
124 
125 #include <CoreFoundation/CFBundle.h>
126  #include "wx/osx/core/cfstring.h"
127 #include <iostream>
128 #include <stdio.h>
129 #include "wx/utils.h"
130 
131 using namespace std;
132 
133 // note this is a "create" function for ownership
MacCreateCFStringWithWxString(const wxString & string)134 CFStringRef MacCreateCFStringWithWxString(const wxString& string)
135 {
136     return CFStringCreateWithCString(NULL,
137                                      (const char*)string.mb_str(wxConvUTF8),
138                                      kCFStringEncodingUTF8);
139 
140 }
141 
MacGetPathToMainExecutableFileOfBundle(CFStringRef bundlePath)142 wxString MacGetPathToMainExecutableFileOfBundle(CFStringRef bundlePath)
143 {
144     wxString theResult = wxT("");
145 
146     CFURLRef bundleURL = CFURLCreateWithFileSystemPath(NULL, bundlePath, kCFURLPOSIXPathStyle, TRUE);
147 
148     if(bundleURL == NULL)
149     {
150         DEBUG_INFO("Mac: CFURL from string (" << bundlePath << ") failed." );
151         return theResult;
152     }
153 
154     CFBundleRef bundle = CFBundleCreate(NULL, bundleURL);
155     CFRelease(bundleURL);
156 
157     if(bundle == NULL)
158     {
159         DEBUG_INFO("Mac: CFBundleCreate (" << bundlePath << " ) failed" );
160     }
161     else
162     {
163         CFURLRef PTOurl = CFBundleCopyExecutableURL(bundle);
164         CFRelease( bundle );
165         if(PTOurl == NULL)
166         {
167             DEBUG_INFO("Mac: Cannot locate the executable in the bundle.");
168         }
169         else
170         {
171             CFURLRef PTOAbsURL = CFURLCopyAbsoluteURL( PTOurl );
172             CFRelease( PTOurl );
173             if(PTOAbsURL == NULL)
174             {
175                 DEBUG_INFO("Mac: Cannot convert the file path to absolute");
176             }
177             else
178             {
179                 CFStringRef pathInCFString = CFURLCopyFileSystemPath(PTOAbsURL, kCFURLPOSIXPathStyle);
180                 CFRelease( PTOAbsURL );
181                 if(pathInCFString == NULL)
182                 {
183                     DEBUG_INFO("Mac: Failed to get URL in CFString");
184                 }
185                 else
186                 {
187                     CFRetain( pathInCFString );
188                     theResult =  wxCFStringRef(pathInCFString).AsString(wxLocale::GetSystemEncoding());
189                     DEBUG_INFO("Mac: the executable's full path in the application bundle: " << theResult.mb_str(wxConvLocal));
190                 }
191             }
192         }
193     }
194     return theResult;
195 }
196 
MacGetPathToMainExecutableFileOfRegisteredBundle(CFStringRef BundleIdentifier)197 wxString MacGetPathToMainExecutableFileOfRegisteredBundle(CFStringRef BundleIdentifier)
198 {
199     wxString theResult = wxT("");
200 
201 	FSRef appRef;
202 	CFURLRef bundleURL;
203 	FSRef actuallyLaunched;
204 	OSStatus err;
205 	FSRef documentArray[1]; // Don't really need an array if we only have 1 item
206 	LSLaunchFSRefSpec launchSpec;
207 	//Boolean  isDir;
208 
209 	err = LSFindApplicationForInfo(kLSUnknownCreator,
210 								   CFSTR("net.sourceforge.hugin.PTBatcherGUI"),
211 								   NULL,
212 								   &appRef,
213 								   &bundleURL);
214 	if (err != noErr) {
215 		// error, can't find PTBatcherGUI
216 		cout << "PTBatcherGui check failed \n" << endl;
217 		wxMessageBox(wxString::Format(_("External program %s not found in the bundle, reverting to system path"), wxT("open")), _("Error"));
218 	}
219     if(bundleURL == NULL)
220     {
221         DEBUG_INFO("Mac: CFURL from string (" << bundleURL << ") failed." );
222         return theResult;
223     }
224 
225     CFBundleRef bundle = CFBundleCreate(NULL, bundleURL);
226     CFRelease(bundleURL);
227 
228     if(bundle == NULL)
229     {
230         DEBUG_INFO("Mac: CFBundleCreate (" << bundleURL << " ) failed" );
231     }
232     else
233     {
234         CFURLRef PTOurl = CFBundleCopyExecutableURL(bundle);
235         CFRelease( bundle );
236         if(PTOurl == NULL)
237         {
238             DEBUG_INFO("Mac: Cannot locate the executable in the bundle.");
239         }
240         else
241         {
242             CFURLRef PTOAbsURL = CFURLCopyAbsoluteURL( PTOurl );
243             CFRelease( PTOurl );
244             if(PTOAbsURL == NULL)
245             {
246                 DEBUG_INFO("Mac: Cannot convert the file path to absolute");
247             }
248             else
249             {
250                 CFStringRef pathInCFString = CFURLCopyFileSystemPath(PTOAbsURL, kCFURLPOSIXPathStyle);
251                 CFRelease( PTOAbsURL );
252                 if(pathInCFString == NULL)
253                 {
254                     DEBUG_INFO("Mac: Failed to get URL in CFString");
255                 }
256                 else
257                 {
258                     CFRetain( pathInCFString );
259                     theResult =  wxCFStringRef(pathInCFString).AsString(wxLocale::GetSystemEncoding());
260                     DEBUG_INFO("Mac: the executable's full path in the application bundle: " << theResult.mb_str(wxConvLocal));
261                 }
262             }
263         }
264     }
265 	cout << "PTBatcherGui check returned  value " << theResult << "\n" << endl;
266     return theResult;
267 }
268 
269 #if defined MAC_SELF_CONTAINED_BUNDLE
270 
MacGetPathToBundledAppMainExecutableFile(CFStringRef appname)271 wxString MacGetPathToBundledAppMainExecutableFile(CFStringRef appname)
272 {
273     wxString theResult = wxT("");
274 
275     CFBundleRef mainbundle = CFBundleGetMainBundle();
276     if(mainbundle == NULL)
277     {
278         DEBUG_INFO("Mac: Not bundled");
279     }
280     else
281     {
282         CFURLRef XRCurl = CFBundleCopyResourceURL(mainbundle, appname, NULL, NULL);
283         if(XRCurl == NULL)
284         {
285             DEBUG_INFO("Mac: Cannot locate the bundle in bundle.");
286         }
287         else
288         {
289             CFBundleRef bundledBundle = CFBundleCreate(NULL, XRCurl);
290             CFRelease( XRCurl );
291 
292             if(bundledBundle == NULL)
293             {
294                 DEBUG_INFO("Mac: Not bundled");
295             }
296             else
297             {
298                 CFURLRef PTOurl = CFBundleCopyExecutableURL(bundledBundle);
299                 CFRelease( bundledBundle );
300 
301                 if(PTOurl == NULL)
302                 {
303                     DEBUG_INFO("Mac: Cannot locate the executable in the bundle.");
304                 }
305                 else
306                 {
307                     CFURLRef PTOAbsURL = CFURLCopyAbsoluteURL( PTOurl );
308                     CFRelease( PTOurl );
309                     if(PTOAbsURL == NULL)
310                     {
311                         DEBUG_INFO("Mac: Cannot convert the file path to absolute");
312                     }
313                     else
314                     {
315                         CFStringRef pathInCFString = CFURLCopyFileSystemPath(PTOAbsURL, kCFURLPOSIXPathStyle);
316                         CFRelease( PTOAbsURL );
317                         if(pathInCFString == NULL)
318                         {
319                             DEBUG_INFO("Mac: Failed to get URL in CFString");
320                         }
321                         else
322                         {
323                             CFRetain( pathInCFString );
324                             theResult =  wxCFStringRef(pathInCFString).AsString(wxLocale::GetSystemEncoding());
325                             DEBUG_INFO("Mac: the executable's full path in the application bundle: " << theResult.mb_str(wxConvLocal));
326                         }
327                     }
328                 }
329             }
330         }
331     }
332     return theResult;
333 }
334 
MacGetPathToBundledResourceFile(CFStringRef filename)335 wxString MacGetPathToBundledResourceFile(CFStringRef filename)
336 {
337     wxString theResult = wxT("");
338 
339     CFBundleRef mainbundle = CFBundleGetMainBundle();
340     if(mainbundle == NULL)
341     {
342         DEBUG_INFO("Mac: Not bundled");
343     }
344     else
345     {
346         CFURLRef XRCurl = CFBundleCopyResourceURL(mainbundle, filename, NULL, NULL);
347         if(XRCurl == NULL)
348         {
349             DEBUG_INFO("Mac: Cannot locate the file in bundle.");
350         }
351         else
352         {
353             CFStringRef pathInCFString = CFURLCopyFileSystemPath(XRCurl, kCFURLPOSIXPathStyle);
354             CFRelease( XRCurl );
355             if(pathInCFString == NULL)
356             {
357                 DEBUG_INFO("Mac: Failed to get URL in CFString");
358             }
359             else
360             {
361                 CFRetain( pathInCFString );
362                 theResult = wxCFStringRef(pathInCFString).AsString(wxLocale::GetSystemEncoding());
363                 DEBUG_INFO("Mac: the resource file's path in the application bundle: " << theResult.mb_str(wxConvLocal));
364             }
365         }
366     }
367     return theResult;
368 }
369 
MacGetPathToBundledFrameworksDirectory()370 wxString MacGetPathToBundledFrameworksDirectory()
371 {
372     wxString theResult = wxT("");
373 
374     CFBundleRef mainbundle = CFBundleGetMainBundle();
375     if(mainbundle == NULL)
376     {
377         DEBUG_INFO("Mac: Not bundled");
378     }
379     else
380     {
381         CFURLRef XRCurl = CFBundleCopyBundleURL(mainbundle);
382         if(XRCurl == NULL)
383         {
384             DEBUG_INFO("Mac: Cannot locate the file in bundle.");
385         }
386         else
387         {
388             CFStringRef pathInCFString = CFURLCopyFileSystemPath(XRCurl, kCFURLPOSIXPathStyle);
389             CFRelease( XRCurl );
390             if(pathInCFString == NULL)
391             {
392                 DEBUG_INFO("Mac: Failed to get URL in CFString");
393             }
394             else
395             {
396                 CFRetain( pathInCFString );
397                 theResult = wxCFStringRef(pathInCFString).AsString(wxLocale::GetSystemEncoding());
398                 DEBUG_INFO("Mac: the Frameworks file's path in the application bundle: " << theResult.mb_str(wxConvLocal));
399             }
400         }
401     }
402     return theResult + wxT("/Contents/Frameworks");
403 }
404 
MacGetPathToBundledExecutableFile(CFStringRef filename)405 wxString MacGetPathToBundledExecutableFile(CFStringRef filename)
406 {
407     wxString theResult = wxT("");
408 
409     CFBundleRef mainbundle = CFBundleGetMainBundle();
410     if(mainbundle == NULL)
411     {
412         DEBUG_INFO("Mac: Not bundled");
413     }
414     else
415     {
416         CFURLRef PTOurl = CFBundleCopyAuxiliaryExecutableURL(mainbundle, filename);
417         if(PTOurl == NULL)
418         {
419             DEBUG_INFO("Mac: Cannot locate the file in the bundle.");
420         }
421         else
422         {
423             CFURLRef PTOAbsURL = CFURLCopyAbsoluteURL( PTOurl );
424             if(PTOAbsURL == NULL)
425             {
426                 DEBUG_INFO("Mac: Cannot convert the file path to absolute");
427             }
428             else
429             {
430                 CFStringRef pathInCFString = CFURLCopyFileSystemPath(PTOAbsURL, kCFURLPOSIXPathStyle);
431                 CFRelease( PTOAbsURL );
432                 if(pathInCFString == NULL)
433                 {
434                     DEBUG_INFO("Mac: Failed to get URL in CFString");
435                 }
436                 else
437                 {
438                     CFRetain( pathInCFString );
439                     theResult =  wxCFStringRef(pathInCFString).AsString(wxLocale::GetSystemEncoding());
440                     DEBUG_INFO("Mac: executable's full path in the application bundle: " << theResult.mb_str(wxConvLocal));
441                 }
442             }
443             CFRelease( PTOurl );
444         }
445     }
446     return theResult;
447 }
448 
MacGetPathToUserDomainTempDir()449 wxString MacGetPathToUserDomainTempDir()
450 {
451     wxString tmpDirPath = wxT("");
452 
453     FSRef tempDirRef;
454     OSErr err = FSFindFolder(kUserDomain, kTemporaryFolderType, kCreateFolder, &tempDirRef);
455     if (err == noErr)
456     {
457         CFURLRef tempDirURL = CFURLCreateFromFSRef(kCFAllocatorSystemDefault, &tempDirRef);
458         if (tempDirURL != NULL)
459         {
460             CFStringRef tmpPath = CFURLCopyFileSystemPath(tempDirURL, kCFURLPOSIXPathStyle);
461             CFRetain(tmpPath);
462             tmpDirPath = wxCFStringRef(tmpPath).AsString(wxLocale::GetSystemEncoding());
463             CFRelease(tempDirURL);
464         }
465     }
466 
467     return tmpDirPath;
468 }
469 
MacGetPathToUserAppSupportAutoPanoFolder()470 wxString MacGetPathToUserAppSupportAutoPanoFolder()
471 {
472     wxString appSupportAutoPanoFolder = wxT("");
473 
474     FSRef appSupportFolder;
475     OSErr err = FSFindFolder(kUserDomain,kApplicationSupportFolderType,kDontCreateFolder,&appSupportFolder);
476     if( err == noErr)
477     {
478         CFURLRef appSupportFolderURL = CFURLCreateFromFSRef(kCFAllocatorDefault,&appSupportFolder);
479         CFURLRef appSupportHugin = CFURLCreateCopyAppendingPathComponent(kCFAllocatorDefault,appSupportFolderURL,CFSTR("Hugin"),true);
480         CFURLRef autopanoURL = CFURLCreateCopyAppendingPathComponent(kCFAllocatorDefault,appSupportHugin,CFSTR("Autopano"),true);
481         CFStringRef tmpPath = CFURLCopyFileSystemPath(autopanoURL,  kCFURLPOSIXPathStyle);
482         CFRetain(tmpPath);
483         appSupportAutoPanoFolder = wxCFStringRef(tmpPath).AsString(wxLocale::GetSystemEncoding());
484         CFRelease(autopanoURL);
485     }
486     return appSupportAutoPanoFolder;
487 }
488 
489 
490 #endif // MAC_SELF_CONTAINED_BUNDLE
491 
492 #endif // __WXMAC__
493 
getInvalidCharacters()494 const wxString getInvalidCharacters()
495 {
496 #if defined __WXMSW__
497     // the characters :"*?<>| are not allowed in filenames, these are handled well by the file dialog
498     // all other characters should work
499     return wxEmptyString;
500 #else
501     // the characters =;:% does not work with the makefile
502     // we are also rejecting the characters <>*?| which are principally allowed in filenames but will probably make problems when used
503     // the double quote does not work with the panotools file format, so also reject
504     //@BUG tilde ~ and backslash \ are not working with vigraimpex, if this works again these characters can be removed from the list
505     return wxT("*?<>|\"\\~");
506 #endif
507 };
508 
containsInvalidCharacters(const wxString stringToTest)509 bool containsInvalidCharacters(const wxString stringToTest)
510 {
511     if(stringToTest.IsEmpty())
512         return false;
513     wxString forbiddenChars=getInvalidCharacters();
514     for(unsigned int j=0;j<forbiddenChars.size();j++)
515     {
516         if(stringToTest.Find(forbiddenChars[j])!=wxNOT_FOUND)
517             return true;
518     };
519     return false;
520 };
521 
ShowFilenameWarning(wxWindow * parent,const wxArrayString filelist)522 void ShowFilenameWarning(wxWindow* parent, const wxArrayString filelist)
523 {
524     wxDialog dlg;
525     wxXmlResource::Get()->LoadDialog(&dlg, parent, wxT("dlg_warning_filename"));
526     XRCCTRL(dlg, "dlg_warning_text", wxStaticText)->SetLabel(wxString::Format(_("The filename(s) contains one of the following invalid characters: %s\nHugin can not work with these filenames. Please rename your file(s) and try again."), getInvalidCharacters().c_str()));
527     XRCCTRL(dlg, "dlg_warning_list", wxListBox)->Append(filelist);
528     dlg.Fit();
529     dlg.CenterOnScreen();
530     dlg.ShowModal();
531 };
532 
533 #if wxUSE_ON_FATAL_EXCEPTION
GenerateReport(wxDebugReport::Context ctx)534 void GenerateReport(wxDebugReport::Context ctx)
535 {
536     //from the debugrpt sample inspired
537     wxDebugReportCompress report;
538     report.AddAll(ctx);
539     if (wxDebugReportPreviewStd().Show(report))
540     {
541         if (report.Process())
542         {
543             wxLogMessage(_("Debug report generated in \"%s\"."), report.GetCompressedFileName().c_str());
544             report.Reset();
545         };
546     };
547 };
548 #endif
549