djm-fix.cpp
branchv_0
changeset 16 63154f9d24a2
parent 13 334b727f7516
child 18 358a601bfe81
     1.1 --- a/djm-fix.cpp	Tue Apr 15 22:44:31 2025 +0200
     1.2 +++ b/djm-fix.cpp	Tue Apr 15 22:45:25 2025 +0200
     1.3 @@ -1,6 +1,6 @@
     1.4  /**
     1.5   * DJM-Fix
     1.6 - * Copyright © 2020 František Kučera (Frantovo.cz, GlobalCode.info)
     1.7 + * Copyright © 2025 František Kučera (Frantovo.cz, GlobalCode.info)
     1.8   *
     1.9   * This program is free software: you can redistribute it and/or modify
    1.10   * it under the terms of the GNU General Public License as published by
    1.11 @@ -33,69 +33,86 @@
    1.12  }
    1.13  
    1.14  /**
    1.15 - * The support for Pioneer DJ DJM-250MK2 (an external USB sound card / mixer) was added to the Linux (kernel) by these patches:
    1.16 + * The support for Pioneer DJ DJM-250MK2 (an external  USB  sound  card / mixer)
    1.17 + * was added to the Linux (kernel) by these patches:
    1.18   *
    1.19 - *  - https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/sound/usb?id=73d8c94084341e2895169a0462dbc18167f01683 (playback)
    1.20 - *  - https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/sound/usb?id=14335d8b9e1a2bf006f9d969a103f9731cabb210 (recording)
    1.21 - *  - https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/sound/usb?id=cdc01a1558dedcee3daee7e1802d0349a07edb87 (mixer setup)
    1.22 + * https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/...
    1.23 + *   - ...sound/usb?id=73d8c94084341e2895169a0462dbc18167f01683 (playback)
    1.24 + *   - ...sound/usb?id=14335d8b9e1a2bf006f9d969a103f9731cabb210 (recording)
    1.25 + *   - ...sound/usb?id=cdc01a1558dedcee3daee7e1802d0349a07edb87 (mixer setup)
    1.26   *
    1.27 - * These patches are enough for playback and for recording from post CH faders.
    1.28 + * These patches are enough for playback and for recording from post CH  faders.
    1.29   *
    1.30 - * However this mixer is somehow incapacitated and if we want to record the raw signal from the PHONO or LINE channels,
    1.31 - * we only get silence. This feature is important for DVS (Digital Vinyl Systems) setups where
    1.32 - * the timecode signal from special control vinyls flows from mixer to the computer
    1.33 - * where it is interpreted in a software like MIXXX and used for controlling the playback of files on our computer.
    1.34 - * The signal (usually music) from these files flows back to the mixer and then to speakers and headphones.
    1.35 + * However this mixer is somehow incapacitated and if we want to record the  raw
    1.36 + * signal  from the PHONO or LINE channels, we only get silence. This feature is
    1.37 + * important for DVS (Digital Vinyl Systems) setups where  the  timecode  signal
    1.38 + * from  special  control  vinyls  flows  from mixer to the computer where it is
    1.39 + * interpreted in a software like MIXXX and used for controlling the playback of
    1.40 + * files on our computer. The signal (usually music) from these files flows back
    1.41 + * to the mixer and then to speakers and headphones.
    1.42   *
    1.43 - * To make this work and enjoy all the features of the device we have bought, we need to tell the mixer that we
    1.44 - * want the signal instead of silence on given channels. And this is the purpose of the djm-fix utility and
    1.45 - * it is done by sending some magic packet to the mixer.
    1.46 + * To make this work and enjoy all the features of the device we have bought, we
    1.47 + * need  to  tell  the mixer that we want the signal instead of silence on given
    1.48 + * channels. And this is the purpose of the djm-fix utility and it  is  done  by
    1.49 + * sending some magic packet to the mixer.
    1.50   *
    1.51 - * Implementation of this magic in the AlsaBridge.cpp file is based on publicly available documentation
    1.52 - * that can be found at <https://mixb.me/CDJHidProtocol/hid-analysis/handshake.html>.
    1.53 - * This page pointed me to the proper hash function (according to the constants, it is bit uncommon but publicly known Fowler–Noll–Vo hash function, FNV)
    1.54 - * and some magic bits. I wrote this standalone C++ program that talks with the mixer over MIDI SysEx messages and does the magic.
    1.55 + * Implementation of this magic in the AlsaBridge.cpp file is based on  publicly
    1.56 + * available documentation that can be found at:
    1.57 + *   - https://swiftb0y.github.io/CDJHidProtocol/hid-analysis/handshake.html
    1.58 + *   - https://mixb.me/CDJHidProtocol/hid-analysis/handshake.html (formerly).
    1.59 + * This page pointed me to the proper hash function (according to the constants,
    1.60 + * it  is bit uncommon but publicly known Fowler–Noll–Vo hash function, FNV) and
    1.61 + * some magic bits. I wrote this standalone C++  program  that  talks  with  the
    1.62 + * mixer over MIDI SysEx messages and does the magic.
    1.63   *
    1.64 - * When this program is started, it finds the mixer and makes it fully working.
    1.65 - * It needs to be running all the time, otherwise we will get silence on the PHONO/LINE channels again.
    1.66 + * When this program is started, it finds the mixer and makes it fully  working.
    1.67 + * It needs to be running all the time, otherwise we will get silence
    1.68 + * on the PHONO/LINE channels again.
    1.69   *
    1.70   * Install dependencies:
    1.71 - *   apt install mercurial make pkg-config g++ libasound2-dev    # in Debian or Ubuntu (it will be similar in other distributions)
    1.72 + *   apt install mercurial make pkg-config g++ libasound2-dev
    1.73 + * (in Debian or Ubuntu - it will be similar in other distributions)
    1.74   *
    1.75   * Download djm-fix:
    1.76 - *   hg clone https://hg.frantovo.cz/midi/djm-fix/               # primary source
    1.77 - *   hg clone https://hg.globalcode.info/midi/djm-fix/           # or we can use this mirror
    1.78 + *   hg clone https://hg.frantovo.cz/midi/djm-fix/        # primary source
    1.79 + *   hg clone https://hg.globalcode.info/midi/djm-fix/    # mirror
    1.80   *
    1.81   * Compile:
    1.82 - *   make                                                        # we can skip this step, it will be compiled on the first run
    1.83 + *   make                                                 # can be skipped
    1.84   *
    1.85   * Run:
    1.86 - *   make run                                                    # in most cases
    1.87 - *   build/djm-fix 'Pioneer DJ.*'                                # or provide custom name pattern (regular expression) to select the proper card
    1.88 + *   make run                                             # in most cases
    1.89 + *   build/djm-fix 'Pioneer DJ.*'                         # with custom name
    1.90 + *                 ^ regular expression to select desired card
    1.91   *
    1.92   * Stop:
    1.93   *   press Ctrl+C
    1.94   * 
    1.95 - * Look for updates in the Mercurial repositories and at <https://blog.frantovo.cz/c/387/>.
    1.96 + * Look for updates in the Mercurial repositories and at:
    1.97 + *   - https://blog.frantovo.cz/c/387/
    1.98   */
    1.99  
   1.100  int main(int argc, char**argv) {
   1.101  	using L = djmfix::logging::Level;
   1.102 -	std::unique_ptr<djmfix::logging::Logger> logger(djmfix::logging::create(std::cerr, L::INFO));
   1.103 +	std::unique_ptr<djmfix::logging::Logger>
   1.104 +			logger(djmfix::logging::create(std::cerr, L::INFO));
   1.105  	try {
   1.106  		logger->log(L::INFO, "DJM-Fix started.");
   1.107  		std::string cardNamePattern = argc == 2 ? argv[1] : "Pioneer DJ.*";
   1.108  
   1.109  		signal(SIGINT, interrupt);
   1.110  		std::unique_ptr<djmfix::DJMFix> djmFix(djmfix::create(logger.get()));
   1.111 -		std::unique_ptr<djmfix::alsa::AlsaBridge> alsaBridge(djmfix::alsa::create(djmFix.get(), cardNamePattern, logger.get()));
   1.112 +		std::unique_ptr<djmfix::alsa::AlsaBridge> alsaBridge(
   1.113 +				djmfix::alsa::create(djmFix.get(),
   1.114 +				cardNamePattern,
   1.115 +				logger.get()));
   1.116  
   1.117  		alsaBridge->start();
   1.118  		while (run) std::this_thread::sleep_for(std::chrono::milliseconds(100));
   1.119 -		
   1.120 +
   1.121  		std::cerr << std::endl;
   1.122  		logger->log(L::INFO, "DJM-Fix stopping.");
   1.123 -		
   1.124 +
   1.125  		alsaBridge->stop();
   1.126  
   1.127  		return 0;