1
0
mirror of https://github.com/cookiengineer/audacity synced 2026-02-16 15:57:52 +01:00

Fixes detection problems on Mac and possibly Windows (Bug #290)

This should fix the detection problems on the Mac and may even help with issues
on Windows and Linux.

On any of the platforms, the main issue is the search path for libraries and
how absolute path names are handled.  The Mac seems to be especially
susceptible since there isn't one concrete location where libraries are stored.

Windows handles absolute paths differently and allows runtime updates to the
environment variables (and if push comes to shove, provides the
SetDllDirectory() function), so if problems still exist, they should be easy to
circumvent.

This patch does three things:

1)  It adds a shell script on OSX that takes care of starting Audacity after
reassigning and clearing the DYLD_LIBRARY_PATH environment variable.  This will
allow loading of libraries from their absolute path rather than searching
DYLD_LIBRARY_PATH first.  This script should be transparent to the user, but it
will affect people running Audacity with gdb as they will have to specifically
target Audacity.app/Contents/MacOS/Audacity instead of the Audacity.app bundle.
 Not big deal really.  If ppl no enough to use gdb from the command line, they
should be able to figure it out.

2)  It corrects detection of a monolithic FFmpeg library.  This is one where
avformat, avcodec, and avutil have all been linked into one large library.  The
main issue here was that under OSX and Linux, looking for symbols that should
reside in avutil and avcodec, would always succeed since dlsym() on these
platforms not only scans the requested library, but any dependent libraries as
well.  And when avformat was loaded, it would pull in it's dependent libraries
as well.

Another issue here was the if it was determined that the library was not
monolithic, the library was never unloaded, so those dependent libraries may
have come from the wrong location since they would have been loaded via the
normal search paths and not by absolute path name.

3)  It adds a method to FileNames which returns the full path name of a loaded
module that contains an address.  In the case of FFmpeg, it is used to verify
that a routine from a specific library is actually being used from that library
or not.  It is also used to show (in Help->Show log) the directory from which a
library was actually loaded.
This commit is contained in:
lllucius
2011-02-23 01:41:40 +00:00
parent 6c147de4ab
commit 07661c186f
6 changed files with 127 additions and 31 deletions

View File

@@ -19,6 +19,7 @@ License: GPL v2. See License.txt.
#include "Audacity.h" // for config*.h
#include "FFmpeg.h"
#include "AudacityApp.h"
#include "FileNames.h"
#include <wx/file.h>
@@ -674,12 +675,12 @@ bool FFmpegLibs::ValidLibsLoaded()
bool FFmpegLibs::InitLibs(wxString libpath_format, bool showerr)
{
wxString syspath;
bool pathfix = false;
FreeLibs();
#if defined(__WXMSW__)
wxString syspath;
bool pathfix = false;
wxLogMessage(wxT("Looking up PATH environment variable..."));
// First take PATH environment variable and store its content.
if (wxGetEnv(wxT("PATH"),&syspath))
@@ -728,55 +729,57 @@ bool FFmpegLibs::InitLibs(wxString libpath_format, bool showerr)
wxFileName name(libpath_format);
bool gotError = false;
// Check for a monolithic avformat
avformat = new wxDynamicLibrary();
wxLogDebug(wxT("Loading avformat from '%s'."), libpath_format.c_str());
// Vaughan, 2010-08-17: No explanation why logging was turned off, so commented these out.
//wxLogWindow* pLogger = wxGetApp().mLogger;
//if (showerr)
// pLogger->SetActiveTarget(NULL);
gotError = !avformat->Load(libpath_format, wxDL_LAZY);
//if (showerr)
// pLogger->SetActiveTarget(pLogger);
wxLogDebug(wxT("Checking for monolithic avformat from '%s'."), name.GetFullPath().c_str());
gotError = !avformat->Load(name.GetFullPath(), wxDL_LAZY);
// Verify it really is monolithic
if (!gotError) {
if (avformat->HasSymbol(wxT("av_free"))) {
util = avformat;
wxFileName actual;
actual = FileNames::PathFromAddr(avformat->GetSymbol(wxT("avutil_version")));
if (actual.GetPath().IsSameAs(name.GetPath())) {
actual = FileNames::PathFromAddr(avformat->GetSymbol(wxT("avcodec_version")));
if (actual.GetPath().IsSameAs(name.GetPath())) {
util = avformat;
codec = avformat;
}
}
if (avformat->HasSymbol(wxT("avcodec_init"))) {
codec = avformat;
if (util == NULL || codec == NULL) {
wxLogDebug(wxT("avformat not monolithic"));
avformat->Unload();
util = NULL;
codec = NULL;
}
else {
wxLogDebug(wxT("avformat is monolithic"));
}
}
if (!util) {
name.SetFullName(GetLibAVUtilName());
avutil = util = new wxDynamicLibrary();
avutil = util = new wxDynamicLibrary();
wxLogDebug(wxT("Loading avutil from '%s'."), name.GetFullPath().c_str());
//if (showerr)
// pLogger->SetActiveTarget(NULL);
util->Load(name.GetFullPath(), wxDL_LAZY);
//if (showerr)
// pLogger->SetActiveTarget(pLogger);
}
if (!codec) {
name.SetFullName(GetLibAVCodecName());
avcodec = codec = new wxDynamicLibrary();
wxLogDebug(wxT("Loading avcodec from '%s'."), name.GetFullPath().c_str());
//if (showerr)
// pLogger->SetActiveTarget(NULL);
codec->Load(name.GetFullPath(), wxDL_LAZY);
//if (showerr)
// pLogger->SetActiveTarget(pLogger);
}
if (!avformat->IsLoaded()) {
//if (showerr)
// pLogger->SetActiveTarget(NULL);
gotError = !avformat->Load(libpath_format, wxDL_LAZY);
//if (showerr)
// pLogger->SetActiveTarget(pLogger);
name.SetFullName(libpath_format);
wxLogDebug(wxT("Loading avformat from '%s'."), name.GetFullPath().c_str());
gotError = !avformat->Load(name.GetFullPath(), wxDL_LAZY);
}
#if defined(__WXMSW__)
//Return PATH to normal
if ( pathfix )
{
@@ -784,6 +787,7 @@ bool FFmpegLibs::InitLibs(wxString libpath_format, bool showerr)
wxLogMessage(wxT("Returning PATH to previous setting..."));
wxSetEnv(wxT("PATH"),oldpath.c_str());
}
#endif
if (gotError) {
wxLogError(wxT("Failed to load FFmpeg libraries."));
@@ -791,6 +795,20 @@ bool FFmpegLibs::InitLibs(wxString libpath_format, bool showerr)
return false;
}
// Show the actual libraries loaded
if (avutil) {
wxLogDebug(wxT("Actual avutil path %s"),
FileNames::PathFromAddr(avutil->GetSymbol(wxT("avutil_version"))).c_str());
}
if (avcodec) {
wxLogDebug(wxT("Actual avcodec path %s"),
FileNames::PathFromAddr(avcodec->GetSymbol(wxT("avcodec_version"))).c_str());
}
if (avformat) {
wxLogDebug(wxT("Actual avformat path %s"),
FileNames::PathFromAddr(avformat->GetSymbol(wxT("avformat_version"))).c_str());
}
wxLogDebug(wxT("Importing symbols..."));
INITDYN(avformat,av_register_all);
INITDYN(avformat,av_open_input_file);