{"id":13613853,"url":"https://github.com/Deep-Symmetry/dysentery","last_synced_at":"2025-04-13T18:31:47.056Z","repository":{"id":8272912,"uuid":"56949802","full_name":"Deep-Symmetry/dysentery","owner":"Deep-Symmetry","description":"Exploring ways to participate in a Pioneer Pro DJ Link network","archived":false,"fork":false,"pushed_at":"2025-03-31T04:55:51.000Z","size":13829,"stargazers_count":209,"open_issues_count":10,"forks_count":24,"subscribers_count":21,"default_branch":"main","last_synced_at":"2025-03-31T05:28:06.196Z","etag":null,"topics":["dj-link","network","pioneer"],"latest_commit_sha":null,"homepage":null,"language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"epl-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Deep-Symmetry.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"Deep-Symmetry","liberapay":"deep-symmetry","custom":"https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick\u0026hosted_button_id=LG5NLFL5T372W\u0026source=url"}},"created_at":"2016-04-24T02:12:33.000Z","updated_at":"2025-03-31T04:55:54.000Z","dependencies_parsed_at":"2024-01-17T00:18:57.271Z","dependency_job_id":"77e99829-a6ab-4bc1-be18-3ce842f380df","html_url":"https://github.com/Deep-Symmetry/dysentery","commit_stats":{"total_commits":485,"total_committers":9,"mean_commits":"53.888888888888886","dds":0.07216494845360821,"last_synced_commit":"0b72b12ff9c2d9c4992450bfaadb54cb6446eb37"},"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Deep-Symmetry%2Fdysentery","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Deep-Symmetry%2Fdysentery/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Deep-Symmetry%2Fdysentery/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Deep-Symmetry%2Fdysentery/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Deep-Symmetry","download_url":"https://codeload.github.com/Deep-Symmetry/dysentery/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248760405,"owners_count":21157351,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dj-link","network","pioneer"],"created_at":"2024-08-01T20:00:54.190Z","updated_at":"2025-04-13T18:31:46.336Z","avatar_url":"https://github.com/Deep-Symmetry.png","language":"Clojure","funding_links":["https://github.com/sponsors/Deep-Symmetry","https://liberapay.com/deep-symmetry","https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick\u0026hosted_button_id=LG5NLFL5T372W\u0026source=url","https://liberapay.com/deep-symmetry/donate","https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick\u0026hosted_button_id=M7EXPEX7CZN8Q"],"categories":["Clojure"],"sub_categories":[],"readme":"# dysentery\nExploring ways to participate in a Pioneer Pro DJ Link network.\n\n[![License](https://img.shields.io/github/license/Deep-Symmetry/dysentery?color=blue)](#license)\n[![project chat](https://img.shields.io/badge/chat-on%20zulip-brightgreen)](https://deep-symmetry.zulipchat.com/#narrow/stream/275855-dysentery-.26-crate-digger)\n\n## Quick Start\n\nTo watch and analyze the packets being sent between your Pioneer gear,\ndownload and run the latest `dysentery.jar` file from the\n[releases](https://github.com/brunchboy/dysentery/releases) page. You\nwill need a\n[Java runtime environment](https://java.com/inc/BrowserRedirect1.jsp)\nOnce you have a recent one installed, you can probably run dysentery\nby just double-clicking the jar file. See the [Status](#status)\nsection for more details, explanation, and a screen shot.\n\n\u003e :wrench: If you\u0026rsquo;re looking for a library to use in your own\n\u003e projects, that\u0026rsquo;s what\n\u003e [beat-link](https://github.com/brunchboy/beat-link#beat-link) was\n\u003e developed for, and\n\u003e [@EvanPurkhiser](https://github.com/EvanPurkhiser) is now also\n\u003e developing [prolink-connect](https://github.com/EvanPurkhiser/prolink-connect)\n\u003e if you\u0026rsquo;d like a TypeScript version.\n\u003e\n\u003e :star2: And if you want to synchronize shows without having to\n\u003e write your own software, check out\n\u003e [beat-link-trigger](https://github.com/brunchboy/beat-link-trigger#beat-link-trigger).\n\n## Disclaimer\n\nThis is in no way a sanctioned implementation of the protocols. It\nshould be obvious, but:\n\n\u003e :warning: Use at your own risk! For example, there are reports that\n\u003e the XDJ-RX crashes when dysentery starts, so don\u0026rsquo;t use it with one\n\u003e on your network. As Pioneer themselves\n\u003e [explain](https://forums.pioneerdj.com/hc/en-us/community/posts/203113059-xdj-rx-as-single-deck-on-pro-dj-link-),\n\u003e the XDJ-RX does not actually implement the protocol:\n\u003e\n\u003e \u0026ldquo;The LINK on the RX is ONLY for linking to rekordbox on your\n\u003e computer or a router with WiFi to connect rekordbox mobile. It can\n\u003e not exchange LINK data with other CDJs or DJMs.\u0026rdquo;\n\nWhile these techniques appear to work for us so far, there are many\ngaps in our knowledge, and things could change at any time with new\nreleases of hardware or even firmware updates from Pioneer.\n\nThat said, if you find anything wrong, or discover anything new,\n*please* [open an\nIssue](https://github.com/brunchboy/dysentery/issues), contact us on\nthe [Zulip\nstream](https://deep-symmetry.zulipchat.com/#narrow/stream/275855-dysentery-.26-crate-digger)\nor submit a pull request so we can all improve our understanding\ntogether.\n\n## Analysis\n\nA major goal of this project is the [Packet\nAnalysis](https://djl-analysis.deepsymmetry.org/), which is intended\nto be useful to anyone who wants to write code to interact with DJ\nLink networks. Check out what we have learned so far, and please help\nus figure out more if you can!\n\nThe packet captures used to create that document can be downloaded\n([Sections 1 and 2](doc/assets/powerup.pcapng),\n[Sections 3 and 4](doc/assets/to-virtual.pcapng)) so you can see if\nyou notice anything we have not, even if you don\u0026rsquo;t have any\nPioneer gear to try out.\n\n### Funding\n\nDysentery and its research products are, and will remain, completely\nfree and open-source. If they have helped you, taught you something,\nor inspired you, please let us know and share some of your discoveries\nand code. If you\u0026rsquo;d like to financially support this ongoing research,\nyou are welcome (but by no means obligated) to donate to offset the\nhundreds of hours of research, development, and writing that have\nalready been invested. Or perhaps to facilitate future efforts, tools,\ntoys, and time to explore.\n\n\u003ca href=\"https://liberapay.com/deep-symmetry/donate\"\u003e\u003cimg style=\"vertical-align:middle\" alt=\"Donate using Liberapay\"\n    src=\"https://liberapay.com/assets/widgets/donate.svg\"\u003e\u003c/a\u003e using Liberapay, or\n\u003ca href=\"https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick\u0026hosted_button_id=M7EXPEX7CZN8Q\"\u003e\u003cimg\n    style=\"vertical-align:middle\" alt=\"Donate\"\n    src=\"https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif\"\u003e\u003c/a\u003e using PayPal\n\n\u003e If enough people jump on board, we may even be able to get a newer\n\u003e CDJ to experiment with, although that\u0026rsquo;s an unlikely stretch goal.\n\u003e :grinning:\n\n## Getting Help\n\n\u003ca href=\"http://zulip.com\"\u003e\u003cimg align=\"right\" alt=\"Zulip logo\"\n src=\"doc/assets/zulip-icon-circle.svg\" width=\"128\" height=\"128\"\u003e\u003c/a\u003e\n\nDeep Symmetry\u0026rsquo;s projects are generously sponsored with hosting\nby \u003ca href=\"https://zulip.com\"\u003eZulip\u003c/a\u003e, an open-source modern team\nchat app designed to keep both live and asynchronous conversations\norganized. Thanks to them, you can \u003ca\nhref=\"https://deep-symmetry.zulipchat.com/#narrow/stream/275855-dysentery-.26-crate-digger\"\u003echat\nwith our community\u003c/a\u003e, ask questions, get inspiration, and share your\nown ideas.\n\n## Status\n\nDysentery is currently being developed as a\n[Clojure](http://clojure.org/) library, because I find that to be the\nmost powerful development environment available to me at the moment.\nOnce I figure things out well enough here, I implement them in\n[beat-link](https://github.com/brunchboy/beat-link#beat-link), which\nis intended to be useful in other projects: it is a standard Java\nlibrary available as a package from Maven Central. If you want to hack\non the dysentery source, you\u0026rsquo;ll need to learn a little bit about\nClojure. Finally,\n[beat-link-trigger](https://github.com/brunchboy/beat-link-trigger#beat-link-trigger)\nbuilds a friendly graphical interface on top of beat-link, making it\neasy to synchronize light shows, videos, and Ableton Live to tracks\nplayed on CDJs.\n\n\u003e As mentioned above, other people are implementing projects with the\n\u003e help of this research (and in many cases, contributing to the research\n\u003e itself). Nice examples include:\n\u003e\n\u003e * [Cardinia Mini](https://nudge.id.au/cardinia-mini/index.html)\n\u003e * [Prolink Tools](https://prolink.tools)\n\u003e * [prolink-go](https://github.com/EvanPurkhiser/prolink-go)\n\u003e * [python-prodj-link](https://github.com/flesniak/python-prodj-link)\n\nYou can run dysentery and look at what it finds on your network by\njust downloading and executing the jar, though, and we hope you will,\nto help us gather more information!\n\nIt is already able to watch for DJ Link traffic on all your network\ninterfaces, and tell you what devices have been noticed, and the local\nand broadcast addresses you will want to use when creating a virtual\nCDJ device to participate in that network.\n\nHere is an example of trying that out by running Dysentery as an\nexecutable jar on my network at home:\n\n```\n\u003e java -jar dysentery.jar\nLooking for DJ Link devices...\nFound:\n   CDJ-2000nexus /172.16.42.4\n   DJM-2000nexus /172.16.42.5\n   CDJ-2000nexus /172.16.42.6\n\nTo communicate create a virtual CDJ with address /172.16.42.2,\nMAC address 3c:15:c2:e7:08:6c, and use broadcast address /172.16.42.255\n\nClose any player window to exit.\n```\n\nIt also creates a virtual CDJ to ask those devices to send status\nupdates, and opens windows tracking the packets it receives from them.\nWhen a packet changes the value of one of the bytes displayed, the\nbackground of that byte is drawn in blue, which gradually fades back\nto black when the value is not changing. This helps to identify what\nparts of the packet change when you do something on the device being\nanalyzed.\n\nTo further focus analysis, if a byte has a value that we expect, it is\ncolored green; if it has an unexpected value, it is colored red. Bytes\nthat we don\u0026rsquo;t yet understand are colored white. If you see any\nwhite values changing, that is a puzzle that remains to be\nsolved\u0026mdash;see if you can identify any pattern, or figure out what\nthey might convey. If you do, or if any byte value shows up in red,\nplease [open an Issue](https://github.com/brunchboy/dysentery/issues)\nto let us know. Bytes which are expected to contain the device name\nand firmware version are rendered as text rather than hex, to make\nthem more readable.\n\n\u003cimg src=\"doc/assets/PacketWindow.png\" width=\"600\" alt=\"Packet Window\"\u003e\n\nUnderneath the raw byte values there is a timestamp which shows when\nthe most recent packet was received. As with the byte values, its\nbackground will flash blue when the timestamp changes, and fade to\nblack over the next second, until the next packet is received.\n\nBeneath the timestamp is a an interpretation of the meaning of the\npacket, as best we can currently understand it, with italic field\nlabels corresponding to the byte fields identified in the\n[beats](https://djl-analysis.deepsymmetry.org/djl-analysis/beats.html)\nand\n[status](https://djl-analysis.deepsymmetry.org/djl-analysis/vcdj.html)\nsections of the [Packet\nAnalysis](https://djl-analysis.deepsymmetry.org/).\n\n\u003e If you have access to any Pioneer Nexus gear, please run Dysentery\n\u003e and see if the results it gives seem to make sense for your\n\u003e equipment. So far it has only been tested with a pair of CDJ-2000\n\u003e nexus players and a DJM-2000 nexus mixer. Even better, if you can\n\u003e help us figure out more of the meanings of the packets, or identify\n\u003e things that we don\u0026rsquo;t yet have right, and thereby improve the\n\u003e analysis for everyone, please\n\u003e [open an Issue](https://github.com/brunchboy/dysentery/issues)!\n\nTo try this, download the latest `dysentery.jar` from the\n[releases](https://github.com/brunchboy/dysentery/releases) page, make\nsure you have a recent Java environment installed, and run it as shown\nabove.\n\nTo build it yourself, and play with it interactively, you will need to\nclone this repository and install [Leiningen](http://leiningen.org).\nThen, within the directory into which you cloned the repo, you can\ntype `lein repl` to enter a Clojure Read-Eval-Print-Loop with the\nproject loaded:\n\n```\n\u003e lein repl\nnREPL server started on port 53806 on host 127.0.0.1 - nrepl://127.0.0.1:53806\nREPL-y 0.3.7, nREPL 0.2.12\nClojure 1.8.0\nJava HotSpot(TM) 64-Bit Server VM 1.8.0_77-b03\ndysentery loaded.\ndysentery.core=\u003e\n```\n\nAt that point, you can evaluate Clojure expressions:\n\n```clojure\n(view/find-devices)\n;; =\u003e Looking for DJ Link devices...\n;; =\u003e Found:\n;; =\u003e   CDJ-2000nexus /172.16.42.5\n;; =\u003e   DJM-2000nexus /172.16.42.3\n;; =\u003e   CDJ-2000nexus /172.16.42.4\n;; =\u003e\n;; =\u003e To communicate create a virtual CDJ with address /172.16.42.2,\n;; =\u003e MAC address 3c:15:c2:e7:08:6b, and use broadcast address /172.16.42.255\nnil\n```\n\nTo log details about beat packets from a particular player (this was\nbuilt to help get the details of Beat Link\u0026rsquo;s `BeatSender`\nimplementation correct), bring up the device windows using\n`(view/find-devices)` from the REPL as shown above, then evaluate an\nexpression like:\n\n```clojure\n(view/log-beats 3 \"/Users/james/Desktop/beats.txt\")\n```\n\n\u003e This causes all beats from the player 3 to be logged to the\n\u003e specified file, producing output like this:\n\n```\nStarting beat log for device 3 at Sat Sep 01 15:17:23 CDT 2018\n\nBeat at   0.444, skew:   n/a, B_b: 2 [1 @status +117, beat:  285], BPM: 129.0, pitch: +0.00%\nBeat at   0.910, skew:   1ms, B_b: 3 [2 @status + 76, beat:  286], BPM: 129.0, pitch: +0.00%\nBeat at   1.375, skew:   0ms, B_b: 4 [3 @status + 53, beat:  287], BPM: 129.0, pitch: +0.00%\nBeat at   1.841, skew:   0ms, B_b: 1 [4 @status + 55, beat:  288], BPM: 129.0, pitch: +0.00%\n```\n\nTo stop the beat logger (without having to exit dysentery):\n\n```clojure\n(view/log-beats)\n```\n\nTo build the executable jar:\n\n```\n\u003e lein uberjar\nCompiling dysentery.core\nCompiling dysentery.finder\nCompiling dysentery.util\nCompiling dysentery.vcdj\nCompiling dysentery.view\nCreated /Users/james/git/dysentery/target/dysentery-0.1.0-SNAPSHOT.jar\nCreated /Users/james/git/dysentery/target/dysentery.jar\n```\n\n### History\n\nThis research began in the summer of 2015 as I was trying to figure\nout a reliable way to synchronize\n[Afterglow](https://github.com/brunchboy/afterglow#afterglow) light\nshows with performances on my CDJs. I broke out\n[Wireshark](https://www.wireshark.org) and after staring at packet\ncaptures over a weekend, I was able to identify how to track the\ncurrent BPM and beat locations by passively watching broadcast\ntraffic, which was my main goal. I still could not get a lock on where\nthe down beat fell, because I could not tell which player was the\nMaster.\n\n#### Virtual CDJ\n\nIn the spring of 2016 I saw a posting on the original\n[VJ Forums thread](http://vjforums.info/threads/cdj-2000-ethernet-protocol-for-live-bpm-sync.39265/page-2#post-295258)\nwhere we had been discussing this, announcing that\n[Diogo Santos](mailto:diogommsantos@gmail.com) had made an important\nbreakthrough. By broadcasting packets that pretended to be a CDJ, his\nsoftware was able to get the other players to start sending it more\ndetails, including information I had not been able to find in other\nways. He was kind enough to share his code, and that was the impetus\nbehind starting this project, to consolidate what people are learning\nabout this protocol, and make it available for other projects to\nbenefit from.\n\n#### Initial metadata breakthrough\n\nIn December 2016 I heard from\n[@EvanPurkhiser](https://github.com/EvanPurkhiser), who had found this\nproject, and went on to make important breakthroughs in obtaining track\nmetadata.\n\n#### Robust metadata understanding\n\nIn May 2017 [Austin Wright](https://bitbucket.org/awwright/) contacted\nme on the (retired) Afterglow\n[Gitter channel](https://gitter.im/brunchboy/afterglow) and told me\nabout some really cool work he was doing. He was even gracious enough\nto publish a bunch of\n[source code](https://bitbucket.org/awwright/libpdjl) that I\u0026rsquo;ve been\nable to use to get a much deeper understanding of how metadata queries\nwork, and to gain access to things like beat grid information (and\neventually track waveform images). This is the current area of active\nresearch.\n\n#### Sync control and tempo mastery\n\nIn the summer of 2018 I dug into implementing more of the protocol, so\nthat the virtual CDJ could send its own status updates and beat\npackets, become tempo master and control the tempo and beat grid, as\nwell as telling other devices to turn sync on or off, or become tempo\nmaster. Also figured out how to respond correctly when the nexus mixer\ntold the virtual CDJ to do those things.\n\n#### nxs2 and beyond\n\nThroughout the succeeding years we continued to expand our knowledge\nand ability to use more elements of the protocols and data files,\nincluding new nxs2 features like colored and named cues, phrase\nanalysis (thanks to [Michael Ganss](https://github.com/mganss)), and\ntowards the end of 2020 we figured out how to support new CDJ-3000\nfeatures, including supporting six channels and exciting new packets\nwith very valuable information contributed by [David\nNg](https://github.com/nudge).\n\n### Why Dysentery?\n\nThe name of this project is a reference to one of the infamous hazards faced in\n[The Oregon Trail](https://en.wikipedia.org/wiki/The_Oregon_Trail_%28video_game%29),\na game which helped many students in the eighties and nineties understand what life\nwas like for pioneers exploring the American West. Since we are exploring the\nprotocol used by Pioneer gear, it seemed at least slightly appropriate. And, ok, I\nhave a hard time resisting forced puns. Let\u0026rsquo;s hope none of us see:\n\n![You have died of dysentery](doc/assets/died-of-dysentery.jpg)\n\n## License\n\n\u003ca href=\"http://deepsymmetry.org\"\u003e\u003cimg align=\"right\" alt=\"Deep Symmetry\"\n src=\"doc/assets/DS-logo-github.png\" width=\"250\" height=\"150\"\u003e\u003c/a\u003e\n\nCopyright © 2016–2023 [Deep Symmetry, LLC](http://deepsymmetry.org)\n\nDistributed under the\n[Eclipse Public License 1.0](http://opensource.org/licenses/eclipse-1.0.php),\nthe same as Clojure. By using this software in any fashion, you are\nagreeing to be bound by the terms of this license. You must not remove\nthis notice, or any other, from this software. A copy of the license\ncan be found in\n[LICENSE](https://rawgit.com/brunchboy/dysentery/master/LICENSE)\nwithin this project.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FDeep-Symmetry%2Fdysentery","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FDeep-Symmetry%2Fdysentery","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FDeep-Symmetry%2Fdysentery/lists"}