heronarts / LX

Core library for 3D LED lighting engines
https://chromatik.co/
Other
41 stars 25 forks source link

Colloquial way to link LX build w/ LXStudio #63

Closed nargetdev closed 2 years ago

nargetdev commented 2 years ago

What is the colloquial way to transfer freshly built LX libs for use with LXStudio?

I've just been doing (from root of LXStudio project, assuming LX and LXStudio adjacent):

cp ../LX/target/lx-0.4.1-jar-with-dependencies.jar ../LX/target/lx-0.4.1-javadoc.jar ../LX/target/lx-0.4.1-sources.jar ../LX/target/lx-0.4.1.jar lib

.. because these *.jar are indexed by git this seems like a bloated way of doing this, rather than a reference.

mcslee commented 2 years ago

Answer slightly depends on what IDE you're using and how you have build setup. But what you show here should work.

If you're working in Eclipse, and have imported both projects using Maven configuration, then having LX and LXStudio-IDE in the same Eclipse workspace should cause LXStudio-IDE to automatically build against your local copy of LX.

You can right click LXStudio-IDE in Eclipse and show Java Build Path to see where it's grabbing things. Example from my machine attached.

FYI - note that I'm doing LX development work now on the dev branch of LX, and that will be 0.4.2-SNAPSHOT rather than 0.4.1. If you're making local modifications against master then that'll still be 0.4.1 and should work fine. Though I'm from now on keeping iterative work off the master branch and only pushing it when there's a stable point release.

tl;dr - if the cp above is working fine you, perfectly fine to stick with that!

Screen Shot 2022-07-07 at 10 34 32 AM
Geethree commented 2 years ago

Hello hello! @mcslee it's been awhile!

Another way we can do this in a more java-y way

Anyways, lxstudio is in maven central now(!!). I've been building against it in gradle. That said the difficult thing is making sure processing with jogl, gluegen and native libraries are available.

Fortunately micycle is building and publishing some processing libraries.

repositories {
    mavenCentral()
    maven { url = "https://jitpack.io"}
}

dependencies {
    implementation group: 'com.heronarts', name: 'lxstudio', version: '0.4.1'
    implementation group: 'com.github.micycle1', name: 'processing-core-4', version: '4.0b8'
}

*Unfortunately.. this doesn't seem to current support MacOS M1 architecture.

I can successfully build and run a lxstudio project.

mcslee commented 2 years ago

And @nargetdev -to @Geethree 's point here, you shouldn't need to build/install LX libs whatsoever, unless you are making yourself a special modified build. Otherwise the Maven POM dependency is enough.

Yeah it's unfortunate that the Processing stuff isn't in Maven. FYI I also set up a one-off step in the P4LX repo to install the needed stuff to the local Maven Repo: https://github.com/heronarts/P4LX#maven-build-process

Just have to mvn validate from P4LX and then the Processing dependencies should be there on your system. Only has to be done once (until Processing version changes)

As for running on M1 - the way Processing includes the gluegen stuff has changed. You need to pass -Djava.library.path explicitly to the java invocation now for it to work, having the dependencies on the classpath is no longer enough, because the M1 natives won't be automatically loaded anymore. Processing 4 seems to use a sort of pre-release gluegen/jogl build... also not in Maven. Hopefully one day.

Bit of documentation on the -Djava.library.path here: https://github.com/heronarts/LXStudio-IDE#configure-your-runtime

nargetdev commented 2 years ago

I am doing stuff directly in LX - implemented the ThrowingBagels protocol https://github.com/iontank/ThrowingBagels, and working on a buffer reallocator tool for indexBuffer remapping (reorder, or duplication i.e. sending one strip in LX to multiple outputs on the same controller such as data_in and backup_in on the redundant data strips i.e. gs8206 ws2814).

ThrowingBagels seems to be spiritual successor of Yona's work with Light at Play https://github.com/Yona-Appletree/LEDscape Which is also a really great OPC server. I'm into the ThrowingBagels implementation though because of the RGB --> RGBW translation on the fly (from 3 byte data, not 4, so it works out of the box with LX for driving RGBW led) - definitely worth checking out.

I'm using intellij and the cp command above is functional however it is cumbersome - make changes, switch LXStudio intellij project, copy lib, run in context, switch LX intellij project, make changes, etc.

I've tried modifying my pom.xml to point the local file

        <dependency>
            <groupId>com.heronarts</groupId>
            <artifactId>lx</artifactId>
            <version>0.4.1</version>
            <scope>system</scope>
            <systemPath>/Users/mswhiskers/007/ethfs/01__SRC/LX/LX/target/lx-0.4.1.jar</systemPath>
        </dependency>

.. no error however this doesn't seem to reference the other .jar LXStudio uses the local one in the lib instead.. I'm gonna try symlinking it instead.

UPDATE: symlinking works

in the lib dir of LXStudio-IDE do..

rm lx-0.4.1*

ln -s $LX_PATH/target/lx-0.4.1*

Then all that would be needed for seamless workflow is a hook in intellij to mvn install on the LX repo if something changed.. for another day

mcslee commented 2 years ago

Nice, sounds cool.

Then all that would be needed for seamless workflow is a hook in intellij to mvn install on the LX repo if something changed.. for another day

Yup that sounds like the "right" fix - in Eclipse you can have two projects open at once, and it automatically notices when one is referenced from the other via pom.xml and automatically builds against the project version. It's pretty handy and doesn't require a full mvn install to the local m2 repo, but essentially the same outcome.

In the meantime symlinking seems perfectly workable.

FYI - LX does now support RGBW output on custom fixtures - but having the controller firmware do the conversion from 3 up to 4 output bytes definitely seems a better approach, no need to be sending that W pixel over the wire if it's purely generated from the RGB value.

mcslee commented 2 years ago

Closing this out for now as sounds like you've got a good solution in place, but feel free to re-open / comment if any more issues come up. Happy coding!

nargetdev commented 2 years ago

I found the RGBW implementation right after commenting it's almost identical to the one on the controller.

Regarding indexBuffer remapping - i saw this is more or less how your using segments (which can repeat) so i'm just using that API as intended now.

I'll make a PR of the ThrowingBagels implementation soon.. right now constructing the datagrams inside of LXStructure class because finality required on the indexBuffer upon construction of the datagram. This feels "wrong" in the sense that the datagram buffering structure should really be inside the ThrowingBagels class implementation but there's no place for that logic to go before super(...) wonder if you have any advice along those lines?

nargetdev commented 2 years ago

Should it be a wrapper class? ThrowingBagelsBufferPreparer .. which returns the final ThrowingBagels datagram?

mcslee commented 2 years ago

Yeah, so I looked at the ThrowingBagels thing and it's a little weird how it wants 2 packets, one with half the pixels and a 2nd packet with the 2nd half of the pixels. Did I understand that right? I was looking at https://github.com/iontank/ThrowingBagels/blob/master/src/net/README.md

This annoyingly makes it awkward to extend from the LXDatagram class, because it isn't actually a single datagram, it's two very coordinated datagrams. Here's what I would recommend. You stick to ThrowingBagelsDatagram extends LXDatagram, but make a static helper/factory method on there, something like:

public static ThrowingBagelsDatagram[] makeDatagrams(LX lx, IndexBuffer indexBuffer) {
  // Here you will have to deal with splitting up the IndexBuffer into two parts
  // first-half/second-half the way that ThrowingBagels wants the packets separated
  // Then you can generate the two ThrowingBagelDatagram instances and return them
  // in an array of length 2.
}

I think that's the most streamlined approach that I can think of. It's a slightly funny design, I'm curious to understand what the reasoning is for that two-packet approach.

mcslee commented 2 years ago

The most annoying part of this will be if the Segments in the IndexBuffer do not neatly split into two halfs, e.g. one segment is 40 long, another is 10 long. Bagels wants 25/25... so you'll have to detect this, split the 40 into 25+15, put the 25 in the first packet, then the 15+10 in the second packet.

All totally doable, just will be a bit of annoying array-manipulation code.

mcslee commented 2 years ago

The other thing I should mention - each Segment can have its own byte-order. So in theory one Segment could be 3-bytes-per-pixel and another could be 4-bytes-per-pixel. This will probably never come up in a realistic ThrowingBagels use case, since you'd be using all one or the other. It doesn't seem like the controller would even support mixed byte-lengths. But just something to be aware of that as you're implementing it. The byte length of each Segment is segment.indices.length * segment.byteOrder.getNumBytes()