leadedge / ofxNDI

An Openframeworks addon to allow sending and receiving images over a network using the NewTek Network Device Protocol.
GNU General Public License v3.0
134 stars 48 forks source link

not working in macOS #49

Closed dimitre closed 5 months ago

dimitre commented 6 months ago

I've made some changes in a fork to make it work locally basically I've renamed libs/NDI/export to libs/NDI/lib updated addon_config.mk and copied libndi.dylib to libs/NDI/lib/osx https://github.com/dimitre/ofxNDI

leadedge commented 6 months ago

Thanks Dimitre, ofxNDIdynloader uses the installed NDI runtime to find the required dll. Does this mean that the runtime installation fails to install the required file? "libndi.dylib"?

dimitre commented 6 months ago

Yes, the installed installs the lib in /usr/local/lib/libndi.dylib and ofxNDIdynloader was trying in two different paths. I can test later and report which paths but none of them were /usr/local/lib/libndi.dylib

leadedge commented 6 months ago

I think this could be a more significant problem. Loading from a local file is a workaround and finding the cause is best in the long run.

@eduardfrigola @moebiussurfing any ideas?

leadedge commented 5 months ago

Any results on this?

I have updated the NDI include and dll files to 5.6.1.

For Windows, I can confirm that the runtime installer downloads correctly from "http://ndi.link/NDIRedistV5" and installs to "C:\Program Files\NDI\NDI 5 Runtime\v5\" and the environment variable used by ofxNDIdynLoader "NDI_RUNTIME_DIR_V5" is the same path.

leadedge commented 5 months ago

Another update to NDI 6.0.0.0 I confirmed for Windows that the new runtime installer downloads from http://ndi.link/NDIRedistV6, installs to "C:\Program Files\NDI\NDI 6 Runtime\v6" and the environment variables "NDI_RUNTIME_DIR_V5" and "NDI_RUNTIME_DIR_V6" are both the same path. I will close this now, but if you have any further information, please advise here.

leadedge commented 4 months ago

Dimitre - did you ever find out what the two different paths were that ofxNDIdynloader was trying? The dynamic loading must work because I can never update libndi.dylib.

eduardfrigola commented 4 months ago

Hi @leadedge, sorry for not replying earlier...

When you posted this I tried to replicate the issue with no luck. I had (still have) a working setup, where I install the libndi in the default location usr/local/lib In my machine [M2 Max // macOS 13.2.1 // Xcode 14.2] I can open the library as expected with the system dlopen() call. https://github.com/leadedge/ofxNDI/blob/93e90e5ad63d0b81c14820195854880be623566b/src/ofxNDIdynloader.cpp#L198

But last week I was with another computer using the library, and this problem appeared. The machine is a M2 Ultra, with macOS 14.2 and Xcode 15.2. In this machine, when executing via Xcode everything seems fine, but when executing the standalone app, the library not loaded error pops up.

Tying to find an easy workaround for the situation, I found out that using the app build with the previous machine (macOS 13.2.1 / Xcode 14.2) it runs and finds the library as expected, so seems the issue is not with macOS 14.2 but with Xcode 15.2 builds.

Searching the possible issue in that direction I found some things that reaffirmed my suspicions: https://developer.apple.com/forums/thread/737920 https://github.com/mesonbuild/meson/issues/12288

As I can understand in this threads, usr/local/lib is not a default location for searching paths for dlopen().

All this using libndi 5.6.0. Maybe libndi 6.x.x solves that issue and installs the library in another location?

I still have not resolved the issue when compiling from Xcode 15, @dimitre fork should work, but I will try to make it work with an installed version of libndi instead of a local one.

Eduard

leadedge commented 4 months ago

Thanks very much Eduard.

The question is what path is returned for the NDI runtime. This is ndi_path returned from FindRuntime(). It should be the same location as for the official installation of the NDI runtime downloaded from http://ndi.link/NDIRedistV6

Correction - that is for windows. It should be

http://ndi.link/NDIRedistV6Apple

We expect this to be usr/local/lib. If the library is installed at this location and ndi_path is the same folder, it should work. If the locations are different, as Dimitri says, this could be another problem related to NDI. It could be a version issue as you suggest.

leadedge commented 4 months ago

Some observations. The NDI SDK documentation says -

On the Mac, it is not possible to specify global environment variable -- the redistributable on MacOS is installed within /usr/local/lib

If that's the case, the result of querying the environment variable might not be correct, and a hard-coded path to /usr/local/lib might be necessary. Also if there is a problem loading a library from /usr/local/lib, can the file be copied to another folder, the executable folder, and loaded from there?

dimitre commented 4 months ago

I've just tested now again. I've installed libNDI v6 and it is correctly installed in /usr/local/lib here is the output of ZSH (default shell) export command to show env variables

HOME=/Users/d
HOMEBREW_CELLAR=/opt/homebrew/Cellar
HOMEBREW_PREFIX=/opt/homebrew
HOMEBREW_REPOSITORY=/opt/homebrew
INFOPATH=/opt/homebrew/share/info:
LC_CTYPE=UTF-8
LOGNAME=d
MANPATH=/opt/homebrew/share/man::
OLDPWD=/Users/d
PATH=/opt/homebrew/opt/node@18/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/Users/d/.cargo/bin:/Users/d/ofbuild
PWD=/Users/d
SHELL=/bin/zsh
SHLVL=1
SSH_AUTH_SOCK=/private/tmp/com.apple.launchd.XXXX/Listeners
TERM=xterm-256color
TERM_PROGRAM=Apple_Terminal
TERM_PROGRAM_VERSION=447.1
TERM_SESSION_ID=A0270C9E-65CC-447B-A89A-70E92AEEA3DF
TMPDIR=/var/folders/8t/mhj0ns1n3j3cmgkkl8q5xk8h0000gp/T/
USER=d
XPC_FLAGS=0x0
XPC_SERVICE_NAME=0
__CFBundleIdentifier=com.apple.Terminal
ccache=/opt/homebrew/bin/ccache

and software output

NDI runtime location libndi.dylib
Couldn't load dynamic library at: libndi.dylib

ofxNDI example sender - 32 bit
 (https://www.ndi.tv/)
ofxNDIsend::CreateSender - not initialized

it seems to me it will try to load the library in the same app folder

just as a quick test, it works if I change this define to the full path

#           define NDILIB_LIBRARY_NAME  "/usr/local/lib/libndi.dylib"
leadedge commented 4 months ago

Thanks Dimitre,

the NDI runtime environment variable is clearly not in the list, so there is no use in testing for it. If the full path works for you, it can be used directly in "FindRuntime" and I have made the changes to try.

If loading still fails for Xcode 15.2, the library file will have to be copied to the application folder. I have included a section explaining library installation in the readme and can extend that slightly if there is still a problem.

I have found that a re-boot is required before Windows environment variables can be accessed. Fortunately, a registry read works around it until the machine is re-started. I have also changed from deprecated NDIlib_v4 to NDIlib_v5 p_NDILib, changed "libs/NDI/export/vs" to "libs/NDI/bin/vs" to align with the current NDI SDK folder naming and updated to NDI 6.0.1.0. All this is now in the Master branch and hopefully it will get a bit closer to a solution.

dimitre commented 4 months ago

All good now! working with installed libNDI v6 just fyi, there are some .exe added to the repository

dimitre commented 4 months ago

Thank you @leadedge

leadedge commented 4 months ago

That's good news. Thanks for your time and the heads up on extra files.