diff --git a/Cargo.lock b/Cargo.lock index a3dd529..2a43c5e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9,7 +9,7 @@ source = "registry+/~https://github.com/rust-lang/crates.io-index" checksum = "8512c9117059663fb5606788fbca3619e2a91dac0e3fe516242eab1fa6be5e44" dependencies = [ "alsa-sys", - "bitflags", + "bitflags 1.3.2", "libc", "nix", ] @@ -48,7 +48,7 @@ version = "0.64.0" source = "registry+/~https://github.com/rust-lang/crates.io-index" checksum = "c4243e6031260db77ede97ad86c27e501d646a27ab57b59a574f725d98ab1fb4" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cexpr", "clang-sys", "lazy_static", @@ -68,6 +68,12 @@ version = "1.3.2" source = "registry+/~https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.4.0" +source = "registry+/~https://github.com/rust-lang/crates.io-index" +checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" + [[package]] name = "block" version = "0.1.6" @@ -151,7 +157,7 @@ version = "0.22.0" source = "registry+/~https://github.com/rust-lang/crates.io-index" checksum = "667fdc068627a2816b9ff831201dd9864249d6ee8d190b9532357f1fc0f61ea7" dependencies = [ - "bitflags", + "bitflags 1.3.2", "block", "core-foundation 0.9.3", "core-graphics 0.21.0", @@ -170,6 +176,19 @@ dependencies = [ "memchr", ] +[[package]] +name = "console" +version = "0.15.7" +source = "registry+/~https://github.com/rust-lang/crates.io-index" +checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", + "unicode-width", + "windows-sys 0.45.0", +] + [[package]] name = "core-foundation" version = "0.7.0" @@ -214,7 +233,7 @@ version = "0.19.2" source = "registry+/~https://github.com/rust-lang/crates.io-index" checksum = "b3889374e6ea6ab25dba90bb5d96202f61108058361f6dc72e8b03e6f8bbe923" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation 0.7.0", "foreign-types", "libc", @@ -226,7 +245,7 @@ version = "0.21.0" source = "registry+/~https://github.com/rust-lang/crates.io-index" checksum = "52a67c4378cf203eace8fb6567847eb641fd6ff933c1145a115c6ee820ebb978" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation 0.9.3", "foreign-types", "libc", @@ -238,7 +257,7 @@ version = "0.11.2" source = "registry+/~https://github.com/rust-lang/crates.io-index" checksum = "cb17e2d1795b1996419648915df94bc7103c28f7b48062d7acf4652fc371b2ff" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation-sys 0.6.2", "coreaudio-sys", ] @@ -283,6 +302,25 @@ version = "0.11.0" source = "registry+/~https://github.com/rust-lang/crates.io-index" checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f" +[[package]] +name = "dialoguer" +version = "0.11.0" +source = "registry+/~https://github.com/rust-lang/crates.io-index" +checksum = "658bce805d770f407bc62102fca7c2c64ceef2fbcb2b8bd19d2765ce093980de" +dependencies = [ + "console", + "shell-words", + "tempfile", + "thiserror", + "zeroize", +] + +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+/~https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + [[package]] name = "encoding_rs" version = "0.8.32" @@ -298,6 +336,33 @@ version = "1.0.0" source = "registry+/~https://github.com/rust-lang/crates.io-index" checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1" +[[package]] +name = "errno" +version = "0.3.3" +source = "registry+/~https://github.com/rust-lang/crates.io-index" +checksum = "136526188508e25c6fef639d7927dfb3e0e3084488bf202267829cf7fc23dbdd" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+/~https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "fastrand" +version = "2.0.0" +source = "registry+/~https://github.com/rust-lang/crates.io-index" +checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" + [[package]] name = "foreign-types" version = "0.3.2" @@ -325,6 +390,15 @@ version = "0.14.0" source = "registry+/~https://github.com/rust-lang/crates.io-index" checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +[[package]] +name = "home" +version = "0.5.5" +source = "registry+/~https://github.com/rust-lang/crates.io-index" +checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +dependencies = [ + "windows-sys 0.48.0", +] + [[package]] name = "hound" version = "3.5.0" @@ -438,6 +512,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "linux-raw-sys" +version = "0.4.5" +source = "registry+/~https://github.com/rust-lang/crates.io-index" +checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" + [[package]] name = "lock_api" version = "0.4.10" @@ -490,7 +570,7 @@ version = "0.7.0" source = "registry+/~https://github.com/rust-lang/crates.io-index" checksum = "451422b7e4718271c8b5b3aadf5adedba43dc76312454b387e98fae0fc951aa0" dependencies = [ - "bitflags", + "bitflags 1.3.2", "jni-sys", "ndk-sys", "num_enum", @@ -519,7 +599,7 @@ version = "0.24.3" source = "registry+/~https://github.com/rust-lang/crates.io-index" checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cfg-if", "libc", ] @@ -713,7 +793,7 @@ version = "0.3.5" source = "registry+/~https://github.com/rust-lang/crates.io-index" checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -750,6 +830,19 @@ version = "1.1.0" source = "registry+/~https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustix" +version = "0.38.11" +source = "registry+/~https://github.com/rust-lang/crates.io-index" +checksum = "c0c3dde1fc030af041adc40e79c0e7fbcf431dd24870053d187d7c66e4b87453" +dependencies = [ + "bitflags 2.4.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.48.0", +] + [[package]] name = "ryu" version = "1.0.13" @@ -802,6 +895,12 @@ dependencies = [ "serde", ] +[[package]] +name = "shell-words" +version = "1.1.0" +source = "registry+/~https://github.com/rust-lang/crates.io-index" +checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" + [[package]] name = "shlex" version = "1.1.0" @@ -832,7 +931,7 @@ version = "0.5.3" source = "registry+/~https://github.com/rust-lang/crates.io-index" checksum = "0f31d7fece546f1e6973011a9eceae948133bbd18fd3d52f6073b1e38ae6368a" dependencies = [ - "bitflags", + "bitflags 1.3.2", "lazy_static", "log", "symphonia-core", @@ -846,7 +945,7 @@ source = "registry+/~https://github.com/rust-lang/crates.io-index" checksum = "f7c73eb88fee79705268cc7b742c7bc93a7b76e092ab751d0833866970754142" dependencies = [ "arrayvec", - "bitflags", + "bitflags 1.3.2", "bytemuck", "lazy_static", "log", @@ -887,14 +986,16 @@ dependencies = [ ] [[package]] -name = "test-keyboard" -version = "0.1.0" +name = "tempfile" +version = "3.8.0" +source = "registry+/~https://github.com/rust-lang/crates.io-index" +checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" dependencies = [ - "anyhow", - "rdev", - "rodio", - "serde", - "serde_json", + "cfg-if", + "fastrand", + "redox_syscall", + "rustix", + "windows-sys 0.48.0", ] [[package]] @@ -955,6 +1056,12 @@ version = "1.0.9" source = "registry+/~https://github.com/rust-lang/crates.io-index" checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" +[[package]] +name = "unicode-width" +version = "0.1.10" +source = "registry+/~https://github.com/rust-lang/crates.io-index" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" + [[package]] name = "walkdir" version = "2.3.3" @@ -1041,6 +1148,19 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "whisper-keys" +version = "1.0.0" +dependencies = [ + "anyhow", + "dialoguer", + "home", + "rdev", + "rodio", + "serde", + "serde_json", +] + [[package]] name = "winapi" version = "0.3.9" @@ -1081,6 +1201,24 @@ dependencies = [ "windows-targets 0.42.2", ] +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+/~https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+/~https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.0", +] + [[package]] name = "windows-targets" version = "0.42.2" @@ -1213,3 +1351,9 @@ dependencies = [ "libc", "pkg-config", ] + +[[package]] +name = "zeroize" +version = "1.6.0" +source = "registry+/~https://github.com/rust-lang/crates.io-index" +checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" diff --git a/Cargo.toml b/Cargo.toml index 555905b..02b27aa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,12 +1,13 @@ [package] -name = "test-keyboard" -version = "0.1.0" +name = "whisper-keys" +version = "1.0.0" edition = "2021" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] anyhow = "1.0.75" +dialoguer = "0.11.0" +home = "0.5.5" rdev = "0.5.3" rodio = "0.17.1" serde = { version = "1.0.164", features = ["derive"] } diff --git a/README.md b/README.md new file mode 100644 index 0000000..59cbbf9 --- /dev/null +++ b/README.md @@ -0,0 +1,41 @@ +# Whisper Keys +Little side project that I made for myself and few friends, rewrite of the initial project [Mechvibes](/~https://github.com/hainguyents13/mechvibes) (#rewriteInRust). The goal was to pratice rust and make a more efficient version of the initial project. + +# What is this ? +As I previously said it's a rewrite of Mechvibes, a little software that emulates the sound of a mechanical keyword when you type, your coworkers and wallet will thank you. + +# State +At the moment there's only a CLI version, I'm planning to make a GUI version, but there's a problem with the lib that I'm using to listen to keyboard events, so I'm waiting for a fix. + +This is only a rewrite of mechvibes, and not __yet__ of mechvibes++ (though I'm planning to do it). + +# Features +Add your soundpacks, you can choose between them at startup. There's also a translater between mechvibes config and whisper-keys config, trying to be as easy as possible to switch. + +# Installation +You can download the latest release [here](/~https://github.com/NotAJocke/whisper-keys/releases/latest) and add it to your path, or you can build it yourself if your binary isn't available. + +### Build +Requirement: [Rust toolchain](https://www.rust-lang.org/tools/install) +```bash +$ git clone /~https://github.com/NotAJocke/whisper-keys.git +$ cd whisper-keys +$ cargo install --path . +``` + +# Usage +Run once to generate the pack folder, then add your soundpacks to the folder (`~/WhisperKeys`), and run again to choose your soundpack. +```bash +$ whisper-keys +``` + +### Translating mechvibes config +```bash +$ whisper-keys --translate +``` + +### Generating a new empty soundpack +This will create a folder `Pack_Name` in the location where you run the command. +```bash +$ whisper-keys --generate +``` \ No newline at end of file diff --git a/assets/Cream/altpitch.mp3 b/assets/Cream/altpitch.mp3 deleted file mode 100644 index 05e88ed..0000000 Binary files a/assets/Cream/altpitch.mp3 and /dev/null differ diff --git a/assets/Cream/backspace.mp3 b/assets/Cream/backspace.mp3 deleted file mode 100644 index c515cab..0000000 Binary files a/assets/Cream/backspace.mp3 and /dev/null differ diff --git a/assets/Cream/config.json b/assets/Cream/config.json deleted file mode 100644 index 3ec8e6d..0000000 --- a/assets/Cream/config.json +++ /dev/null @@ -1,108 +0,0 @@ -{ - "alt": "midpitch.mp3", - "altgr": "midpitch.mp3", - "backspace": "midpitch.mp3", - "capslock": "midpitch.mp3", - "controlleft": "midpitch.mp3", - "controlright": "midpitch.mp3", - "delete": "midpitch.mp3", - "downarrow": "midpitch.mp3", - "end": "midpitch.mp3", - "escape": "altpitch.mp3", - "f1": "midpitch.mp3", - "f10": "midpitch.mp3", - "f11": "midpitch.mp3", - "f12": "midpitch.mp3", - "f2": "midpitch.mp3", - "f3": "midpitch.mp3", - "f4": "midpitch.mp3", - "f5": "midpitch.mp3", - "f6": "midpitch.mp3", - "f7": "midpitch.mp3", - "f8": "midpitch.mp3", - "f9": "midpitch.mp3", - "home": "midpitch.mp3", - "leftarrow": "midpitch.mp3", - "metaleft": "midpitch.mp3", - "metaright": "midpitch.mp3", - "pagedown": "midpitch.mp3", - "pageup": "midpitch.mp3", - "returnk": "midpitch.mp3", - "rightarrow": "midpitch.mp3", - "shiftleft": "midpitch.mp3", - "shiftright": "midpitch.mp3", - "space": "midpitch.mp3", - "tab": "midpitch.mp3", - "uparrow": "midpitch.mp3", - "printscreen": "midpitch.mp3", - "scrolllock": "midpitch.mp3", - "pause": "midpitch.mp3", - "numlock": "midpitch.mp3", - "backquote": "midpitch.mp3", - "num1": "midpitch.mp3", - "num2": "midpitch.mp3", - "num3": "midpitch.mp3", - "num4": "midpitch.mp3", - "num5": "midpitch.mp3", - "num6": "midpitch.mp3", - "num7": "midpitch.mp3", - "num8": "midpitch.mp3", - "num9": "midpitch.mp3", - "num0": "midpitch.mp3", - "minus": "midpitch.mp3", - "equal": "midpitch.mp3", - "keyq": "highpitch.mp3", - "keyw": "lowpitch.mp3", - "keye": "midpitch.mp3", - "keyr": "midpitch.mp3", - "keyt": "midpitch.mp3", - "keyy": "midpitch.mp3", - "keyu": "midpitch.mp3", - "keyi": "midpitch.mp3", - "keyo": "midpitch.mp3", - "keyp": "midpitch.mp3", - "leftbracket": "midpitch.mp3", - "rightbracket": "midpitch.mp3", - "keya": "midpitch.mp3", - "keys": "midpitch.mp3", - "keyd": "midpitch.mp3", - "keyf": "midpitch.mp3", - "keyg": "midpitch.mp3", - "keyh": "midpitch.mp3", - "keyj": "midpitch.mp3", - "keyk": "midpitch.mp3", - "keyl": "midpitch.mp3", - "semicolon": "midpitch.mp3", - "quote": "midpitch.mp3", - "backslash": "midpitch.mp3", - "intlbackslash": "midpitch.mp3", - "keyz": "midpitch.mp3", - "keyx": "midpitch.mp3", - "keyc": "midpitch.mp3", - "keyv": "midpitch.mp3", - "keyb": "midpitch.mp3", - "keyn": "midpitch.mp3", - "keym": "midpitch.mp3", - "comma": "midpitch.mp3", - "dot": "midpitch.mp3", - "slash": "midpitch.mp3", - "insert": "midpitch.mp3", - "kpreturn": "midpitch.mp3", - "kpminus": "midpitch.mp3", - "kpplus": "midpitch.mp3", - "kpmultiply": "midpitch.mp3", - "kpdivide": "midpitch.mp3", - "kp0": "midpitch.mp3", - "kp1": "midpitch.mp3", - "kp2": "midpitch.mp3", - "kp3": "midpitch.mp3", - "kp4": "midpitch.mp3", - "kp5": "midpitch.mp3", - "kp6": "midpitch.mp3", - "kp7": "midpitch.mp3", - "kp8": "midpitch.mp3", - "kp9": "midpitch.mp3", - "kpdelete": "midpitch.mp3", - "function": "midpitch.mp3", - "unknown": "midpitch.mp3" -} \ No newline at end of file diff --git a/assets/Cream/config_older.json b/assets/Cream/config_older.json deleted file mode 100644 index a08f827..0000000 --- a/assets/Cream/config_older.json +++ /dev/null @@ -1,127 +0,0 @@ -{ - "id": "custom-sound-pack-1621216786772", - "name": "Creammmm", - "key_define_type": "multi", - "includes_numpad": false, - "sound": "sound.ogg", - "defines": { - "1": "altpitch.mp3", - "2": "midpitch.mp3", - "3": "lowpitch.mp3", - "4": "midpitch.mp3", - "5": "highpitch.mp3", - "6": "lowpitch.mp3", - "7": "lowpitch.mp3", - "8": "midpitch.mp3", - "9": "lowpitch.mp3", - "10": "highpitch.mp3", - "11": "midpitch.mp3", - "12": "midpitch.mp3", - "13": "altpitch.mp3", - "14": "altpitch.mp3", - "15": "altpitch.mp3", - "16": "highpitch.mp3", - "17": "lowpitch.mp3", - "18": "midpitch.mp3", - "19": "lowpitch.mp3", - "20": "lowpitch.mp3", - "21": "midpitch.mp3", - "22": "highpitch.mp3", - "23": "midpitch.mp3", - "24": "midpitch.mp3", - "25": "altpitch.mp3", - "26": "midpitch.mp3", - "27": "midpitch.mp3", - "28": "altpitch.mp3", - "29": "highpitch.mp3", - "30": "lowpitch.mp3", - "31": "lowpitch.mp3", - "32": "highpitch.mp3", - "33": "lowpitch.mp3", - "34": "midpitch.mp3", - "35": "lowpitch.mp3", - "36": "midpitch.mp3", - "37": "midpitch.mp3", - "38": "altpitch.mp3", - "39": "midpitch.mp3", - "40": "highpitch.mp3", - "41": "altpitch.mp3", - "42": "midpitch.mp3", - "43": "highpitch.mp3", - "44": "midpitch.mp3", - "45": "lowpitch.mp3", - "46": "lowpitch.mp3", - "47": "lowpitch.mp3", - "48": "highpitch.mp3", - "49": "midpitch.mp3", - "50": "lowpitch.mp3", - "51": "midpitch.mp3", - "52": "midpitch.mp3", - "53": "altpitch.mp3", - "54": "midpitch.mp3", - "55": "highpitch.mp3", - "56": "highpitch.mp3", - "57": "spacebar.mp3", - "58": "altpitch.mp3", - "59": "lowpitch.mp3", - "60": "lowpitch.mp3", - "61": "highpitch.mp3", - "62": "altpitch.mp3", - "63": "lowpitch.mp3", - "64": "lowpitch.mp3", - "65": "highpitch.mp3", - "66": "lowpitch.mp3", - "67": "lowpitch.mp3", - "68": "highpitch.mp3", - "69": "lowpitch.mp3", - "70": "lowpitch.mp3", - "71": "lowpitch.mp3", - "72": "midpitch.mp3", - "73": "midpitch.mp3", - "74": "midpitch.mp3", - "75": "midpitch.mp3", - "76": "lowpitch.mp3", - "77": "midpitch.mp3", - "78": "highpitch.mp3", - "79": "lowpitch.mp3", - "80": "midpitch.mp3", - "81": "highpitch.mp3", - "82": "lowpitch.mp3", - "83": "lowpitch.mp3", - "87": "midpitch.mp3", - "88": "midpitch.mp3", - "91": null, - "92": null, - "93": null, - "3597": null, - "3612": "backspace.mp3", - "3613": "lowpitch.mp3", - "3637": "midpitch.mp3", - "3639": "midpitch.mp3", - "3640": "lowpitch.mp3", - "3653": "midpitch.mp3", - "3655": "highpitch.mp3", - "3657": "lowpitch.mp3", - "3663": "midpitch.mp3", - "3665": "lowpitch.mp3", - "3666": "lowpitch.mp3", - "3667": "lowpitch.mp3", - "3675": "lowpitch.mp3", - "3676": "lowpitch.mp3", - "3677": "lowpitch.mp3", - "57416": "midpitch.mp3", - "57419": "highpitch.mp3", - "57421": "midpitch.mp3", - "57424": "lowpitch.mp3", - "60999": "highpitch.mp3", - "61000": "midpitch.mp3", - "61001": "lowpitch.mp3", - "61003": "highpitch.mp3", - "61005": "midpitch.mp3", - "61007": "midpitch.mp3", - "61008": "altpitch.mp3", - "61009": "lowpitch.mp3", - "61010": "lowpitch.mp3", - "61011": "lowpitch.mp3" - } -} \ No newline at end of file diff --git a/assets/Cream/highpitch.mp3 b/assets/Cream/highpitch.mp3 deleted file mode 100644 index d9aa0a2..0000000 Binary files a/assets/Cream/highpitch.mp3 and /dev/null differ diff --git a/assets/Cream/lowpitch.mp3 b/assets/Cream/lowpitch.mp3 deleted file mode 100644 index 547e75b..0000000 Binary files a/assets/Cream/lowpitch.mp3 and /dev/null differ diff --git a/assets/Cream/midpitch.mp3 b/assets/Cream/midpitch.mp3 deleted file mode 100644 index 6ed14e8..0000000 Binary files a/assets/Cream/midpitch.mp3 and /dev/null differ diff --git a/assets/Cream/spacebar.mp3 b/assets/Cream/spacebar.mp3 deleted file mode 100644 index 0a42674..0000000 Binary files a/assets/Cream/spacebar.mp3 and /dev/null differ diff --git a/assets/a.wav b/assets/a.wav deleted file mode 100644 index 23e25b5..0000000 Binary files a/assets/a.wav and /dev/null differ diff --git a/assets/nk-cream/[.wav b/assets/nk-cream/[.wav deleted file mode 100644 index 30474bb..0000000 Binary files a/assets/nk-cream/[.wav and /dev/null differ diff --git a/assets/nk-cream/].wav b/assets/nk-cream/].wav deleted file mode 100644 index 8cee564..0000000 Binary files a/assets/nk-cream/].wav and /dev/null differ diff --git a/assets/nk-cream/a.wav b/assets/nk-cream/a.wav deleted file mode 100644 index 23e25b5..0000000 Binary files a/assets/nk-cream/a.wav and /dev/null differ diff --git a/assets/nk-cream/b.wav b/assets/nk-cream/b.wav deleted file mode 100644 index 04de3fc..0000000 Binary files a/assets/nk-cream/b.wav and /dev/null differ diff --git a/assets/nk-cream/backspace.wav b/assets/nk-cream/backspace.wav deleted file mode 100644 index 1dc56b9..0000000 Binary files a/assets/nk-cream/backspace.wav and /dev/null differ diff --git a/assets/nk-cream/c.wav b/assets/nk-cream/c.wav deleted file mode 100644 index 5f0bb3d..0000000 Binary files a/assets/nk-cream/c.wav and /dev/null differ diff --git a/assets/nk-cream/caps lock.wav b/assets/nk-cream/caps lock.wav deleted file mode 100644 index 9f46f1e..0000000 Binary files a/assets/nk-cream/caps lock.wav and /dev/null differ diff --git a/assets/nk-cream/config.json b/assets/nk-cream/config.json deleted file mode 100644 index a8eef3b..0000000 --- a/assets/nk-cream/config.json +++ /dev/null @@ -1,127 +0,0 @@ -{ - "id": "custom-sound-pack-1599402588730", - "name": "NK Cream (original by Ryan)", - "key_define_type": "multi", - "includes_numpad": false, - "sound": "sound.ogg", - "defines": { - "1": "q.wav", - "2": "w.wav", - "3": "e.wav", - "4": "e.wav", - "5": "r.wav", - "6": "t.wav", - "7": "y.wav", - "8": "u.wav", - "9": "i.wav", - "10": "o.wav", - "11": "p.wav", - "12": "[.wav", - "13": "].wav", - "14": "backspace.wav", - "15": "tab.wav", - "16": "q.wav", - "17": "w.wav", - "18": "e.wav", - "19": "r.wav", - "20": "t.wav", - "21": "y.wav", - "22": "u.wav", - "23": "i.wav", - "24": "o.wav", - "25": "p.wav", - "26": "[.wav", - "27": "].wav", - "28": "enter.wav", - "29": "tab.wav", - "30": "a.wav", - "31": "s.wav", - "32": "d.wav", - "33": "f.wav", - "34": "g.wav", - "35": "h.wav", - "36": "j.wav", - "37": "k.wav", - "38": "l.wav", - "39": "[.wav", - "40": "].wav", - "41": "q.wav", - "42": "shift.wav", - "43": "backspace.wav", - "44": "z.wav", - "45": "x.wav", - "46": "c.wav", - "47": "v.wav", - "48": "b.wav", - "49": "n.wav", - "50": "m.wav", - "51": "l.wav", - "52": "[.wav", - "53": "].wav", - "54": "shift.wav", - "55": "o.wav", - "56": "e.wav", - "57": "space.wav", - "58": "caps lock.wav", - "59": "w.wav", - "60": "e.wav", - "61": "e.wav", - "62": "r.wav", - "63": "t.wav", - "64": "y.wav", - "65": "u.wav", - "66": "i.wav", - "67": "o.wav", - "68": "p.wav", - "69": "u.wav", - "70": "i.wav", - "71": "y.wav", - "72": "u.wav", - "73": "i.wav", - "74": "p.wav", - "75": "h.wav", - "76": "j.wav", - "77": "k.wav", - "78": "enter.wav", - "79": "b.wav", - "80": "n.wav", - "81": "m.wav", - "82": "shift.wav", - "83": "[.wav", - "87": "].wav", - "88": "].wav", - "91": null, - "92": null, - "93": null, - "3597": null, - "3612": "shift.wav", - "3613": "backspace.wav", - "3637": "i.wav", - "3639": "u.wav", - "3640": "p.wav", - "3653": "o.wav", - "3655": "h.wav", - "3657": "k.wav", - "3663": "n.wav", - "3665": "m.wav", - "3666": "h.wav", - "3667": "b.wav", - "3675": "q.wav", - "3676": "[.wav", - "3677": "].wav", - "57416": "g.wav", - "57419": "c.wav", - "57421": "b.wav", - "57424": "v.wav", - "60999": "h.wav", - "61000": "g.wav", - "61001": "k.wav", - "61003": "c.wav", - "61005": "b.wav", - "61007": "n.wav", - "61008": "v.wav", - "61009": "m.wav", - "61010": "h.wav", - "61011": "b.wav" - } -} diff --git a/assets/nk-cream/d.wav b/assets/nk-cream/d.wav deleted file mode 100644 index 372e2c4..0000000 Binary files a/assets/nk-cream/d.wav and /dev/null differ diff --git a/assets/nk-cream/e.wav b/assets/nk-cream/e.wav deleted file mode 100644 index 0ad8fb8..0000000 Binary files a/assets/nk-cream/e.wav and /dev/null differ diff --git a/assets/nk-cream/enter.wav b/assets/nk-cream/enter.wav deleted file mode 100644 index 717e2cb..0000000 Binary files a/assets/nk-cream/enter.wav and /dev/null differ diff --git a/assets/nk-cream/f.wav b/assets/nk-cream/f.wav deleted file mode 100644 index 7ccf61e..0000000 Binary files a/assets/nk-cream/f.wav and /dev/null differ diff --git a/assets/nk-cream/g.wav b/assets/nk-cream/g.wav deleted file mode 100644 index 4e2a78f..0000000 Binary files a/assets/nk-cream/g.wav and /dev/null differ diff --git a/assets/nk-cream/h.wav b/assets/nk-cream/h.wav deleted file mode 100644 index b9fdc30..0000000 Binary files a/assets/nk-cream/h.wav and /dev/null differ diff --git a/assets/nk-cream/i.wav b/assets/nk-cream/i.wav deleted file mode 100644 index be7f392..0000000 Binary files a/assets/nk-cream/i.wav and /dev/null differ diff --git a/assets/nk-cream/j.wav b/assets/nk-cream/j.wav deleted file mode 100644 index 50cf399..0000000 Binary files a/assets/nk-cream/j.wav and /dev/null differ diff --git a/assets/nk-cream/k.wav b/assets/nk-cream/k.wav deleted file mode 100644 index 04f2229..0000000 Binary files a/assets/nk-cream/k.wav and /dev/null differ diff --git a/assets/nk-cream/l.wav b/assets/nk-cream/l.wav deleted file mode 100644 index 6d4b876..0000000 Binary files a/assets/nk-cream/l.wav and /dev/null differ diff --git a/assets/nk-cream/m.wav b/assets/nk-cream/m.wav deleted file mode 100644 index 1624865..0000000 Binary files a/assets/nk-cream/m.wav and /dev/null differ diff --git a/assets/nk-cream/n.wav b/assets/nk-cream/n.wav deleted file mode 100644 index a02f066..0000000 Binary files a/assets/nk-cream/n.wav and /dev/null differ diff --git a/assets/nk-cream/o.wav b/assets/nk-cream/o.wav deleted file mode 100644 index 30474bb..0000000 Binary files a/assets/nk-cream/o.wav and /dev/null differ diff --git a/assets/nk-cream/p.wav b/assets/nk-cream/p.wav deleted file mode 100644 index 8cee564..0000000 Binary files a/assets/nk-cream/p.wav and /dev/null differ diff --git a/assets/nk-cream/q.wav b/assets/nk-cream/q.wav deleted file mode 100644 index 7032a46..0000000 Binary files a/assets/nk-cream/q.wav and /dev/null differ diff --git a/assets/nk-cream/r.wav b/assets/nk-cream/r.wav deleted file mode 100644 index e172224..0000000 Binary files a/assets/nk-cream/r.wav and /dev/null differ diff --git a/assets/nk-cream/s.wav b/assets/nk-cream/s.wav deleted file mode 100644 index badb009..0000000 Binary files a/assets/nk-cream/s.wav and /dev/null differ diff --git a/assets/nk-cream/shift.wav b/assets/nk-cream/shift.wav deleted file mode 100644 index 717e2cb..0000000 Binary files a/assets/nk-cream/shift.wav and /dev/null differ diff --git a/assets/nk-cream/space.wav b/assets/nk-cream/space.wav deleted file mode 100644 index b1b671f..0000000 Binary files a/assets/nk-cream/space.wav and /dev/null differ diff --git a/assets/nk-cream/t.wav b/assets/nk-cream/t.wav deleted file mode 100644 index 018b90c..0000000 Binary files a/assets/nk-cream/t.wav and /dev/null differ diff --git a/assets/nk-cream/tab.wav b/assets/nk-cream/tab.wav deleted file mode 100644 index 9f46f1e..0000000 Binary files a/assets/nk-cream/tab.wav and /dev/null differ diff --git a/assets/nk-cream/u.wav b/assets/nk-cream/u.wav deleted file mode 100644 index 563754a..0000000 Binary files a/assets/nk-cream/u.wav and /dev/null differ diff --git a/assets/nk-cream/v.wav b/assets/nk-cream/v.wav deleted file mode 100644 index f24e97b..0000000 Binary files a/assets/nk-cream/v.wav and /dev/null differ diff --git a/assets/nk-cream/w.wav b/assets/nk-cream/w.wav deleted file mode 100644 index 61980f4..0000000 Binary files a/assets/nk-cream/w.wav and /dev/null differ diff --git a/assets/nk-cream/x.wav b/assets/nk-cream/x.wav deleted file mode 100644 index f15c6f6..0000000 Binary files a/assets/nk-cream/x.wav and /dev/null differ diff --git a/assets/nk-cream/y.wav b/assets/nk-cream/y.wav deleted file mode 100644 index 4a24977..0000000 Binary files a/assets/nk-cream/y.wav and /dev/null differ diff --git a/assets/nk-cream/z.wav b/assets/nk-cream/z.wav deleted file mode 100644 index 400a534..0000000 Binary files a/assets/nk-cream/z.wav and /dev/null differ diff --git a/src/commands.rs b/src/commands.rs new file mode 100644 index 0000000..bf622f6 --- /dev/null +++ b/src/commands.rs @@ -0,0 +1,86 @@ +use std::{ + fs, + path::Path, + sync::{mpsc, Arc, Mutex}, + thread, +}; + +use crate::{keylogger, mechvibes, packs, player, APP_NAME}; +use anyhow::{Context, Ok, Result}; +use dialoguer::{console::Term, theme::ColorfulTheme, Input, Select}; +use home::home_dir; +use rodio::OutputStream; + +pub fn run() -> Result<()> { + let available_packs = packs::list_available_local().context("Couln't get local packs")?; + let home_dir = home_dir().context("Couldn't find home directory")?; + let packs_folder = Path::new(&home_dir).join(APP_NAME); + + if available_packs.is_empty() { + println!("No custom pack found."); + return Ok(()); + } + + let pack_idx = Select::with_theme(&ColorfulTheme::default()) + .items(&available_packs) + .default(0) + .interact_on(&Term::stderr()) + .unwrap_or(0); + let pack = available_packs[pack_idx].clone(); + + let config = + packs::load_pack(packs_folder, &pack).context("Selected pack couldn't be loaded")?; + let (tx, rx) = mpsc::channel(); + let (_stream, stream_handle) = + OutputStream::try_default().context("Couln't find an audio output channel")?; + + keylogger::listen(tx)?; + + let sound_level: Arc> = Arc::new(Mutex::new(50f32)); + let sound_level_lock = Arc::clone(&sound_level); + println!("Volume set to 50%"); + thread::spawn(move || loop { + let new_sound_level: f32 = Input::new() + .with_prompt("Enter the new volume:") + .interact_text() + .unwrap(); + println!("Volume set to {}%", new_sound_level); + *sound_level_lock.lock().unwrap() = new_sound_level; + }); + + for msg in rx.iter() { + if cfg!(debug_assertions) { + dbg!(&msg); + } + let buf = config.get(&msg).unwrap_or_else(|| { + config + .get("unknown") + .context("Couln't get proprety 'unknown' in config file.") + .unwrap() + }); + player::play_sound( + stream_handle.clone(), + buf.clone(), + *sound_level.lock().unwrap(), + )?; + } + + Ok(()) +} + +pub fn generate_template(path: &str) -> Result<()> { + let pack_path = Path::new(path).join("Pack_Name"); + fs::create_dir_all(&pack_path)?; + let template = include_str!("config_template.json"); + fs::write(pack_path.join("config.json"), template)?; + + Ok(()) +} + +pub fn translate_config(path: &str) -> Result<()> { + mechvibes::translate_config(path)?; + + println!("Config translated at location: {}", path); + + Ok(()) +} diff --git a/src/config_template.json b/src/config_template.json index bfa6d15..bdbd489 100644 --- a/src/config_template.json +++ b/src/config_template.json @@ -27,7 +27,7 @@ "metaright": "", "pagedown": "", "pageup": "", - "returnk": "", + "return": "", "rightarrow": "", "shiftleft": "", "shiftright": "", diff --git a/src/key_wrapper.rs b/src/key_wrapper.rs new file mode 100644 index 0000000..75c099c --- /dev/null +++ b/src/key_wrapper.rs @@ -0,0 +1,19 @@ +use rdev::Key; +use std::fmt::Display; + +pub struct KeyWrapper(pub Key); + +impl Display for KeyWrapper { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?}", self.0) + } +} + +impl KeyWrapper { + pub fn to_lowercase(&self) -> String { + match self.0 { + Key::Unknown(_) => "unknown".to_string(), + _ => format!("{}", self).to_lowercase(), + } + } +} diff --git a/src/keylogger.rs b/src/keylogger.rs new file mode 100644 index 0000000..8fbcec6 --- /dev/null +++ b/src/keylogger.rs @@ -0,0 +1,36 @@ +use anyhow::Result; +use rdev::{self, EventType, Key}; +use std::{sync::mpsc::Sender, thread}; + +use crate::key_wrapper::KeyWrapper; + +pub fn listen(tx: Sender) -> Result<()> { + thread::spawn(move || { + let mut last_key: Option = None; + let mut last_event_type: Option = None; + + rdev::listen(move |event| { + if let EventType::KeyPress(key) = event.event_type { + if let (Some(last_k), Some(last_e)) = (last_key, last_event_type) { + if last_k == key { + if let EventType::KeyPress(_) = last_e { + return; + } + } + } + + let key_lowercase = KeyWrapper(key).to_lowercase(); + + tx.send(key_lowercase).unwrap(); + + last_key = Some(key); + } + + last_event_type = Some(event.event_type); + }) + .map_err(|e| format!("Couldn't start the keylogger.\n\nErr: {:?}", e)) + .unwrap(); + }); + + Ok(()) +} diff --git a/src/main.rs b/src/main.rs index 1f4af06..69ecdbe 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,69 +1,57 @@ -use anyhow::Ok; -use rdev::{listen, EventType, Key}; -use rodio::{self, Decoder, OutputStream, Sink}; +use anyhow::{Context, Ok, Result}; +use home::home_dir; use std::{ - collections::HashMap, - fmt::Display, - fs::{self, File}, - io::BufReader, + env::{self, consts::OS}, + fs, + path::Path, }; -fn main() -> anyhow::Result<()> { - let config = load_config_file()?; +mod commands; +mod key_wrapper; +mod keylogger; +mod mechvibes; +mod packs; +mod player; - let (_stream, stream_handle) = OutputStream::try_default()?; +static APP_NAME: &str = "WhisperKeys"; - let mut last_key: Option = None; - let mut last_event_type: Option = None; +fn main() -> anyhow::Result<()> { + let args = env::args().collect::>().split_off(1); - listen(move |event| { - if let EventType::KeyPress(key) = event.event_type { - println!("KeyPress: {:?}", key); + init()?; - if let (Some(lastk), Some(laste)) = (last_key, last_event_type) { - if lastk == key { - if let EventType::KeyPress(_) = laste { - return; - } + if !args.is_empty() { + match args[0].as_str() { + "--translate" | "-t" => { + if args.len() < 2 { + println!("Please specify the path to the pack folder."); + return Ok(()); } + commands::translate_config(&args[1])?; } - - let mut key_lowercase = format!("{}", KeyWrapper(key)).to_lowercase(); - if key_lowercase == "return" { - key_lowercase = "returnk".to_string(); - } - - let filename = config.get(&key_lowercase).unwrap().to_string(); - let file = File::open(format!("assets/Cream/{}", filename)).unwrap(); - let data = BufReader::new(file); - let source = Decoder::new(data).unwrap(); - let sink = Sink::try_new(&stream_handle).unwrap(); - - sink.set_volume(1.0); - sink.append(source); - sink.detach(); - - last_key = Some(key); + "--generate-template" | "-g" => commands::generate_template("./")?, + _ => commands::run()?, } - - last_event_type = Some(event.event_type); - }) - .map_err(|e| anyhow::Error::msg(format!("{:#?}", e)))?; + } else { + commands::run()?; + } Ok(()) } -fn load_config_file() -> anyhow::Result> { - let file_content = fs::read_to_string("./assets/Cream/config.json")?; - let parsed_content: HashMap = serde_json::from_str(&file_content)?; - - Ok(parsed_content) -} - -pub struct KeyWrapper(pub Key); - -impl Display for KeyWrapper { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:?}", self.0) +fn init() -> Result<()> { + let local_dir = home_dir().context("Couldn't find home directory")?; + let path = match OS { + "windows" => Path::new(&local_dir) + .join("AppData") + .join("Roaming") + .join(APP_NAME), + _ => Path::new(&local_dir).join(APP_NAME), + }; + + if fs::read_dir(&path).is_err() { + fs::create_dir_all(&path)?; } + + Ok(()) } diff --git a/src/mechvibes.rs b/src/mechvibes.rs new file mode 100644 index 0000000..7a5881e --- /dev/null +++ b/src/mechvibes.rs @@ -0,0 +1,190 @@ +use anyhow::{Context, Result}; +use rdev::Key; +use serde_json::Value; +use std::{collections::HashMap, fs, path::Path}; + +use crate::key_wrapper::KeyWrapper; + +#[allow(dead_code)] +#[derive(Debug, serde::Deserialize)] +struct MechVibes { + defines: serde_json::Value, +} + +pub fn translate_config(path: &str) -> Result<()> { + let config_path = Path::new(path).join("config.json"); + let config: String = + fs::read_to_string(&config_path).context("File doesn't exists or is unreachable.")?; + let parsed_config: MechVibes = + serde_json::from_str(&config).context("Couldn't parse the config file.")?; + let mut template: HashMap = HashMap::new(); + + for (key, value) in parsed_config + .defines + .as_object() + .context("Original config file isn't properly formatted")? + { + if value != &Value::Null { + let k = mechvibes_key_translate( + key.parse::() + .context("Unknown value in original config")?, + ); + template.insert(KeyWrapper(k).to_lowercase(), value.to_owned()); + } + } + + if template.get("unknown").is_none() { + println!( + "WARNING: No unknown key found in the config. \ + This means that the keylogger will not be able to \ + detect unknown keys. And will probably crash \ + Please add a key named \"unknown\" to your config." + ); + } + fs::rename(&config_path, config_path.with_extension("json.bak"))?; + + // write to a new file + let serialized = serde_json::to_string_pretty(&template)?; + fs::write(&config_path, serialized)?; + + Ok(()) +} + +// from /~https://github.com/hainguyents13/mechvibes/blob/master/src/libs/keycodes.js +pub fn mechvibes_key_translate(code: u16) -> Key { + match code { + 1 => Key::Escape, + 59 => Key::F1, + 60 => Key::F2, + 61 => Key::F3, + 62 => Key::F4, + 63 => Key::F5, + 64 => Key::F6, + 65 => Key::F7, + 66 => Key::F8, + 67 => Key::F9, + 68 => Key::F10, + 87 => Key::F11, + 88 => Key::F12, + + 41 => Key::BackQuote, + + 2 => Key::Num1, + 3 => Key::Num2, + 4 => Key::Num3, + 5 => Key::Num4, + 6 => Key::Num5, + 7 => Key::Num6, + 8 => Key::Num7, + 9 => Key::Num8, + 10 => Key::Num9, + 11 => Key::Num0, + + 12 => Key::Minus, + 13 => Key::Equal, + 14 => Key::Backspace, + + 15 => Key::Tab, + 58 => Key::CapsLock, + + 30 => Key::KeyA, + 48 => Key::KeyB, + 46 => Key::KeyC, + 32 => Key::KeyD, + 18 => Key::KeyE, + 33 => Key::KeyF, + 34 => Key::KeyG, + 35 => Key::KeyH, + 23 => Key::KeyI, + 36 => Key::KeyJ, + 37 => Key::KeyK, + 38 => Key::KeyL, + 50 => Key::KeyM, + 49 => Key::KeyN, + 24 => Key::KeyO, + 25 => Key::KeyP, + 16 => Key::KeyQ, + 19 => Key::KeyR, + 31 => Key::KeyS, + 20 => Key::KeyT, + 22 => Key::KeyU, + 47 => Key::KeyV, + 17 => Key::KeyW, + 45 => Key::KeyX, + 21 => Key::KeyY, + 44 => Key::KeyZ, + + 26 => Key::LeftBracket, + 27 => Key::RightBracket, + 43 => Key::BackSlash, + + 39 => Key::SemiColon, + 40 => Key::Quote, + 28 => Key::Return, + + 51 => Key::Comma, + 52 => Key::Dot, + 53 => Key::Slash, + + 57 => Key::Space, + + 3639 => Key::PrintScreen, + 70 => Key::ScrollLock, + 3653 => Key::Pause, + + 3636 => Key::Insert, + 3667 => Key::Delete, + 3655 => Key::Home, + 3663 => Key::End, + 3657 => Key::PageUp, + 3665 => Key::PageDown, + + 57416 => Key::UpArrow, + 57419 => Key::LeftArrow, + 57421 => Key::RightArrow, + 57424 => Key::DownArrow, + + 42 => Key::ShiftLeft, + 54 => Key::ShiftRight, + 29 => Key::ControlLeft, + 3613 => Key::ControlRight, + 56 => Key::Alt, + 3640 => Key::AltGr, + 3675 => Key::MetaLeft, + 3676 => Key::MetaRight, + + 69 => Key::NumLock, + 3637 => Key::KpDivide, + 55 => Key::KpMultiply, + 74 => Key::KpMinus, + 3597 => Key::Equal, + 78 => Key::KpPlus, + 3612 => Key::KpReturn, + 83 => Key::Dot, + + 79 => Key::Kp1, + 80 => Key::Kp2, + 81 => Key::Kp3, + 75 => Key::Kp4, + 76 => Key::Kp5, + 77 => Key::Kp6, + 71 => Key::Kp7, + 72 => Key::Kp8, + 73 => Key::Kp9, + 82 => Key::Kp0, + + 3666 => Key::Function, + 61010 => Key::Insert, + 61011 => Key::Delete, + 60999 => Key::Home, + 61007 => Key::End, + 61001 => Key::PageUp, + 61009 => Key::PageDown, + 61000 => Key::UpArrow, + 61003 => Key::LeftArrow, + 61005 => Key::RightArrow, + 61008 => Key::DownArrow, + + _ => Key::Unknown(code.into()), + } +} diff --git a/src/packs.rs b/src/packs.rs new file mode 100644 index 0000000..e0e11db --- /dev/null +++ b/src/packs.rs @@ -0,0 +1,87 @@ +use anyhow::{Context, Result}; +use home::home_dir; +use rodio::{source::Buffered, Decoder, Source}; +use std::{ + collections::HashMap, + env::consts::OS, + ffi::OsString, + fs::{self, File}, + io::BufReader, + path::{Path, PathBuf}, +}; + +use crate::APP_NAME; + +pub fn list_available_local() -> Result> { + let local_dir = home_dir().context("Couldn't get your local dir.")?; + let path = match OS { + "windows" => Path::new(&local_dir) + .join("AppData") + .join("Roaming") + .join(APP_NAME), + _ => Path::new(&local_dir).join(APP_NAME), + }; + let items = fs::read_dir(&path).context("Local dir do not exist or is unreadable.")?; + let subdirs: Vec = items + .filter_map(|d| { + let entry = d.ok()?; + let path = entry.path(); + if path.is_dir() { + Some(entry.file_name()) + } else { + None + } + }) + .collect(); + + let mut packs: Vec = Vec::new(); + for dir in subdirs.iter() { + let path = Path::new(&path).join(dir); + let files = fs::read_dir(path).unwrap(); + let filesnames = files + .filter_map(|f| { + let entry = f.ok()?; + let path = entry.path(); + if path.is_file() { + Some(entry.file_name()) + } else { + None + } + }) + .collect::>(); + let has_config_file = filesnames.contains(&OsString::from("config.json")); + if has_config_file { + packs.push(dir.to_str().unwrap().to_owned()) + } + } + + let subdirs_str: Vec = subdirs + .iter() + .map(|d| d.to_str().unwrap().to_owned()) + .collect(); + + Ok(subdirs_str) +} + +pub fn load_pack( + folder: PathBuf, + pack_name: &str, +) -> Result>>>> { + let path = Path::new(&folder).join(pack_name); + let config = fs::read_to_string(path.join("config.json"))?; + let parsed_config: HashMap = + serde_json::from_str(&config).context("Original config isn't valid")?; + + let mut final_config: HashMap = HashMap::new(); + for (key, value) in parsed_config { + let filepath = path.join(value); + let file = File::open(&filepath).context(format!("Couldn't load file: {:?}", filepath))?; + let buf = BufReader::new(file); + let source = Decoder::new(buf).context("Couldn't decode file")?; + let buffered = Decoder::buffered(source); + + final_config.insert(key, buffered); + } + + Ok(final_config) +} diff --git a/src/player.rs b/src/player.rs new file mode 100644 index 0000000..50a461b --- /dev/null +++ b/src/player.rs @@ -0,0 +1,18 @@ +use anyhow::{Context, Result}; +use std::{fs::File, io::BufReader}; + +use rodio::{source::Buffered, Decoder, OutputStreamHandle, Sink}; + +pub fn play_sound( + stream_handle: OutputStreamHandle, + buf: Buffered>>, + volume: f32, +) -> Result<()> { + let sink = Sink::try_new(&stream_handle).context("Coulnd't create an audio sink.")?; + + sink.set_volume(volume * 0.01); + sink.append(buf.clone()); + sink.detach(); + + Ok(()) +}