#!/bin/sh # hwremap-patch.sh: remap hardware buttons on a standalone MPC or Force. An LD_PRELOAD shim # (hwremap) sits on the controller's MIDI and turns a chosen button into other buttons, a pad # or a touchscreen tap. The library and the two example configs are embedded below. # # ADVANCED AND OPT-IN. It changes how the device starts MPC. Read the warnings. Not part of any plugin. # # sh hwremap-patch.sh status # sh hwremap-patch.sh options [--layout mpc-live|force] # sh hwremap-patch.sh install [--layout mpc-live|force] [--options LIST] [--with LIST] [--without LIST] [--confirmed] # sh hwremap-patch.sh uninstall [--confirmed] # sh hwremap-patch.sh help # Run it ON the device as root, after copying this one file there. # The Force map is made of options (which button does what). On a terminal install asks which to # turn on; --options (an exact list, or all / none), --with and --without choose without asking, and # options lists them. Only a config that does not exist yet is written, so the choice applies to a # first install; edit /sdcard/hwremap.conf afterwards. # # Two install styles, picked from the device: # Hakai (a launcher /usr/bin/az01-launch-MPC): the library goes to /usr/lib/hwremap.so and that # launcher's LD_PRELOAD lines gain it. The root filesystem is remounted writable for a moment. # Force and other images that start MPC from systemd (acvs or inmusic-mpc): the library goes to # /data/hwremap/hwremap.so and a drop-in adds it to the service's LD_PRELOAD, keeping whatever # was already preloaded. # The default button map is configs/mpc-live.conf or configs/force.conf, written to /sdcard/hwremap.conf # only when that file does not exist yet. --layout picks which one. Edits of the config apply on the # next button press and do not need this script again. # # The shim is hwremap from https://github.com/mmiroshnikov/akai_standalone_remap # (commit 9d2aa57a570b0c4788f88b04ca242bb82176c380, MIT). Its author tried it on an MPC Live # (Hakai, MPC 3.9.1) and a Force (stock firmware 3.9.0). This installer has been tested offline only. # # WARNINGS # - MPC is stopped and started. Save the project first. # - A firmware update can wipe the launcher edit or the drop-in. Run status, then install again. # - The default MPC Live map sends Pad Bank A-D and + / - to the Mode Menu, so those buttons no # longer do their old job until you hold Shift or edit the config. The Force map changes Mixer, # Menu and Knobs (see the guide). # - uninstall puts the launcher or the drop-in back and removes the library. A config you edited # is left in place; an untouched default config is removed. # - Not affiliated with Akai Professional / inMusic. # # Version 0.2.0. Source: tools/mpc_patch/hwremap of the repository this came from. set -u VERSION=0.2.1 P=${HW_PREFIX:-} # tests only: a folder that stands for / MARK=$P/data/hwremap CONF=$P/sdcard/hwremap.conf LAUNCHER=$P/usr/bin/az01-launch-MPC BK_ROOT=$P/data/mpc-vst-plugins/backups SO_LAUNCHER=/usr/lib/hwremap.so SO_DROPIN=/data/hwremap/hwremap.so FAILED=0 STOPPED=0 ROOT_RW=0 WROTE_CONF=0 SVC= STYLE= LAYOUT= OPT_SET= OPT_WITH= OPT_WITHOUT= OPTS= die() { echo "ERROR: $*" >&2; exit 1; } usage() { sed -n '2,17p' "$0" | sed 's/^# \{0,1\}//'; exit "${1:-0}"; } # --- unpack the library and the two default configs (generated; do not edit the markers) write_so() { # $1 destination dest=$1 tmp=$(mktemp) || die "cannot make a temporary file" # LC_ALL=C: gawk in a UTF-8 locale writes printf "%c" values above 127 as multi-byte characters, which corrupts the library LC_ALL=C awk 'BEGIN { for (i = 0; i < 16; i++) { d = sprintf("%x", i); v[d] = i; v[toupper(d)] = i } } /^$/ { next } { s = $0; n = length(s); for (i = 1; i <= n; i += 2) printf "%c", v[substr(s, i, 1)] * 16 + v[substr(s, i + 1, 1)] }' <<'HW_SO_HEX' > "$tmp" || { rm -f "$tmp"; die "could not unpack the library"; } 7f454c460101010000000000000000000300280001000000d00b000034000000 0842000000040005340020000500280019001800010000000000000000000000 00000000dc2f0000dc2f0000050000000000010001000000ec3e0000ec3e0100 ec3e010008020000e4880100060000000000010002000000083f0000083f0100 083f0100f8000000f8000000060000000400000051e574640000000000000000 000000000000000000000000060000001000000052e57464ec3e0000ec3e0100 ec3e010014010000140100000400000001000000250000002f00000028000000 06000000120000000000000000000000000000002a0000000000000019000000 030000000e000000000000002e0000001d000000150000002200000029000000 090000001700000024000000230000001a000000110000001800000000000000 2b0000000400000027000000000000001f000000070000000d00000020000000 000000001c000000000000002500000000000000000000000000000000000000 0000000000000000000000000500000000000000000000000000000000000000 000000000000000000000000000000000f000000000000000000000000000000 0c0000000a0000001000000000000000000000002d0000001400000000000000 000000002c0000000000000000000000000000000b000000080000001b000000 0000000000000000130000002600000000000000210000001600000000000000 00000000000000001e000000030000002b000000010000000500000088840230 000000002b0000002c000000b197c2bee621c1be4e69dab07d609c7c00000000 00000000000000000000000000000000d8090000000000000300090000000000 bc40010000000000030014005f01000000000000000000001200000085010000 0000000000000000120000003d010000000000000000000012000000c2000000 0000000000000000120000004600000000000000000000002200000070000000 000000000000000012000000100000000000000000000000200000008f000000 0000000000000000120000000d010000000000000000000012000000ae010000 00000000000000001200000022010000000000000000000012000000ac000000 0000000000000000120000004c01000000000000000000001200000027010000 000000000000000012000000bb01000000000000000000001200000077000000 000000000000000012000000870000000000000000000000120000005c000000 00000000000000001200000037010000000000000000000012000000fe000000 000000000000000012000000b9000000000000000000000012000000c9000000 0000000000000000120000000100000000000000000000002000000080010000 000000000000000012000000a5000000000000000000000012000000b2000000 000000000000000012000000d000000000000000000000001200000063000000 0000000000000000120000007e00000000000000000000001200000055000000 000000000000000012000000310100000000000000000000120000009e000000 00000000000000001200000095000000000000000000000012000000b3010000 0000000000000000120000008c0100000000000000000000120000002c000000 000000000000000020000000e200000000000000000000001200000044010000 0000000000000000120000009f0000000000000000000000120000006a000000 000000000000000012000000a201000075200000580a000012000b0074010000 4d1c0000b802000012000b0097010000712000000400000012000b0092010000 051f00006c01000012000b00005f5f676d6f6e5f73746172745f5f005f49544d 5f64657265676973746572544d436c6f6e655461626c65005f49544d5f726567 6973746572544d436c6f6e655461626c65005f5f6378615f66696e616c697a65 006d656d7365740073747263707900646c7673796d00646c73796d0073747274 6f6c006d656d63707900736e7072696e7466005f5f787374617400666f70656e 0076667072696e74660066636c6f73650072656e616d65006667657473007374 7263687200737472746f6b5f7200737472636d70006d616c6c6f630070746872 6561645f617474725f696e697400707468726561645f617474725f7365746465 74616368737461746500707468726561645f6372656174650070746872656164 5f617474725f64657374726f790066726565006e616e6f736c65657000777269 746500667265616400737472737472007374726e636d7000707468726561645f 6d757465785f6c6f636b00707468726561645f6d757465785f756e6c6f636b00 736e645f7261776d6964695f6f70656e0063616c6c6f6300706970653200706f 6c6c005f5f706f6c6c5f63686b00736e645f7261776d6964695f726561640073 7072696e746600636c6f636b5f67657474696d65006c6962646c2e736f2e3200 6c6962707468726561642e736f2e30006c6962632e736f2e3600474c4942435f 322e3400474c4942435f322e3900474c4942435f322e31370000000000000000 0200030003000300030003000000030003000200030003000200030004000300 0300030003000200030003000000020003000300030005000300030002000300 03000300060000000300030002000500010001000100010001000100c9010000 10000000200000001469690d00000500ee0100000000000001000300e4010000 10000000400000001969690d00000600f8010000100000009791960600000400 02020000100000001469690d00000300ee0100000000000001000100d4010000 10000000000000001469690d00000200ee01000000000000ec3e010017000000 f03e010017000000f43e010017000000f83e010017000000fc3e010017000000 003f010017000000043f010017000000bc40010017000000a840010015070000 ac40010015090000b040010015190000b440010015260000b8400100152a0000 0c40010016030000104001001604000014400100160500001840010016060000 1c40010016070000204001001608000024400100160a000028400100160b0000 2c400100160c000030400100160d000034400100160e000038400100160f0000 3c40010016100000404001001611000044400100161200004840010016130000 4c40010016140000504001001615000054400100161600005840010016170000 5c40010016180000604001001619000064400100161a000068400100161b0000 6c400100161c000070400100161d000074400100161e000078400100161f0000 7c40010016200000804001001621000084400100162200008840010016230000 8c40010016240000904001001625000094400100162e00009840010016270000 9c40010016280000a040010016290000a4400100162a000008402de97b0000eb 0880bde804e02de504e09fe50ee08fe008f0bee50c36010000c68fe213ca8ce2 0cf6bce500c68fe213ca8ce204f6bce500c68fe213ca8ce2fcf5bce500c68fe2 13ca8ce2f4f5bce500c68fe213ca8ce2ecf5bce500c68fe213ca8ce2e4f5bce5 00c68fe213ca8ce2dcf5bce500c68fe213ca8ce2d4f5bce500c68fe213ca8ce2 ccf5bce500c68fe213ca8ce2c4f5bce500c68fe213ca8ce2bcf5bce500c68fe2 13ca8ce2b4f5bce500c68fe213ca8ce2acf5bce500c68fe213ca8ce2a4f5bce5 00c68fe213ca8ce29cf5bce500c68fe213ca8ce294f5bce500c68fe213ca8ce2 8cf5bce500c68fe213ca8ce284f5bce500c68fe213ca8ce27cf5bce500c68fe2 13ca8ce274f5bce500c68fe213ca8ce26cf5bce500c68fe213ca8ce264f5bce5 00c68fe213ca8ce25cf5bce500c68fe213ca8ce254f5bce500c68fe213ca8ce2 4cf5bce500c68fe213ca8ce244f5bce500c68fe213ca8ce23cf5bce500c68fe2 13ca8ce234f5bce500c68fe213ca8ce22cf5bce500c68fe213ca8ce224f5bce5 00c68fe213ca8ce21cf5bce500c68fe213ca8ce214f5bce500c68fe213ca8ce2 0cf5bce500c68fe213ca8ce204f5bce57847fde700c68fe213ca8ce2f8f4bce5 00c68fe213ca8ce2f0f4bce500c68fe213ca8ce2e8f4bce500c68fe213ca8ce2 e0f4bce500c68fe213ca8ce2d8f4bce514309fe514209fe503308fe0022093e7 000052e31eff2f01c1ffffea20340100b00000000648074b074a78447b447a44 834203d0054bd35803b11847704700bff6340100f4340100fe330100ac000000 0848094b7844094a7b441b1a7a44d90f01eba301491003d0054bd35803b11847 704700bfcc340100c8340100d0330100b400000008b50a4b0a4a7b447a441b78 6bb9094bd35823b1084b7b441868fff7dceefff7bfff064b01227b441a7008bd 9a340100a0330100a80000004e3401007a340100c4e700bf1c484ff4844210b5 00217844fff750ef19484ff48442002178444ff4c874fff748ef16484ff48442 00217844fff740ef13484ff4844200217844fff73aef11484ff4844200217844 fff732ef0e4b0f4a4ff448707b4400217a44c3e900404ff0ff344ff4af70c2e9 00119c609622c3e9030210bd2a7902001c3702000af50100fcb20100ee700100 d03301000c3401002de9f04f04462a4b2ded028b87b07b44284a7a4401929a68 42b121464ff0ff3007b0bdec028bbde8f04f1047224f1646224a0df10808224b 7f447a44444607f1100b7b440df10c0a0df10e090df10f05904608ee100a98e8 03002060aaf8001048462e6002ac090c89f8001019466e602e72fff78eee1349 224600207944fff7c4ee114b5f457b44986003d058b957f8043fe0e718ee104a 02460028bdd10b4b019ad258b9e718ee104a0246b5e700bfc6330100c2320100 9031010072210000f61d0000c41d00004e330100b80000000b4670b5066c84b0 054613f8014b6d2c00f08d80742c6cd0a4f178021846b2fa82f2002152091201 fff708ee00281ddb782c19d07f2819dc682c02bf01300023c5f8800014d0623c 162c0fd8dfe804f04b0e410e0e0e0e0e0e0e0e0e0e0e300e0e0e0e260e0e1300 ff2804dd4ff0ff33184604b070bd01248df80800c6f140039c42f3dc224602a9 a819fff70eee2a6c0023224418462a6404b070bd9022002303248df808208df8 09008df80a30e5e7c0b29923002149f67f1206248df80d10adf80a208df80830 8df809008df80c00d4e790227f2303248df808208df809008df80a30cae7c0b2 9023002149f27f02e3e702a9002218460191fff7a0ed029b019904461a782c2a b0d1581c0022fff796ed029b1b78002ba8d144ea0002b2f5803fa3d20122e867 c5e91d24a0e70e4a00f14404302120467a44fff704ee95f844304bb120225f2b 08bf227014f8013f002bf8d195f84430b3fa83f35b095b42184604b070bd00bf 401c00000fb4194b10b57b4498b05b6823b918b0bde8104004b07047144c02aa 03207c442146fff792ed18b90d9bb3f5802f15dc0f49104879447844fff750ed 04460028e5d01baa1a990192fff7deed2046fff7d6ed18b0bde8104004b07047 064920467944fff7a2ede3e792310100f21b0000041c0000da1b0000c41b0000 2de9f04f0320dff820542ded048badf51d7ddff818147d4406ac79442246fff7 56ed6b69002840f01781d4e910249a4203d1ab69a34200f0d880fd4bfd497b44 fd4879447844c3e90524fff70aed0646002800f0ca80f94b1cadf94f7b44dff8 e48308ee103af84b7f44f8447b440093fff722fe32464ff400712846fff708ed 002800f0ab8023212846fff756ed08b1002303700df1140939464a4628460023 c9f80030fff72aed04460028e2d04146fff7c4ec8246002800f09d80e3492046 7944fff7bcec8246002800f0a780e04920467944fff7b2ec8246002800f0ad80 dc4920467944fff7aaec8246002800f0bf80d94920467944fff7a0ec82460028 00f03b81d54920467944fff798ec8246002800f06b81d24920467944fff78eec 8246002800f0b380ce4920467944fff786ec38b1cc4920467944fff780ec0028 40f02d812378642b00f05d81682b00f05e81742b00f04381dff810a3fa44c449 4a4600207944fff7caec0446002881d0002220461146fff76eec83467f283ff6 79af8422002102fb00aa5046fff7ececb8494a4600207944fff7b0ec04460028 3ff468afcdf804b018ee10ba06e05946fff7a4ec044600283ff45caf21465046 fff72afe4a460028f1d0ddf804b02146a9485a467844fff7d5fe4be73046fff7 d0eca6487844fff7cdfe0df51d7dbdec048bbde8f08f4a463946fff780ec40b1 51460a22fff726ecb0f1000a18bf4ff0010a9b4b7b44c3f804a02be74a463946 fff76cec002800f0de8052465146fff712ec944b7b4498601ce74a463946fff7 5eec002800f0a68051460a22fff702ec8d4b7b44d8600de7002bc6d0fff72cfd 00236b610df51d7dbdec048bbde8f08f4a463946fff742ec002800f08e805146 0a22fff7e8eb814b7b441861f2e64a463946fff734ec4a46834639465046fff7 2eec0446bbf1000f00f08d80524651465846fff7d0eb8246002c3ff4dbae0022 20461146fff7c6eb4aea00037f2b01903ff6d0ae6e4b7b441c681f2c3ff7caae 8c226c4800217844029002fb04f3039303eb000b5846fff738ec6749dde90223 7944002042f803a04a46019bcbf80430fff7f4eb834650b3604b08ee906acdf8 0ca009ee105a7b44ddf808a0009e1d4606e03146fff7e2eb2c68834600286dd0 8c23594603fb04a00830fff765fd4a460028eed0ddf80ca05946514818ee906a 019b5246784419ee105afff70bfe4d4a7a441368013313607ce64a463946fff7 beeb48b351460a22fff764eb464b7b4418606fe64ff4af705ae7962073e74349 20467944fff74aeb00283ff4cbae404920467944fff742eb00283ff4c3aedff8 f4a0fa44d4e600283ff454ae002220461146fff740eb4de64ff4c870d6e7dff8 d8a0fa44bbe64ff0ff3022e74a463946fff784eb78b151460a22fff72ceb2f4b 7b44586036e6dff8b8a0fa44a7e6dff8b4a0fa44a3e64ff44870f0e718ee906a 19ee105aa3e700bfc6300100a61b00009e300100961b00007c1b0000801b0000 741b00007a1b0000701b0000281b00001e1b0000141b00000a1b0000001b0000 f61a0000101b0000081b0000906c0100781a0000461a0000801a0000881a0000 082f0100a82e01008a2e0100542e0100462e010086590100dc180000f62d0100 b4180000ac2d01004e2d0100a61800009a1800002a7202000aac0100dc2c0100 e22f0200daed0100f0b5064610208bb00d461746fff718eb10b3022d044608bf 0023c0e90065876006d0104a7a4402eb8602d3680133d36001ade3602846fff7 22eb01212846fff75ceb094a234629467a446846fff7ecea20b92846fff7a6ea 0bb0f0bd2046fff7aeeaf6e7302c0100f50400002de9f0418468aeb0d0e90056 fff7a0ea44f6d352c1f26202e31702a882fb04120021c3eba2134ff47a720293 02fb134444f24023c0f20f0303fb04f40394fff79aea3d4801217844fff7d0ea 071e6bdb3a4a0323c0f23903dff8e4c07a441493fc440321c0f235010cf1100c d369002418910df1180e591c12949bb215930323c0f236031c930123c0f24a13 209301232193032313942493c0f20103cde91644cde919541b94cde91d641f94 cde92244cde925542794cde92964cde92b442d942893d161bce80f00aee80f00 bce80f00aee80f009ce80f008ee80f00702212a93846fff7aeea2146804604a8 04944ff4b443c0f262230593fff73cea06a930223846fff79eea08eb00033846 0193fff7caea0c48019b324629467844fff798fc00202eb0bde8f08107487844 fff790fc00202eb0bde8f081021700004c2b0100601900005616000032160000 2de9f04f05462ded028b9bb090f8443083bb2c6c002c23dda64b2c44dff898c2 29467b440027fc44d3f80c05d3f81065431c01315a42c3f30b03c2f30b0258bf 5342b3421fbf012711f8012c0cf800201846a142ecd11fb1984b7b44c3f80c05 6b6f002b40f0ee8001201bb0bdec028bbde8f08f924904ac224603207944fff7 e6e905f1440308ee103a002840f086808c4b14997b441a6a914203d1159a5b6a 9a427bd08849894879447844fff798e90646002872d00f9f781cfff7e6e90190 002800f0f2803a4633460121dff80092fff7c8e9034630461e46fff712ea7d4b 019ff9447b447c48149a00217844b9551a6200f50370159a09f140095a624ff4 4072fff7f2e938464946fff752e9074600283cd0714b0df10c0a08ee904a7b44 9b4603f5037200920a22514607f11e00fff750e9072206460f281fd868490398 79448418fff702ea804622212046b8f1000f13d1fff7b0e93023214603fb06f6 60b1041b009b2f2ca8bf2f2498195e4422462644fff764e986f80c82781c4946 fff716e907460028ced118ee904a0198fff738e953487844fff7b4fb524e18ee 108a00277e4406f5037630464146fff706e900286dd14d4a0df11b0c4c4b7a44 dff830813a447b44f84492f86020d3f80c65d3f810e57b238df814208df81720 90228df811307f238df8153099238df816304ff41043c0f27b03069349f67f13 adf8123001e014f8012f731c5942c3f30b03c1f30b0158bf4b4273451ebf08f8 062001201e46a445edd118b1324b7b44c3f80c65314818ee101a3a467844fff7 61fbe6e60c20d5e91e76fff71ee9054600283ff409af2a4b04acc0e900762046 7b441b69ab60fff72ee901212046fff768e9244a2b4621467a4403a8fff7f8e8 18b92046fff7b2e8eee62846fff7bae8f7e701373036102f87d11b4818ee101a 7844fff72ffb0020dfe63046fff728e974e700bf7a2a0100c6450100422a0100 c4150000c8290100b0140000961500009217000078290100b02901007e290100 44150000da140000f8280100b6160000d6280100244401006e28010050140000 fc27010039fcffff04140000dff870c070b5fc44dcf80c55dcf810456b1c5a42 c3f30b03c2f30b0258bf5342a34225d05a1cdff850e05642c0b2fe44c2f30b02 c6f30b06ccf80c3558bf72429026a2420ef8056012d00ef80300531c5842c9b2 c3f30b03ccf80c25c0f30b0058bf4342a3421cbf0ef80210ccf80c3570bd00bf 8a270100b24201002de9f0410568d0e9017484b0c668fff736e844f6d353c1f2 6203002102a883fb0432e317c3eba2134ff47a72029302fb134444f24023c0f2 0f0303fb04f40394fff72ee8784c7c4404f21450fff722e8022f7ad04fea8508 04eb0803da68b24209d07248784400f21450fef7d2ef002004b0bde8f081002f 40f0a280d3f82c27002aeed06a4a8421c3f82c777a4401fb0522116c002940f0 b88092f84410002940f0b380516f002940f0af80d2f88020002a40f0aa80d4f8 0c650122c3f82c29b318d4f810055a42c3f30b03c2f30b0258bf5342834226d0 5a1c5649c4f80c3554427944c2f30b02c4f30b04efb258bf6242902482428c55 15d04f4c511c7c44e7540b464942c3f30b03c1f30b0158bf4b424a4983427944 c1f80c251ebfc1f80c357f23a354464829467844fff726fa444b7b44d86a0028 93db01220df107018df80720fff712e88be7d4f80c6504eb8505d4f81015731c 5a42d5f82c05c3f30b03c2f30b0258bf53428b4221d05a1c354d5742c0b27d44 c2f30b02c7f30b07c4f80c3558bf7a4290278a42af5510d0e854531c5842c4f8 0c25c3f30b03c0f30b0058bf43428b421ebfc4f80c350021a954264b7b44d86a 0028fff652afbce7012f7ff44eafd3f82c2d002a3ff449af1f4884220021c3f8 2c1d784402fb0500fff74afd1b4829467844fff7c7f91a4b7b44d86a0028fff6 34af3a460df107018df80770fef7b2ef2be714488423784403fb0500fff730fd 114b01227b444344c3f82c2b7fe700bfce260100b02601005863010082410100 66410100fe25010012120000a2250100ee400100202501000aa4010064110000 e4240100d6610100f82401002de9f04f1646944d85b004467d44d5f82c2f002a 00f0de80904d7d44d5f8302f002a00f0e2808e4f324620467f44d7f82c5fa847 b0fa80f3002c05464fea531308bf0023002b00f0c1802368002b00f0bd8007f2 1450fef7eceefff79bf981490020d4f800a07944fef786ef7e49804600207944 fef780ef7c49074600207944fef77aef7a49814600207944fef774efb8f1000f 18bf002f834600f09180b9f1000f18bf002800f08b80c04701460120fef782ee 8046002800f0828050464146b847002840f0ac804046c84781464046d8470746 002e00f0bc803a46002f00f0a380b9f1000f00f08b80624831464b467844fff7 11f9604948467944fef762ee002800f084804046fef786ee5b4b5c4900207b44 22687944c3f8342ffef72cef034630b12068012202a99847012800f08e804ff0 ff37534c7c44a36a2763002b75db514c00210e464ff400727c4404f22c70fef7 d4ee4ff40072314604f62c10fef7ccee4ff40072314604f62c50fef7c6ee4ff4 0072314604f63870fef7beee424839467844fff7c7f841484ff4007231467844 c4f80c65c4f81065c0e910664830fef7acee31464ff4007204f62c30fef7a4ee 3748d4f8341f7844fff7acf83548784400f21450fef7f0ed284605b0bde8f08f 3148cde900137844fef77effc5f82c0fdde9001316e72d48cde900137844fef7 73ffc5f8300fdde9001312e7284b314628487b447844fff785f83fb126493846 7944fef7d6ed00287ff473af4046fef7faedcbe7214a7a4459e74ff40061c0f2 080104f12800fef77eee00283ff47faf4ff0ff33c4e90a3379e7029f71e7184e 7e4440e7a42401009624010084240100be100000ca100000d2100000ea100000 f4100000961000009e2301008210000038230100642301003410000016340100 0e100000ee220100220f0000200f00006e0d0000dc0f00007c0f00004a0d0000 a40e00002de9f0470646514cb0b00d467c441746d4f84832002b00f08f804d4b 7b44186b9b6a03430ad54b4b3a46294630467b44d3f8483230b0bde8f0471847 6b1e0e2bf1d800244ff0ff3806f1040c00e01c4656f83410631c884205d13cf8 342012f0010f18bfa0469d42f1d1b8f1ff3fdad0dff8e490f94409f2145a5046 fef77ced5046d9f810a5d9f80c95fef734edca4511d0334606ebc5050022da80 08339d42fbd106ebc80801231f46a8f80630384630b0bde8f0874feac50910ad 4a4631462846fef76ced254b3a4628467b44996a234b7b44d3f8487209f1c003 6b4443f8801c012143f87c1ca11cb847071ededb0023b11d05ebc3029c42d288 21f8332003f10103f6d109f1c0030deb030535f97a3c002bcbd0134d6c467d44 a86a40222146fef718ed0028f8dc06ebc806b6f9063043b1013fbae70b487844 fef772fec4f8480269e70123f380b0e7e43201009c210100c232010084210100 ec2001001e3201009e2001000a0e0000fef78ebd2de9f04f0d46dff820492ded 028b93467c44adf22c4d08ee100ad4f82c3f002b00f00b82dff804497c44d4f8 303f002b00f00b82dff8f86818ee100abbfa8bf37e445b09d6f8342f82420cbf 1c4643f0010454b1d6f8303f5a4629460df22c4dbdec028bbde8f04f184706f2 1450013d0295fef7caecd6f80c752246d6f810352846dff8b0687e44591c9f42 14d04a42f55c04f10104c1f30b03c2f30b0100f8015f58bf4b420122a345edd8 dff888287a44c2f81035eee022b1dff880387b44c3f81075002c40f0e680dff8 7498bbf5807f5b4628bf4ff48073f94408ee903a09ab0193dff85c38da46cb46 7b4404934df68363c4f21b3305930bf214552846fef740ecdbf8303f18ee902a 019918ee100a984704462846fef776ec002c40f3c381dbf80430002b40f06f81 dff81838019adff818587b4404eb020803f5cc637d44144603931fe0f72b18bf 002ab6bf002201226a6480f2f180dff8f41703f0f0020120d02a794481f84c32 086400f00581f02a00f00981c02a00f0ff800223c1f85032444562d014f8013b f72b00f29080f02b00f0b0806e6c5ab2002ed3d1002adadb2a6c511c4ab995f8 4c2282f080026f2a9cbf0221012200f20d81dff894777f44b818396480f84c32 d7f850329342d7d197f84c321a0706d103f0e002802a08bf032900f038810029 28dddff868370027dff864277b44ddf810e07a4402f51372d3f80c651144d3f8 10c5731c01325842c3f30b03c0f30b0058bf434263451fbf012712f8010c0ef8 06001e468a42ecd127b1dff828377b44c3f80c65dff82037002244457b441a64 9cd1dff818370020dff8146704467b4402997e44d3f80c55d3f810355a1c9d42 3ad05042f75c04f10104c2f30b03c0f30b0201f8017f58bf53420120a245edd8 dff8e0267a44c2f81035dff8dc06784400f21450fef770eb20460df22c4dbdec 028bbde8f08fdff8c4667e44d6f80c75d6f810157a1c5042c2f30b02c0f30b00 58bf42428a423ff457afc6f80c25dff8a0267a44d3554fe720b1dff898367b44 c3f81055002c3ff402afcee7dff888660120dff8882600217e447a44d6f80c75 82f84c12116450643a185042d6f81015c2f30b02c0f30b0058bf42428a423ff4 2bafc6f80c25dff858267a44d35523e7dff850667e44d6f80c75d6f810157a1c 5042c2f30b02c0f30b0058bf42428a4205d0c6f80c25dff830267a44d355f72b 7ff40aafdff8243600227b445a6403e7dff81c3601227b44c3f85022fce603f0 fd02f12a08bfc1f850023ff4f5aef22b3ff4efaedff8fc650022c1f850227e44 d6f80c75d6f810157a1c5042c2f30b02c0f30b0058bf42428a423ff43bafc6f8 0c25dff8d4257a44d35533e7dff8cc657e44d6f80c75d6f810157a1c5042c2f3 0b02c0f30b0058bf42428a423ff4c4aec6f80c25dff8a8257a44d355bce6019b 49afdff8a0953d4698461e19f94418f8012b284649460335fef76eeb4645f6d1 dff8840539467844fef75cfd78e6dff87c057844fef738fcc4f82c0fece5dff8 70057844fef730fcc4f8300fece503f0f00397f84d92902b54d0dff85875fef7 7ffd4fea89037f441f44d7f8386f002e40f08c81d7f82c17d1b9d7f82c29002a 40f0c881d7f82c6b002e40f0c981dff828257a441344116c9e64a0e62846fef7 6cea20460df22c4dbdec028bbde8f08fdff808258421c7f82c677a4401fb0922 116c002940f0998192f84410002940f09481516f002940f09081d2f88020002a 40f08b81dff8d83409eb49107b4403eb8000fff775f8dff8cc0449467844fef7 f1fc97e697f84e32002ba6d0fef728fddff8b4347b449b68002bc0f28e8107eb 83039e6cdff8a434003e7b4418bf01261f68002f34dddff898140123dff894c4 7944fc4403e09f422add8c3101334a68581e9145f7d10a680ceb8202926c002a f1d08a6c002a00f086808c23dff868747f4403fb00f606f108003844fff730f8 dff858340120ba597b44494603eb8903c3f82c0bdff848047844fef7a3fc49e6 012e77d08423dff83c247a4403fb09f31a44116c002940f08c8092f844100029 40f08780516f002940f08380d2f88020002a7ed1dff8107409eb49127f443b44 07eb820792001e6c26b993f84430002b00f0ac8049ae012031460692fef70aea fa48069a4ff47a767844131884220693dde949c302fb0900059a82fb0312db17 c3eba243026cd917ccfb0631002a40f0408190f84420002a40f03b81426f002a 40f03781d0f88020002a40f032814feac9020398024442e902313b6c002b00f0 19813846fef7bcff002840f041814fea890301260be791f84c20002a7ff475af ca6f002a7ff471afd1f88820002a7ff46caf58e7842109eb4910800001fb09fc d3490246794461440b6c002b39d0d14b7b441844fef794ffcf4bd04801227b44 494603eb89037844c3f82c2bfef70afcb0e5cb4e7e4406eb8906d6f82c1d0029 00f0a180c74f09eb4910f3687f44013307eb8000f3600023c6f82c3dfef770ff 842303fb0977d7f88000002840f0a1800123c6f82c3bbc4849467844fef7e2fb 88e591f84430002bc1d14b6f002bbed1d1f88030002bbad1b44f7f4407eb0c01 07440b6cfbb991f84430e3b98420b049794400fb09f001444b6f8bb9d1f88030 73b9ac49794401440b6c4bb991f8443033b94b6f23b9d1f88030002b3ff477af 002e3ff437af4fea890380e6a24b49a9012007917b44013e5a680023c7f8383f 0692fef738e90799dff870c2d1e90023fc4405990cebc90c81fb0301db174ff4 7a70c3eba143dce9961c4feae37ec2fb003e069a5b1a6eeb0c0ed117d31a61eb 0e01012b71f100012edb1a4648460221c7f82c65fef718fe1ce5894a01214846 7a441344874a7a44c3f82c1dd268fef70bfe0fe54846c7f82c19fff767f809e5 c7f82c2b06e5804b48467b441a680123c6f82c37fef7f8fdfce47c4b7b441f68 002f3ff778aeade600213046fff74ef8f0e401387f21fff749f8d7f88030c6f8 383f49ae31460120fef7d4e80599dde949036f4a81fb0361db177a444ff47a76 02ebc902c3eba143d917c0fb0631c2e9963140e797f84430002b7ff4e2ae7b6f 002b7ff4deaed7f88030002b3ff4dfaed7e6604e4feac9027e4406f5cc661644 56e9020650ea060c3ff4c3aedff868c1181a61eb0606fc44dcf80ce086454fea ee7c7ceb060ca2bf00231946069fb0e6524b01227b4403eb8903c3f82c2b069b bb4207d04e4a7a444e4849467844fef7e9fa8fe44c4a7a44f6e700bf78200100 6020010048200100523b0100d81f0100ca1f0100ae1f0100ec3a01004a300100 403001001a300100be2f0100901e0100822f01004e1e0100382f01002e1e0100 7a390100f81d0100ee1d0100d21d0100fa3801009e1d0100841d01007a2e0100 a2380100481d0100723801000a2e0100fe2d0100de1c010006380100ac1c0100 d4370100d0090000be090000960800009a080000161c0100e22c0100921e0200 609a0100b8070000281b0100521b01008c460100322c01005c460100f41a0100 54080000a2990100705f0200441d0200a8da01009cda0100be19010056070000 a8190100601c0200ee060000125e0200fc5d0200e81b0200a8180100c4290100 7c180100361801001218010040180100fa280100bc2801006617010088170100 3a02000024050000ba04000008402de90880bde81c0000001600000017000000 160000001a000000160000002a0000001600000032000000160000002c000000 1600000029000000160000002b00000016000000240000001600000026000000 16000000350000001600000002000000160000000f000000160000003d000000 1600000036000000160000002e00000016000000060000001600000000000000 00000000322e333400000000646c73796d000000257300002f746d702f687772 656d61702e6c6f67000000002f746d702f687772656d61702e6c6f672e310000 610000002f7364636172642f687772656d61702e636f6e660000000072000000 20090d0a000000006c6f6700686f6c640000000064626c6d73000000746f7563 686d73006c6f6e676d730000686f6c646d730000636f6d626f00000062616420 746f6b656e202725732720666f7220636f6d626f20256c6420256c640a000000 64626c0068656c6400000000746170006c6f6e670000000062616420746f6b65 6e202725732720666f7220256c640a00636f6e666967206c6f616465640a0000 2f6465762f696e7075742f6576656e7430000000746f756368206f70656e2066 61696c65640a0000746f7563682025642c25642028257a64206279746573290a 000000002f6d656469612f617a30312d696e7465726e616c2f53657474696e67 732f4d50432f4d50432e73657474696e677300006d656e752067726964206c6f 616465640a000000222076616c3d22006d6f64652027257327202d3e20736c6f 742025640a0000006d6f64652027257327206e6f7420696e20746865206d656e 7520677269640a006c6f6e672070726573732025640a000072656d6170202564 2028746170290a003f000000736e645f7261776d6964695f6f70656e00000000 736e645f7261776d6964695f7265616400000000736e645f7261776d6964695f 696e666f5f73697a656f6600736e645f7261776d6964695f696e666f00000000 736e645f7261776d6964695f696e666f5f6765745f7375626465766963655f6e 616d6500736e645f7261776d6964695f696e666f5f6765745f6e616d65000000 5072697661746500736e645f7261776d6964695f706f6c6c5f64657363726970 746f727300000000707269766174652066642025640a0000686f6f6b65642070 72697661746520696e7075742025700a000000006f70656e2025733a20272573 27202f20272573270a000000706f6c6c000000002028646f75626c6529000000 2530325820000000696e3a2025730a0072656d61702025642028636f6d626f20 77697468202564290a00000072656d61702025642028646f75626c65290a0000 72656d61702025642028686f6c64290a0000000072656d617020256425730a00 322e3400322e313700000000322e322e35000000322e3000474c4942435f0000 0000000000000000000000000000000003003900ffffffff0000000000000000 01004a0100000000000000000000000000000000000000003c56414c5545206e 616d653d224d6f64654d656e755061676531536c6f74000031373335302f2d2b 28262e2c25242a521c0000001600000017000000160000001a00000016000000 2a0000001600000032000000160000002c000000160000002900000016000000 2b00000016000000240000001600000026000000160000003500000016000000 02000000160000000f000000160000003d000000160000003600000016000000 2e00000016000000060000001600000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000950c0000550c0000642b0000c02e0000c42e0000 cc2e0000d42e000001000000c901000001000000d401000001000000e4010000 0c000000d80900000d000000cc2a000019000000ec3e01001b00000004000000 1a000000f03e01001c0000000400000004000000d4000000f5feff6f2c020000 050000004c050000060000005c0200000a0000000d0200000b00000010000000 03000000004001000200000038010000140000001100000017000000a0080000 110000003808000012000000680000001300000008000000feffff6fb8070000 ffffff6f03000000f0ffff6f5a070000faffff6f080000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 083f01000000000000000000e4090000e4090000e4090000e4090000e4090000 e4090000e4090000e4090000e4090000e4090000e4090000e4090000e4090000 e4090000e4090000e4090000e4090000e4090000e4090000e4090000e4090000 e4090000e4090000e4090000e4090000e4090000e4090000e4090000e4090000 e4090000e4090000e4090000e4090000e4090000e4090000e4090000e4090000 e4090000e40900000000000000000000000000000000000000000000bc400100 9001000020030000ffffffff5e01000096000000ffffffffffffffff30750000 ffffffffffffffffffffffffffffffffffffffff4743433a2028474e55292031 312e352e30004130000000616561626900012600000005372d4100060a074108 0109020a041204140115011703180119011a021c012201002e73687374727461 62002e676e752e68617368002e64796e73796d002e64796e737472002e676e75 2e76657273696f6e002e676e752e76657273696f6e5f72002e72656c2e64796e 002e72656c2e706c74002e696e6974002e74657874002e66696e69002e726f64 617461002e65685f6672616d65002e696e69745f6172726179002e66696e695f 6172726179002e646174612e72656c2e726f002e64796e616d6963002e676f74 002e64617461002e627373002e636f6d6d656e74002e41524d2e617474726962 7574657300000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000f0000000500000002000000d4000000 d400000058010000030000000000000004000000040000000b000000f6ffff6f 020000002c0200002c0200003000000003000000000000000400000004000000 150000000b000000020000005c0200005c020000f00200000400000003000000 04000000100000001d00000003000000020000004c0500004c0500000d020000 0000000000000000010000000000000025000000ffffff6f020000005a070000 5a0700005e0000000300000000000000020000000200000032000000feffff6f 02000000b8070000b80700008000000004000000030000000400000000000000 4100000009000000020000003808000038080000680000000300000000000000 04000000080000004a0000000900000042000000a0080000a008000038010000 03000000130000000400000008000000530000000100000006000000d8090000 d80900000c000000000000000000000004000000000000004e00000001000000 06000000e4090000e4090000ec01000000000000000000000400000004000000 590000000100000006000000d00b0000d00b0000fc1e00000000000000000000 04000000000000005f0000000100000006000000cc2a0000cc2a000008000000 00000000000000000400000000000000650000000100000002000000d42a0000 d42a000004050000000000000000000004000000000000006d00000001000000 02000000d82f0000d82f00000400000000000000000000000400000000000000 770000000e00000003000000ec3e0100ec3e0000040000000000000000000000 0400000004000000830000000f00000003000000f03e0100f03e000004000000 000000000000000004000000040000008f0000000100000003000000f43e0100 f43e000014000000000000000000000004000000000000009c00000006000000 03000000083f0100083f0000f800000004000000000000000400000008000000 a500000001000000030000000040010000400000bc0000000000000000000000 0400000004000000aa0000000100000003000000bc400100bc40000038000000 00000000000000000400000000000000b00000000800000003000000f8400100 f4400000d886010000000000000000000800000000000000b500000001000000 3000000000000000f44000001200000000000000000000000100000001000000 be00000003000070000000000000000006410000310000000000000000000000 01000000000000000100000003000000000000000000000037410000ce000000 00000000000000000100000000000000 HW_SO_HEX # the awk unpacker can drop or mangle bytes on a device (NULs): never put a library into MPC's LD_PRELOAD unchecked if [ "$(wc -c < "$tmp" | tr -d ' ')" != "17904" ] || [ "$(sha256sum < "$tmp" | cut -d' ' -f1)" != "157dde26402b25f62bf41723741e2dc2c1bace958ecda43d21b00bc4419231a0" ]; then rm -f "$tmp"; die "the library did not unpack correctly (size or sha256 differs); nothing was changed" fi mv "$tmp" "$dest" || die "cannot install the library" chmod 755 "$dest" || die "cannot mark the library executable" } conf_raw() { # $1 mpc-live|force: the embedded map, option markers included case "$1" in mpc-live) cat <<'HW_CONF_LIVE' # hwremap config for MPC Live -> /sdcard/hwremap.conf on the device; edits apply on the next button press. # Buttons are notes on channel 1, pads are notes on channel 10 (see hwremap.c for tokens). # # MPC Live / Live II button notes: Shift 49, Menu 123, Next Seq 42, Main 52, - 55, + 54, # Pad Bank A-D 35-38 # Pad notes (pad 1 = bottom left): 1:0x25 2:0x24 3:0x2A 4:0x52 5:0x28 6:0x26 7:0x2E 8:0x2C # 9:0x30 10:0x2F 11:0x2D 12:0x2B 13:0x31 14:0x37 15:0x33 16:0x35 # Hold Menu + pad N opens the mode at that position of the 4x4 Mode Menu (pad 13 = top left). # mName finds the mode in the saved Mode Menu layout (MPC.settings is written when MPC saves # preferences or exits, so a moved icon is picked up after that). log 0 # With Shift held, remapped buttons keep their normal function (value change, banks E-H). hold 49 # Pad Bank A-D: the top row of the Mode Menu, left to right 35 d123 p0x31 u123 36 d123 p0x37 u123 37 d123 p0x33 u123 38 d123 p0x35 u123 # + : first icon of the second row 54 d123 p0x30 u123 # + twice: third icon of the second row dbl 54 d123 p0x2D u123 # - : second icon of the second row 55 d123 p0x2F u123 # - twice: fourth icon of the second row dbl 55 d123 p0x2B u123 dblms 350 HW_CONF_LIVE ;; force) cat <<'HW_CONF_FORCE' # hwremap config for Akai Force -> /sdcard/hwremap.conf on the device. # #@hide # The install script writes this file with only the options you pick. Lines starting "#@" are # markers it reads (hwremap ignores them as comments), so this whole file is also a valid config: # every block below is then active, including the ones marked off. # #@always a block that is always written # #@option NAME on|off a block written when the option is chosen; "on" or "off" is the default # #@if EXPR a block written when EXPR holds: names joined by & (and) and | (or), # a leading ! negates a name; & binds tighter than |. #@end closes it # #@hide ... #@show lines left out of the written file (this explanation) #@show # # Force button notes (channel 1): Shift 49, Menu 2, Knobs 1, Mixer 11, Master 5, Edit 37, Clip 9, # Rec Arm 93, Up 112, Down 113, Left 114, Right 115 # Touch taps are raw: x = screen_y * 1.6, y = 720 - screen_x * 0.5625 (the touch panel is 1280 x 720, # rotated against the screen). Checked on a Force on 2026-10-09 (docs/NOTES.md). # Taps hit screen positions, so the blocks that tap an icon need the default Mode Menu layout. #@always log 0 # With Shift held, remapped buttons keep their normal function unless a "held" rule says otherwise. hold 49 longms 400 holdms 800 dblms 350 touchms 300 #@option mixer-master on Mixer twice: Master (the first press opens the mixer as usual) dbl 11 b5 #@option mixer-tabs on Mixer + Up / Down / Left / Right: the mixer's Pan & Volume / Effects / I/O / Sends tabs # taps the tab bar at the bottom of the mixer screen combo 11 112 t1232,540 combo 11 113 t1232,301 combo 11 114 t1232,181 combo 11 115 t1232,421 #@option edit-editor on Edit twice: the plugin / track editor (the stock Shift + Clip shortcut) dbl 37 d49 b9 u49 #@option clip-arrange on Clip + Left: Arrange (needs Arrange in the top-left slot of the Mode Menu) combo 9 114 b2 t280,487 #@option menu-main-mode on Menu twice: tap the Main Mode icon (needs the default Mode Menu layout; the first press opens the menu as usual) dbl 2 t331,655 #@option knobs-short off Knobs, short press: Shift + Knobs (a held press is then a plain Knobs press) tap 1 d49 b1 u49 # Shift + Knobs is a plain Knobs press held 1 u49 b1 d49 #@option knobs-long off Knobs, long press: a plain Knobs tap long 1 b1 #@option knobs-double off Knobs, double press: the original long press (Knobs held while the button is held, at least holdms) dbl 1 h1 #@if !knobs-short&knobs-long|!knobs-short&knobs-double # long and double presses need a short-press rule; without the Shift one, a short press is a plain Knobs tap tap 1 b1 #@end HW_CONF_FORCE ;; *) die "unknown layout: $1" ;; esac } conf_options() { # $1 layout: one "nameon|offdescription" line per option conf_raw "$1" | awk '/^#@option[ \t]/ { n = $2; d = $3; $1 = ""; $2 = ""; $3 = ""; sub(/^[ \t]+/, ""); printf "%s\t%s\t%s\n", n, d, $0 }' } render_conf() { # $1 layout, $2 chosen options (space separated): the map with only those blocks conf_raw "$1" | awk -v sel=" $2 " ' function chosen(n) { return index(sel, " " n " ") > 0 } function holds(expr, alts, na, i, terms, nt, j, t, ok) { na = split(expr, alts, "|") for (i = 1; i <= na; i++) { nt = split(alts[i], terms, "&") ok = 1 for (j = 1; j <= nt; j++) { t = terms[j] if (substr(t, 1, 1) == "!") { if (chosen(substr(t, 2))) ok = 0 } else if (!chosen(t)) ok = 0 } if (ok) return 1 } return 0 } BEGIN { inc = 1 } /^#@always/ { inc = 1; next } /^#@option[ \t]/ { n = $2; $1 = ""; $2 = ""; $3 = ""; sub(/^[ \t]+/, "") inc = chosen(n) if (inc) print "# " $0 next } /^#@if[ \t]/ { inc = holds($2); next } /^#@end/ { inc = 1; next } /^#@hide/ { inc = 0; next } /^#@show/ { inc = 1; next } /^#@/ { print "ERROR: unknown marker " $1 > "/dev/stderr"; exit 2 } inc { print } ' } write_default_conf() { # $1 path, $2 mpc-live|force, $3 chosen options render_conf "$2" "$3" > "$1" } tty_ok() { ( : < /dev/tty ) 2>/dev/null; } # a failed redirect on a builtin ends a BusyBox shell, so try it in a subshell list_has() { case " $1 " in *" $2 "*) return 0 ;; esac; return 1; } list_add() { if list_has "$1" "$2"; then echo "$1"; else echo "${1:+$1 }$2"; fi; } list_del() { out=; for x in $1; do [ "$x" = "$2" ] || out="${out:+$out }$x"; done; echo "$out"; } choose_options() { # sets OPTS from the layout's defaults and the --options / --with / --without flags names=$(conf_options "$LAYOUT" | cut -f1 | tr '\n' ' ') names=${names% } if [ -z "$names" ]; then [ -z "$OPT_SET$OPT_WITH$OPT_WITHOUT" ] || die "the $LAYOUT map has no options" OPTS=; return fi case "$OPT_SET" in "") OPTS=$(conf_options "$LAYOUT" | awk -F'\t' '$2 == "on" { printf "%s ", $1 }'); OPTS=${OPTS% } ;; all) OPTS=$names ;; none) OPTS= ;; *) OPTS=$(printf '%s' "$OPT_SET" | tr ',' ' ') ;; esac for n in $(printf '%s' "$OPT_WITH" | tr ',' ' '); do OPTS=$(list_add "$OPTS" "$n"); done for n in $(printf '%s' "$OPT_WITHOUT" | tr ',' ' '); do OPTS=$(list_del "$OPTS" "$n"); done for n in $OPTS $(printf '%s %s' "$OPT_WITH" "$OPT_WITHOUT" | tr ',' ' '); do list_has "$names" "$n" || die "unknown option '$n' (known: $names)" done } ask_options() { # a checklist on the terminal; changes OPTS names=$(conf_options "$LAYOUT" | cut -f1 | tr '\n' ' ') while :; do echo echo "Which button remaps do you want? (the default is marked)" i=0 conf_options "$LAYOUT" | while IFS=' ' read -r n d t; do i=$((i + 1)) if list_has "$OPTS" "$n"; then m=x; else m=' '; fi printf ' %2d [%s] %s\n' "$i" "$m" "$t" done printf 'Number to switch on/off, a = all, n = none, Enter = continue: ' if on_device && tty_ok; then read -r a < /dev/tty; else read -r a; fi case "$a" in "") return ;; a) OPTS=${names% } ;; n) OPTS= ;; *[!0-9]*) echo "Not a number." ;; *) n=$(printf '%s' "$names" | awk -v k="$a" '{ print $k }') if [ -z "$n" ]; then echo "No option $a." elif list_has "$OPTS" "$n"; then OPTS=$(list_del "$OPTS" "$n") else OPTS=$(list_add "$OPTS" "$n"); fi ;; esac done } can_ask() { # a terminal to ask on (tests: HW_ASK=1 reads stdin) if on_device; then tty_ok; else [ "${HW_ASK:-}" = 1 ]; fi } mpc_service() { if systemctl cat acvs >/dev/null 2>&1; then echo acvs elif systemctl cat inmusic-mpc >/dev/null 2>&1; then echo inmusic-mpc else echo ""; fi } detect_style() { # a Force has the launcher file too (the script its service runs) but it sets no LD_PRELOAD: that one takes the drop-in if [ -f "$LAUNCHER" ] && grep -q 'LD_PRELOAD=' "$LAUNCHER"; then echo launcher elif [ -n "$(mpc_service)" ]; then echo dropin else echo ""; fi } so_path() { # device path of the library for a style (no test prefix) case "$1" in launcher) echo "$SO_LAUNCHER" ;; dropin) echo "$SO_DROPIN" ;; esac } so_file() { # where the bytes are written (under the test prefix) case "$1" in launcher) echo "$P$SO_LAUNCHER" ;; dropin) echo "$P$SO_DROPIN" ;; esac } dropin_file() { echo "$P/etc/systemd/system/$1.service.d/hwremap.conf"; } installed_version() { [ -f "$MARK/VERSION" ] && cat "$MARK/VERSION"; } backup_present() { [ -d "$BK_ROOT" ] && [ -n "$(ls "$BK_ROOT" 2>/dev/null)" ]; } state_line() { echo "STATE state=$1 supported=$2 backup=$(backup_present && echo 1 || echo 0)${3:+ reason=$3}"; } need_tools() { for c in awk sed grep cmp mktemp systemctl pidof wc tr cut sha256sum; do command -v "$c" >/dev/null || return 1 done return 0 } on_device() { [ -z "$P" ]; } root_rw() { on_device || return 0 mount -o remount,rw / || die "could not remount / read-write" ROOT_RW=1 } root_ro() { on_device || return 0 [ "$ROOT_RW" = 1 ] || return 0 sync mount -o remount,ro / || echo "WARNING: could not remount / read-only" ROOT_RW=0 } stop_mpc() { systemctl stop "$SVC" || die "could not stop $SVC" STOPPED=1 } start_mpc() { systemctl start "$SVC" || echo "WARNING: could not start $SVC; start it yourself: systemctl start $SVC" STOPPED=0 } # Insert the library into every LD_PRELOAD assignment that does not already name it. # A line with $CURSOR_SO gets the library just before that, which is where the Hakai launcher expects it. patch_launcher() { src=$1 tmp=$(mktemp) || die "cannot make a temporary file" awk ' /^[[:space:]]*#/ { print; next } /LD_PRELOAD=/ && index($0, "hwremap.so") == 0 { if (index($0, "$CURSOR_SO") > 0) sub(/\$CURSOR_SO/, "/usr/lib/hwremap.so $CURSOR_SO") else if (match($0, /LD_PRELOAD="[^"]*"/)) $0 = substr($0, 1, RSTART + 11) "/usr/lib/hwremap.so " substr($0, RSTART + 12) else if (match($0, /LD_PRELOAD=[^[:space:]]+/)) $0 = substr($0, 1, RSTART + 10) "/usr/lib/hwremap.so:" substr($0, RSTART + 11) else { print "ERROR: a launcher line sets LD_PRELOAD in a shape this patch cannot edit" > "/dev/stderr" print $0 > "/dev/stderr" exit 2 } } { print } ' "$src" > "$tmp" || { rm -f "$tmp"; die "could not edit the launcher"; } if cmp -s "$src" "$tmp"; then rm -f "$tmp"; die "the launcher has no LD_PRELOAD line to add the library to"; fi cat "$tmp" > "$src" || { rm -f "$tmp"; die "could not write the launcher"; } rm -f "$tmp" } current_preload() { raw=$(systemctl show "$SVC" -p Environment 2>/dev/null || true) printf '%s\n' "$raw" | awk ' { s = $0 sub(/^Environment=/, "", s) if (match(s, /LD_PRELOAD=/)) { rest = substr(s, RSTART + RLENGTH) if (match(rest, / [A-Za-z_][A-Za-z0-9_]*=/)) rest = substr(rest, 1, RSTART - 1) gsub(/^[" ]+|[" ]+$/, "", rest) print rest } }' } plain_preload() { # refuse a value we would not want to write back into a unit file printf '%s' "$1" | grep -q '["'"'"'`$]' && return 1 return 0 } hook_present() { # something already redirects MPC through hwremap, with or without our marker if [ -f "$LAUNCHER" ] && grep -q hwremap.so "$LAUNCHER"; then return 0; fi if [ -f "$P$SO_LAUNCHER" ] || [ -f "$P$SO_DROPIN" ]; then return 0; fi svc=$(mpc_service) if [ -n "$svc" ] && [ -f "$(dropin_file "$svc")" ]; then return 0; fi return 1 } maps_have_it() { if ! on_device; then [ -n "${HW_MAPS:-}" ] && [ -f "$HW_MAPS" ] && grep -q hwremap "$HW_MAPS" return fi pid=$(pidof MPC 2>/dev/null) || return 1 grep -q hwremap "/proc/$pid/maps" } mpc_running() { if ! on_device; then [ -n "${HW_PID:-}" ] return fi pidof MPC >/dev/null 2>&1 } restore_hook() { # undo the launcher edit or the drop-in; the library is removed by the caller style=$(cat "$MARK/STYLE") svc=$(cat "$MARK/SERVICE") case "$style" in launcher) [ -f "$MARK/az01-launch-MPC.orig" ] || die "the saved launcher is missing ($MARK/az01-launch-MPC.orig); not touching $LAUNCHER" root_rw cat "$MARK/az01-launch-MPC.orig" > "$LAUNCHER" || die "could not restore the launcher" rm -f "$P$SO_LAUNCHER" root_ro ;; dropin) rm -f "$(dropin_file "$svc")" rmdir "$P/etc/systemd/system/$svc.service.d" 2>/dev/null || true rm -f "$P$SO_DROPIN" systemctl daemon-reload || echo "WARNING: systemctl daemon-reload failed" ;; *) die "unknown install style: $style" ;; esac } rollback() { echo "Installation interrupted: putting back what was changed" if [ -f "$MARK/az01-launch-MPC.orig" ] && [ -f "$LAUNCHER" ]; then if cat "$MARK/az01-launch-MPC.orig" > "$LAUNCHER"; then rm -f "$MARK/az01-launch-MPC.orig" else echo "WARNING: could not restore the launcher; the original is at $MARK/az01-launch-MPC.orig and in the backup" fi fi rm -f "$P$SO_LAUNCHER" "$P$SO_DROPIN" if [ -n "$SVC" ]; then rm -f "$(dropin_file "$SVC")" systemctl daemon-reload >/dev/null 2>&1 || true fi if [ "$WROTE_CONF" = 1 ]; then rm -f "$CONF"; fi rm -f "$MARK/VERSION" "$MARK/STYLE" "$MARK/SERVICE" "$MARK/config.default" "$MARK/OPTIONS" rmdir "$MARK" 2>/dev/null || true root_ro if [ "$STOPPED" = 1 ] && [ -n "$SVC" ]; then systemctl start "$SVC" || echo "WARNING: could not start $SVC again" STOPPED=0 fi } on_exit() { if [ "$FAILED" = 1 ]; then rollback exit 1 fi } confirm() { # $1 word [ "$CONFIRMED" = 1 ] && return 0 printf 'Type %s to continue: ' "$1" if on_device && tty_ok; then read -r a < /dev/tty; else read -r a; fi [ "$a" = "$1" ] || die "cancelled; nothing was changed" } cmd_status() { if on_device; then if [ "$(id -u)" != 0 ]; then echo "Not root: run this on the device as root."; state_line unsupported 0 not-root; return; fi case "$(uname -m)" in armv7*) ;; *) echo "This is for 32-bit ARM MPC OS devices; this one is $(uname -m)."; state_line unsupported 0 arch; return ;; esac fi if ! need_tools; then echo "A tool this patch needs is missing (awk, sed, grep, cmp, mktemp, systemctl, pidof, wc, tr, cut, sha256sum)."; state_line unsupported 0 tools; return; fi STYLE=$(detect_style) if [ -z "$STYLE" ]; then echo "This device has neither the Hakai launcher ($LAUNCHER) nor an acvs or inmusic-mpc service." state_line unsupported 0 unknown-layout return fi if v=$(installed_version); then if [ "$v" != "$VERSION" ]; then echo "Another version of this patch is installed ($v; this script is $VERSION). Remove it with its own script first." state_line unsupported 0 other-version return fi st=$(cat "$MARK/STYLE" 2>/dev/null || echo "?") echo "Installed (version $VERSION, style $st)." [ ! -f "$MARK/OPTIONS" ] || echo "Options chosen at install: $(cat "$MARK/OPTIONS" | sed 's/^$/none/')." if [ ! -f "$(so_file "$st")" ]; then echo "The library file is missing."; state_line partial 1 incomplete; return; fi if maps_have_it; then echo "MPC has loaded it."; state_line patched 1; return; fi if mpc_running; then echo "MPC is running but has not loaded it. Restart MPC."; state_line partial 1 not-loaded; return; fi echo "MPC is not running, so the remap is not in effect until it starts."; state_line partial 1 not-running return fi if hook_present; then echo "hwremap is already on this device (the library or an LD_PRELOAD line) but this patch did not install it. Remove that copy first; this script will not overwrite it." state_line unsupported 0 hand-install return fi echo "Not installed. Style this script would use: $STYLE." state_line stock 1 } prepare() { # shared checks for install and uninstall; sets SVC if on_device; then [ "$(id -u)" = 0 ] || die "run as root on the device" case "$(uname -m)" in armv7*) ;; *) die "this is for 32-bit ARM MPC OS devices (this one is $(uname -m))" ;; esac fi need_tools || die "a tool this patch needs is missing (awk, sed, grep, cmp, mktemp, systemctl, pidof, wc, tr, cut, sha256sum)" SVC=$(mpc_service) [ -n "$SVC" ] || die "cannot find the MPC service (looked for acvs and inmusic-mpc)" } cmd_options() { # list the options of a layout and which are on by default [ -n "$LAYOUT" ] || LAYOUT=force case "$LAYOUT" in mpc-live|force) ;; *) die "--layout must be mpc-live or force" ;; esac if [ -z "$(conf_options "$LAYOUT")" ]; then echo "The $LAYOUT map has no options."; return; fi echo "Options of the $LAYOUT map (default: on = marked):" conf_options "$LAYOUT" | while IFS=' ' read -r n d t; do if [ "$d" = on ]; then m=on; else m=off; fi printf ' %-18s %-3s %s\n' "$n" "$m" "$t" done } cmd_install() { prepare v=$(installed_version) && die "this patch is already installed (version $v). Uninstall it first (sh $0 uninstall)." hook_present && die "hwremap is already on this device without this patch's marker. Remove that copy first (see the guide); this script will not overwrite it." STYLE=$(detect_style) [ -n "$STYLE" ] || die "this device has neither the Hakai launcher nor an acvs or inmusic-mpc service" if [ -z "$LAYOUT" ]; then case "$STYLE" in launcher) LAYOUT=mpc-live ;; dropin) LAYOUT=force ;; esac fi case "$LAYOUT" in mpc-live|force) ;; *) die "--layout must be mpc-live or force" ;; esac OPTS= if [ ! -f "$CONF" ]; then choose_options if [ -z "$OPT_SET$OPT_WITH$OPT_WITHOUT" ] && [ "$CONFIRMED" = 0 ] && [ -n "$(conf_options "$LAYOUT")" ]; then if can_ask; then ask_options; else echo "No terminal to ask on: using the default options (see: sh $0 options)."; fi fi elif [ -n "$OPT_SET$OPT_WITH$OPT_WITHOUT" ]; then echo "Note: $CONF already exists and is left as it is, so the option flags are ignored." fi case "$STYLE" in launcher) where="$SO_LAUNCHER (and $LAUNCHER)"; need_rw="The root filesystem is remounted writable, then read-only again." ;; dropin) where="$SO_DROPIN (and a systemd drop-in for $SVC)"; need_rw="The root filesystem is not remounted." ;; esac echo "Installing button remap $VERSION." echo " style: $STYLE" echo " library: $where" echo " $need_rw" if [ -f "$CONF" ]; then echo " config: $CONF already exists and will be left as it is." else echo " config: $CONF will be created from the $LAYOUT map (edit it to change what the buttons do)." [ -z "$(conf_options "$LAYOUT")" ] || echo " options: ${OPTS:-none}" fi echo " MPC ($SVC) will be stopped and started. Save your project first." confirm PATCH [ "${HW_FAIL:-}" = before-write ] && die "test failure before any change" BACKUP=$BK_ROOT/hwremap-$VERSION-$(date +%Y%m%d-%H%M%S) [ ! -e "$BACKUP" ] || die "backup folder exists: $BACKUP" FAILED=1 trap on_exit EXIT mkdir -p "$BACKUP" "$MARK" "$P/sdcard" || die "cannot create the backup folder" chmod 700 "$BACKUP" || die "cannot protect the backup folder" if [ "$STYLE" = launcher ]; then cp "$LAUNCHER" "$BACKUP/az01-launch-MPC.orig" || die "cannot back up the launcher"; fi systemctl show "$SVC" -p Environment > "$BACKUP/environment.before" 2>/dev/null || true printf '%s\n' "Patch-only backup of the launcher or the service environment. No projects." > "$BACKUP/README.txt" stop_mpc case "$STYLE" in launcher) root_rw cp "$LAUNCHER" "$MARK/az01-launch-MPC.orig" || die "cannot save the launcher" patch_launcher "$LAUNCHER" [ "${HW_FAIL:-}" = after-launcher ] && die "test failure after editing the launcher" mkdir -p "$P/usr/lib" || die "cannot create /usr/lib" write_so "$P$SO_LAUNCHER" cp "$LAUNCHER" "$BACKUP/az01-launch-MPC.patched" ;; dropin) cur=$(current_preload) plain_preload "$cur" || die "the current LD_PRELOAD is not a plain list of paths; refusing to rewrite it" case " $cur " in *" $SO_DROPIN "*) new=$cur ;; "") new=$SO_DROPIN ;; *) new="$SO_DROPIN $cur" ;; esac mkdir -p "$MARK" "$(dirname "$(dropin_file "$SVC")")" || die "cannot create the drop-in folder" write_so "$P$SO_DROPIN" [ "${HW_FAIL:-}" = after-launcher ] && die "test failure after writing the library" { echo "[Service]" printf 'Environment="LD_PRELOAD=%s"\n' "$new" } > "$(dropin_file "$SVC")" || die "cannot write the drop-in" cp "$(dropin_file "$SVC")" "$BACKUP/hwremap.conf" systemctl daemon-reload || die "systemctl daemon-reload failed" ;; esac if [ ! -f "$CONF" ]; then write_default_conf "$CONF" "$LAYOUT" "$OPTS" || die "cannot write the config" printf '%s\n' "$OPTS" > "$MARK/OPTIONS" cp "$CONF" "$MARK/config.default" || die "cannot save the default config" WROTE_CONF=1 fi printf '%s\n' "$VERSION" > "$MARK/VERSION" printf '%s\n' "$STYLE" > "$MARK/STYLE" printf '%s\n' "$SVC" > "$MARK/SERVICE" root_ro start_mpc FAILED=0 trap - EXIT on_device && sync echo "Button remap $VERSION installed. Backup: $BACKUP" echo "Config: $CONF (a change there applies on the next button press)." echo "Check it: sh $0 status" } cmd_uninstall() { prepare v=$(installed_version) || { echo "Not installed. Nothing to do."; exit 0; } [ "$v" = "$VERSION" ] || die "another version is installed ($v): use its own script" echo "This removes the library and the startup hook. MPC ($SVC) will be stopped and started." if [ -f "$MARK/config.default" ] && [ -f "$CONF" ] && cmp -s "$MARK/config.default" "$CONF"; then echo "The default config has not been edited, so $CONF will be removed too." elif [ -f "$CONF" ]; then echo "$CONF was edited or was already there: it will be left in place." fi confirm REMOVE stop_mpc trap 'if [ "$STOPPED" = 1 ]; then systemctl start "$SVC" || echo "WARNING: could not start $SVC again"; fi' EXIT if [ -f "$MARK/config.default" ] && [ -f "$CONF" ] && cmp -s "$MARK/config.default" "$CONF"; then rm -f "$CONF" fi restore_hook rm -f "$MARK/VERSION" "$MARK/STYLE" "$MARK/SERVICE" "$MARK/config.default" "$MARK/OPTIONS" "$MARK/az01-launch-MPC.orig" rmdir "$MARK" 2>/dev/null || true start_mpc trap - EXIT echo "Removed. The buttons are back to what the device shipped with (once MPC is up)." if [ -f "$CONF" ]; then echo "Left $CONF in place."; fi } # --- arguments CMD=${1:-help}; [ $# -gt 0 ] && shift CONFIRMED=0 while [ $# -gt 0 ]; do case "$1" in --layout) [ -n "${2:-}" ] || die "--layout needs mpc-live or force"; LAYOUT=$2; shift 2 ;; --options) [ -n "${2:-}" ] || die "--options needs a comma list, all or none"; OPT_SET=$2; shift 2 ;; --with) [ -n "${2:-}" ] || die "--with needs a comma list"; OPT_WITH=$2; shift 2 ;; --without) [ -n "${2:-}" ] || die "--without needs a comma list"; OPT_WITHOUT=$2; shift 2 ;; --confirmed) CONFIRMED=1; shift ;; *) usage 1 ;; esac done case "$CMD" in status) cmd_status ;; options) cmd_options ;; install) cmd_install ;; uninstall) cmd_uninstall ;; help|-h|--help) usage 0 ;; *) usage 1 ;; esac