Making Remotemaster's library loading more flexible

Discussion forum for JP1 software tools currently in use, or being developed, such as IR, KM, RemoteMaster, and other misc apps/tools.

Moderator: Moderators

Post Reply
Barf
Expert
Posts: 1525
Joined: Fri Oct 24, 2008 1:54 pm
Location: Munich, Germany
Contact:

Making Remotemaster's library loading more flexible

Post by Barf »

Remotemaster depends heavily on the external loadable libraries DecodeIR, jp12serial, jp1parallell, jp1usb (.dll on windows, called .so on Linux and others). It loads these libraries from a subdirectory of the installation directory, called e.g. Windows or Linux-amd64. There is presently no possibility to load libraries located elsewhere, for example in a shared system directory like ...Program Files\Common Files\jp1\libs or /usr/local/lib. In contrast, most Java programs respects the system property java.libraries.path, pointing to a system directory where to load dynamic libraries. This can be given with the -Djava.libraries.path=... option when invoking the JVM.

I propose the fix included at the end of this posting. It will make RM(IR) first search the "old" local location, then the system location.

Nothing will change for the user who has installed in the "old" way. No internet connection is needed. :wink:

If someone requests a RemoteMaster.jar to test with, just say so.

No answer is taken as approval. :wink:

Code: Select all

Index: com/hifiremote/jp1/RemoteMaster.java
===================================================================
--- com/hifiremote/jp1/RemoteMaster.java        (revision 1081)
+++ com/hifiremote/jp1/RemoteMaster.java        (working copy)
@@ -2533,7 +2533,7 @@
         sb.append( "</ul>" );
 
         sb.append( "<p>Libraries loaded from " );
-        sb.append( LibraryLoader.getLibraryFolder() );
+        sb.append( LibraryLoader.getLibraryFolder() != null ? LibraryLoader.getLibraryFolder() : "system path." );
         sb.append( "</p></html>" );
 
         JEditorPane pane = new JEditorPane( "text/html", sb.toString() );
Index: com/hifiremote/LibraryLoader.java
===================================================================
--- com/hifiremote/LibraryLoader.java   (revision 1081)
+++ com/hifiremote/LibraryLoader.java   (working copy)
@@ -33,27 +33,44 @@
     {
       String mappedName = System.mapLibraryName( libraryName );
       File libraryFile = new File( libraryFolder, mappedName );
-      System.err.println( "Loading " + libraryFile.getAbsolutePath() );
-      System.load( libraryFile.getAbsolutePath() );
-      System.err.println( "Loaded " + libraryFile.getAbsolutePath() );
-      libraries.put( libraryName, mappedName );
+      System.err.println( "Trying to load " + libraryFile.getAbsolutePath() );
+      try
+      {
+         System.load(libraryFile.getAbsolutePath());
+         System.err.println("Loaded " + libraryFile.getAbsolutePath());
+         libraries.put(libraryName, mappedName);
+      }
+      catch (UnsatisfiedLinkError ex)
+      {
+         System.err.println("Loading of " + libraryFile.getAbsolutePath() + " failed, trying system path.");
+         loadLibrary(libraryName);
+      }
     }
   }
 
   public static void loadLibrary( String libraryName ) throws UnsatisfiedLinkError
   {
-    if ( libraries.get( libraryName ) == null )
+    if (libraries.get(libraryName) == null)
     {
-      System.err.println( "Loading " + libraryName );
-      System.loadLibrary( libraryName );
-      System.err.println( "Loaded " + libraryName );
-      libraries.put( libraryName, libraryName );
+      System.err.println("Trying to load " + libraryName + " from system path" );
+      try
+      {
+         System.loadLibrary(libraryName);
+         System.err.println("Loaded " + libraryName);
+         libraries.put(libraryName, libraryName);
+         libraryFolder = null;
+       }
+       catch (UnsatisfiedLinkError ex)
+       {
+          System.err.println("Loading of " + libraryName + " from system path failed.");
+          throw (ex);
+       }
     }
   }
 
   public static String getLibraryFolder()
   {
-    return libraryFolder.getAbsolutePath();
+    return libraryFolder != null ? libraryFolder.getAbsolutePath() : null;
   }
 
   protected static HashMap< String, String > libraries = new HashMap< String, String >();
gfb107
Expert
Posts: 3411
Joined: Sun Aug 03, 2003 7:18 pm
Location: Cary, NC
Contact:

Post by gfb107 »

I don't see the need for this change. Are there other libraries you expect to integrate into RMIR? Is your installer going to put the bundled libraries in a different place than simply unzipping currently does?
eferz
Expert
Posts: 1078
Joined: Thu Jun 03, 2010 1:25 am
Location: Austin, Texas

Post by eferz »

gfb107 wrote:I don't see the need for this change. Are there other libraries you expect to integrate into RMIR? Is your installer going to put the bundled libraries in a different place than simply unzipping currently does?
I believe the idea is to enable the ability to have a "global library directory" so that one doesn't need to maintain the same libraries used by different tools in separate folders. Although, one would think if someone cared enough to do this that they would use ln (linux/unix) or mklink (windows) to create symbolic links.
Remotes; JP1.2: Comcast URC-1067, JP1.3: Insignia NS-RC02U-10A, JP1.4 OARI06G, JP2.1: Cox URC-8820-MOTO (still trying to figure out how to make them self-aware.)
gfb107
Expert
Posts: 3411
Joined: Sun Aug 03, 2003 7:18 pm
Location: Cary, NC
Contact:

Post by gfb107 »

I get that. I'm a big believer in not changing code unless there is a use case driving the change. We don't currently have any plans to integrate other libraries with RMIR.

For example, we have a need to support moving RemoteMaster.properties and rmaster.err out of the installation folder because it is standard practice in *nix and newer versions of Windows to restrict writing to the installation folder. User's have reported runtime difficulties because of this. So I support making that change.

I don't see anything like that here. Sure it would be more standard. But that's not enough in my book.
eferz
Expert
Posts: 1078
Joined: Thu Jun 03, 2010 1:25 am
Location: Austin, Texas

Post by eferz »

gfb107 wrote:I get that. I'm a big believer in not changing code unless there is a use case driving the change. We don't currently have any plans to integrate other libraries with RMIR.

I don't see anything like that here. Sure it would be more standard. But that's not enough in my book.
I agree with you, maybe not for the same reasons. In my case, I've always been frustrated with "shared libraries". I understand its implementation when we had itty bitty drives 10 to 40MB that costs thousands of dollars. However, now that there are drives in the order of terabytes for less than a hundred its not necessary.

In fact, when I in technical support for xyz software, there would be nothing but frustration coming from me when I got calls because abc software was installed. It replaced the dynamic linked libraries which cause this person to call for help about our software. Guh! Just thinking about it irritates me.

Anyways, like I said there are OS utilities which allows you to create symbolic links should someone want to create a unified directory. So, I agree with you in deeming it unnecessary.

However, now that we're talking about libraries. Is there a mechanism to keep the individual libraries up to date? Or do you guys prefer packaging updated libraries with the new versions of the software? I'm guessing it is the latter but just wanted to get your thoughts.
Remotes; JP1.2: Comcast URC-1067, JP1.3: Insignia NS-RC02U-10A, JP1.4 OARI06G, JP2.1: Cox URC-8820-MOTO (still trying to figure out how to make them self-aware.)
Barf
Expert
Posts: 1525
Joined: Fri Oct 24, 2008 1:54 pm
Location: Munich, Germany
Contact:

Post by Barf »

gfb107 wrote:I get that. I'm a big believer in not changing code unless there is a use case driving the change..
The use case is to allow people (like myself) to maintain one or several dynamic libraries separately, for example on the system level, possibly using experimental versions. Is it likely that a user would like to update, say, DecodeIR? And then, for more than on of the invoking programs?

And, yes, it is "standard" in that experienced users/administrator expects it to behave in that way, i.e. to respect java.libraries.path. It is a matter of organizing and structuring, not of saving a megabyte of disk space. "Single sourcing".

BTW, my programs IrpMaster and IrMaster implements the scheme already: first try to load locally, then in the system location.

The behavior of the installer should stay as it is, installing the shared libraries locally, at least as default.
Are there other libraries you expect to integrate into RMIR?
No, rather the other way around. I translated MakeHex and ExchangeIR (partially) to Java recently...
Although, one would think if someone cared enough to do this that they would use ln (linux/unix) or mklink (windows) to create symbolic links.
Oh well... Links are a kludge. Links are to the file system roughly what GOTO is to programming. It destroys the directed acyclic graph that otherwise the file system forms. It makes paths non-unique. It may make a command like "cd .." sometimes behave differently from what you expect. If there is no other way, a link may come in handy, but a real fix of a problem is of course much preferable to a kludge. (Otherwise I would not suggest it.)
Is there a mechanism to keep the individual libraries up to date?
No, there is not. They are not even kept in svn, or in another version system, at least to my knowledge. The version of DecodeIR.dll distributed with the current Remotemaster is not even the current official version, IIRC.

Summing up, users may like to install their shared libraries locally (once per program) or collected together. Both these two use cases have their advantages and disadvantages. But for "us", it is desirable to support both. The proposed fix has no (known) disadvantages, and will not change anything for the user who wants to keep everything like it was. And the code is already written.
gfb107
Expert
Posts: 3411
Joined: Sun Aug 03, 2003 7:18 pm
Location: Cary, NC
Contact:

Post by gfb107 »

OK, just as long as we continue to put the libraries that RMIR uses in the same folder they are now. Users who are want to share a single copy of a library can manually move/delete files to accomplish that.
Post Reply