voice-bird-cli 0.2.0__tar.gz → 0.2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {voice_bird_cli-0.2.0 → voice_bird_cli-0.2.2}/PKG-INFO +1 -1
- {voice_bird_cli-0.2.0 → voice_bird_cli-0.2.2}/pyproject.toml +1 -1
- {voice_bird_cli-0.2.0 → voice_bird_cli-0.2.2}/voice-bird-cli/Cargo.lock +335 -1
- {voice_bird_cli-0.2.0 → voice_bird_cli-0.2.2}/voice-bird-cli/Cargo.toml +8 -1
- {voice_bird_cli-0.2.0 → voice_bird_cli-0.2.2}/voice-bird-cli/src/app.rs +18 -0
- voice_bird_cli-0.2.2/voice-bird-cli/src/logger.rs +47 -0
- {voice_bird_cli-0.2.0 → voice_bird_cli-0.2.2}/voice-bird-cli/src/main.rs +70 -1
- {voice_bird_cli-0.2.0 → voice_bird_cli-0.2.2}/voice-bird-cli/src/platform/macos.rs +29 -15
- {voice_bird_cli-0.2.0 → voice_bird_cli-0.2.2}/voice-bird-cli/src/ui.rs +28 -0
- {voice_bird_cli-0.2.0 → voice_bird_cli-0.2.2}/python/voice_bird_cli/__init__.py +0 -0
- {voice_bird_cli-0.2.0 → voice_bird_cli-0.2.2}/python/voice_bird_cli/__main__.py +0 -0
- {voice_bird_cli-0.2.0 → voice_bird_cli-0.2.2}/voice-bird-cli/README.md +0 -0
- {voice_bird_cli-0.2.0 → voice_bird_cli-0.2.2}/voice-bird-cli/src/audio.rs +0 -0
- {voice_bird_cli-0.2.0 → voice_bird_cli-0.2.2}/voice-bird-cli/src/config.rs +0 -0
- {voice_bird_cli-0.2.0 → voice_bird_cli-0.2.2}/voice-bird-cli/src/platform/mod.rs +0 -0
- {voice_bird_cli-0.2.0 → voice_bird_cli-0.2.2}/voice-bird-cli/src/platform/windows.rs +0 -0
- {voice_bird_cli-0.2.0 → voice_bird_cli-0.2.2}/voice-bird-cli/src/streaming.rs +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "maturin"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "voice-bird-cli"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.2"
|
|
8
8
|
description = "Voice Bird CLI - Terminal audio streaming for voice transcription"
|
|
9
9
|
authors = [{ name = "Dzmitry Rekun" }]
|
|
10
10
|
readme = "voice-bird-cli/README.md"
|
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
# It is not intended for manual editing.
|
|
3
3
|
version = 4
|
|
4
4
|
|
|
5
|
+
[[package]]
|
|
6
|
+
name = "adler2"
|
|
7
|
+
version = "2.0.1"
|
|
8
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
9
|
+
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
|
|
10
|
+
|
|
5
11
|
[[package]]
|
|
6
12
|
name = "aho-corasick"
|
|
7
13
|
version = "1.1.4"
|
|
@@ -54,6 +60,26 @@ version = "1.0.100"
|
|
|
54
60
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
55
61
|
checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
|
|
56
62
|
|
|
63
|
+
[[package]]
|
|
64
|
+
name = "arboard"
|
|
65
|
+
version = "3.6.1"
|
|
66
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
67
|
+
checksum = "0348a1c054491f4bfe6ab86a7b6ab1e44e45d899005de92f58b3df180b36ddaf"
|
|
68
|
+
dependencies = [
|
|
69
|
+
"clipboard-win",
|
|
70
|
+
"image",
|
|
71
|
+
"log",
|
|
72
|
+
"objc2",
|
|
73
|
+
"objc2-app-kit",
|
|
74
|
+
"objc2-core-foundation",
|
|
75
|
+
"objc2-core-graphics",
|
|
76
|
+
"objc2-foundation",
|
|
77
|
+
"parking_lot",
|
|
78
|
+
"percent-encoding",
|
|
79
|
+
"windows-sys 0.60.2",
|
|
80
|
+
"x11rb",
|
|
81
|
+
]
|
|
82
|
+
|
|
57
83
|
[[package]]
|
|
58
84
|
name = "autocfg"
|
|
59
85
|
version = "1.5.0"
|
|
@@ -114,12 +140,24 @@ version = "3.19.1"
|
|
|
114
140
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
115
141
|
checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510"
|
|
116
142
|
|
|
143
|
+
[[package]]
|
|
144
|
+
name = "bytemuck"
|
|
145
|
+
version = "1.25.0"
|
|
146
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
147
|
+
checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec"
|
|
148
|
+
|
|
117
149
|
[[package]]
|
|
118
150
|
name = "byteorder"
|
|
119
151
|
version = "1.5.0"
|
|
120
152
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
121
153
|
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
|
122
154
|
|
|
155
|
+
[[package]]
|
|
156
|
+
name = "byteorder-lite"
|
|
157
|
+
version = "0.1.0"
|
|
158
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
159
|
+
checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495"
|
|
160
|
+
|
|
123
161
|
[[package]]
|
|
124
162
|
name = "bytes"
|
|
125
163
|
version = "1.11.0"
|
|
@@ -207,6 +245,15 @@ dependencies = [
|
|
|
207
245
|
"libloading",
|
|
208
246
|
]
|
|
209
247
|
|
|
248
|
+
[[package]]
|
|
249
|
+
name = "clipboard-win"
|
|
250
|
+
version = "5.4.1"
|
|
251
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
252
|
+
checksum = "bde03770d3df201d4fb868f2c9c59e66a3e4e2bd06692a0fe701e7103c7e84d4"
|
|
253
|
+
dependencies = [
|
|
254
|
+
"error-code",
|
|
255
|
+
]
|
|
256
|
+
|
|
210
257
|
[[package]]
|
|
211
258
|
name = "combine"
|
|
212
259
|
version = "4.6.7"
|
|
@@ -391,6 +438,15 @@ dependencies = [
|
|
|
391
438
|
"libc",
|
|
392
439
|
]
|
|
393
440
|
|
|
441
|
+
[[package]]
|
|
442
|
+
name = "crc32fast"
|
|
443
|
+
version = "1.5.0"
|
|
444
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
445
|
+
checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
|
|
446
|
+
dependencies = [
|
|
447
|
+
"cfg-if",
|
|
448
|
+
]
|
|
449
|
+
|
|
394
450
|
[[package]]
|
|
395
451
|
name = "crossterm"
|
|
396
452
|
version = "0.28.1"
|
|
@@ -416,6 +472,12 @@ dependencies = [
|
|
|
416
472
|
"winapi",
|
|
417
473
|
]
|
|
418
474
|
|
|
475
|
+
[[package]]
|
|
476
|
+
name = "crunchy"
|
|
477
|
+
version = "0.2.4"
|
|
478
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
479
|
+
checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5"
|
|
480
|
+
|
|
419
481
|
[[package]]
|
|
420
482
|
name = "crypto-common"
|
|
421
483
|
version = "0.1.7"
|
|
@@ -509,6 +571,16 @@ version = "0.2.0"
|
|
|
509
571
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
510
572
|
checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b"
|
|
511
573
|
|
|
574
|
+
[[package]]
|
|
575
|
+
name = "dispatch2"
|
|
576
|
+
version = "0.3.0"
|
|
577
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
578
|
+
checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec"
|
|
579
|
+
dependencies = [
|
|
580
|
+
"bitflags 2.10.0",
|
|
581
|
+
"objc2",
|
|
582
|
+
]
|
|
583
|
+
|
|
512
584
|
[[package]]
|
|
513
585
|
name = "either"
|
|
514
586
|
version = "1.15.0"
|
|
@@ -531,18 +603,72 @@ dependencies = [
|
|
|
531
603
|
"windows-sys 0.61.2",
|
|
532
604
|
]
|
|
533
605
|
|
|
606
|
+
[[package]]
|
|
607
|
+
name = "error-code"
|
|
608
|
+
version = "3.3.2"
|
|
609
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
610
|
+
checksum = "dea2df4cf52843e0452895c455a1a2cfbb842a1e7329671acf418fdc53ed4c59"
|
|
611
|
+
|
|
534
612
|
[[package]]
|
|
535
613
|
name = "fastrand"
|
|
536
614
|
version = "2.3.0"
|
|
537
615
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
538
616
|
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
|
|
539
617
|
|
|
618
|
+
[[package]]
|
|
619
|
+
name = "fax"
|
|
620
|
+
version = "0.2.6"
|
|
621
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
622
|
+
checksum = "f05de7d48f37cd6730705cbca900770cab77a89f413d23e100ad7fad7795a0ab"
|
|
623
|
+
dependencies = [
|
|
624
|
+
"fax_derive",
|
|
625
|
+
]
|
|
626
|
+
|
|
627
|
+
[[package]]
|
|
628
|
+
name = "fax_derive"
|
|
629
|
+
version = "0.2.0"
|
|
630
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
631
|
+
checksum = "a0aca10fb742cb43f9e7bb8467c91aa9bcb8e3ffbc6a6f7389bb93ffc920577d"
|
|
632
|
+
dependencies = [
|
|
633
|
+
"proc-macro2",
|
|
634
|
+
"quote",
|
|
635
|
+
"syn",
|
|
636
|
+
]
|
|
637
|
+
|
|
638
|
+
[[package]]
|
|
639
|
+
name = "fdeflate"
|
|
640
|
+
version = "0.3.7"
|
|
641
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
642
|
+
checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c"
|
|
643
|
+
dependencies = [
|
|
644
|
+
"simd-adler32",
|
|
645
|
+
]
|
|
646
|
+
|
|
647
|
+
[[package]]
|
|
648
|
+
name = "fern"
|
|
649
|
+
version = "0.7.1"
|
|
650
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
651
|
+
checksum = "4316185f709b23713e41e3195f90edef7fb00c3ed4adc79769cf09cc762a3b29"
|
|
652
|
+
dependencies = [
|
|
653
|
+
"log",
|
|
654
|
+
]
|
|
655
|
+
|
|
540
656
|
[[package]]
|
|
541
657
|
name = "find-msvc-tools"
|
|
542
658
|
version = "0.1.8"
|
|
543
659
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
544
660
|
checksum = "8591b0bcc8a98a64310a2fae1bb3e9b8564dd10e381e6e28010fde8e8e8568db"
|
|
545
661
|
|
|
662
|
+
[[package]]
|
|
663
|
+
name = "flate2"
|
|
664
|
+
version = "1.1.9"
|
|
665
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
666
|
+
checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c"
|
|
667
|
+
dependencies = [
|
|
668
|
+
"crc32fast",
|
|
669
|
+
"miniz_oxide",
|
|
670
|
+
]
|
|
671
|
+
|
|
546
672
|
[[package]]
|
|
547
673
|
name = "foldhash"
|
|
548
674
|
version = "0.1.5"
|
|
@@ -651,6 +777,16 @@ dependencies = [
|
|
|
651
777
|
"version_check",
|
|
652
778
|
]
|
|
653
779
|
|
|
780
|
+
[[package]]
|
|
781
|
+
name = "gethostname"
|
|
782
|
+
version = "1.1.0"
|
|
783
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
784
|
+
checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8"
|
|
785
|
+
dependencies = [
|
|
786
|
+
"rustix 1.1.3",
|
|
787
|
+
"windows-link",
|
|
788
|
+
]
|
|
789
|
+
|
|
654
790
|
[[package]]
|
|
655
791
|
name = "getrandom"
|
|
656
792
|
version = "0.2.17"
|
|
@@ -680,6 +816,17 @@ version = "0.3.3"
|
|
|
680
816
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
681
817
|
checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280"
|
|
682
818
|
|
|
819
|
+
[[package]]
|
|
820
|
+
name = "half"
|
|
821
|
+
version = "2.7.1"
|
|
822
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
823
|
+
checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b"
|
|
824
|
+
dependencies = [
|
|
825
|
+
"cfg-if",
|
|
826
|
+
"crunchy",
|
|
827
|
+
"zerocopy",
|
|
828
|
+
]
|
|
829
|
+
|
|
683
830
|
[[package]]
|
|
684
831
|
name = "hashbrown"
|
|
685
832
|
version = "0.15.5"
|
|
@@ -755,6 +902,20 @@ version = "1.0.1"
|
|
|
755
902
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
756
903
|
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
|
757
904
|
|
|
905
|
+
[[package]]
|
|
906
|
+
name = "image"
|
|
907
|
+
version = "0.25.9"
|
|
908
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
909
|
+
checksum = "e6506c6c10786659413faa717ceebcb8f70731c0a60cbae39795fdf114519c1a"
|
|
910
|
+
dependencies = [
|
|
911
|
+
"bytemuck",
|
|
912
|
+
"byteorder-lite",
|
|
913
|
+
"moxcms",
|
|
914
|
+
"num-traits",
|
|
915
|
+
"png",
|
|
916
|
+
"tiff",
|
|
917
|
+
]
|
|
918
|
+
|
|
758
919
|
[[package]]
|
|
759
920
|
name = "indexmap"
|
|
760
921
|
version = "2.13.0"
|
|
@@ -963,6 +1124,16 @@ version = "0.2.1"
|
|
|
963
1124
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
964
1125
|
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
|
965
1126
|
|
|
1127
|
+
[[package]]
|
|
1128
|
+
name = "miniz_oxide"
|
|
1129
|
+
version = "0.8.9"
|
|
1130
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1131
|
+
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
|
|
1132
|
+
dependencies = [
|
|
1133
|
+
"adler2",
|
|
1134
|
+
"simd-adler32",
|
|
1135
|
+
]
|
|
1136
|
+
|
|
966
1137
|
[[package]]
|
|
967
1138
|
name = "mio"
|
|
968
1139
|
version = "1.1.1"
|
|
@@ -975,6 +1146,16 @@ dependencies = [
|
|
|
975
1146
|
"windows-sys 0.61.2",
|
|
976
1147
|
]
|
|
977
1148
|
|
|
1149
|
+
[[package]]
|
|
1150
|
+
name = "moxcms"
|
|
1151
|
+
version = "0.7.11"
|
|
1152
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1153
|
+
checksum = "ac9557c559cd6fc9867e122e20d2cbefc9ca29d80d027a8e39310920ed2f0a97"
|
|
1154
|
+
dependencies = [
|
|
1155
|
+
"num-traits",
|
|
1156
|
+
"pxfm",
|
|
1157
|
+
]
|
|
1158
|
+
|
|
978
1159
|
[[package]]
|
|
979
1160
|
name = "native-tls"
|
|
980
1161
|
version = "0.2.14"
|
|
@@ -1110,12 +1291,70 @@ dependencies = [
|
|
|
1110
1291
|
"objc2-encode",
|
|
1111
1292
|
]
|
|
1112
1293
|
|
|
1294
|
+
[[package]]
|
|
1295
|
+
name = "objc2-app-kit"
|
|
1296
|
+
version = "0.3.2"
|
|
1297
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1298
|
+
checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c"
|
|
1299
|
+
dependencies = [
|
|
1300
|
+
"bitflags 2.10.0",
|
|
1301
|
+
"objc2",
|
|
1302
|
+
"objc2-core-graphics",
|
|
1303
|
+
"objc2-foundation",
|
|
1304
|
+
]
|
|
1305
|
+
|
|
1306
|
+
[[package]]
|
|
1307
|
+
name = "objc2-core-foundation"
|
|
1308
|
+
version = "0.3.2"
|
|
1309
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1310
|
+
checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536"
|
|
1311
|
+
dependencies = [
|
|
1312
|
+
"bitflags 2.10.0",
|
|
1313
|
+
"dispatch2",
|
|
1314
|
+
"objc2",
|
|
1315
|
+
]
|
|
1316
|
+
|
|
1317
|
+
[[package]]
|
|
1318
|
+
name = "objc2-core-graphics"
|
|
1319
|
+
version = "0.3.2"
|
|
1320
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1321
|
+
checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807"
|
|
1322
|
+
dependencies = [
|
|
1323
|
+
"bitflags 2.10.0",
|
|
1324
|
+
"dispatch2",
|
|
1325
|
+
"objc2",
|
|
1326
|
+
"objc2-core-foundation",
|
|
1327
|
+
"objc2-io-surface",
|
|
1328
|
+
]
|
|
1329
|
+
|
|
1113
1330
|
[[package]]
|
|
1114
1331
|
name = "objc2-encode"
|
|
1115
1332
|
version = "4.1.0"
|
|
1116
1333
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1117
1334
|
checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33"
|
|
1118
1335
|
|
|
1336
|
+
[[package]]
|
|
1337
|
+
name = "objc2-foundation"
|
|
1338
|
+
version = "0.3.2"
|
|
1339
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1340
|
+
checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272"
|
|
1341
|
+
dependencies = [
|
|
1342
|
+
"bitflags 2.10.0",
|
|
1343
|
+
"objc2",
|
|
1344
|
+
"objc2-core-foundation",
|
|
1345
|
+
]
|
|
1346
|
+
|
|
1347
|
+
[[package]]
|
|
1348
|
+
name = "objc2-io-surface"
|
|
1349
|
+
version = "0.3.2"
|
|
1350
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1351
|
+
checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d"
|
|
1352
|
+
dependencies = [
|
|
1353
|
+
"bitflags 2.10.0",
|
|
1354
|
+
"objc2",
|
|
1355
|
+
"objc2-core-foundation",
|
|
1356
|
+
]
|
|
1357
|
+
|
|
1119
1358
|
[[package]]
|
|
1120
1359
|
name = "objc_exception"
|
|
1121
1360
|
version = "0.1.2"
|
|
@@ -1233,6 +1472,12 @@ version = "1.0.15"
|
|
|
1233
1472
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1234
1473
|
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
|
|
1235
1474
|
|
|
1475
|
+
[[package]]
|
|
1476
|
+
name = "percent-encoding"
|
|
1477
|
+
version = "2.3.2"
|
|
1478
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1479
|
+
checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
|
|
1480
|
+
|
|
1236
1481
|
[[package]]
|
|
1237
1482
|
name = "pin-project-lite"
|
|
1238
1483
|
version = "0.2.16"
|
|
@@ -1251,6 +1496,19 @@ version = "0.3.32"
|
|
|
1251
1496
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1252
1497
|
checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
|
|
1253
1498
|
|
|
1499
|
+
[[package]]
|
|
1500
|
+
name = "png"
|
|
1501
|
+
version = "0.18.1"
|
|
1502
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1503
|
+
checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61"
|
|
1504
|
+
dependencies = [
|
|
1505
|
+
"bitflags 2.10.0",
|
|
1506
|
+
"crc32fast",
|
|
1507
|
+
"fdeflate",
|
|
1508
|
+
"flate2",
|
|
1509
|
+
"miniz_oxide",
|
|
1510
|
+
]
|
|
1511
|
+
|
|
1254
1512
|
[[package]]
|
|
1255
1513
|
name = "ppv-lite86"
|
|
1256
1514
|
version = "0.2.21"
|
|
@@ -1287,6 +1545,21 @@ dependencies = [
|
|
|
1287
1545
|
"unicode-ident",
|
|
1288
1546
|
]
|
|
1289
1547
|
|
|
1548
|
+
[[package]]
|
|
1549
|
+
name = "pxfm"
|
|
1550
|
+
version = "0.1.27"
|
|
1551
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1552
|
+
checksum = "7186d3822593aa4393561d186d1393b3923e9d6163d3fbfd6e825e3e6cf3e6a8"
|
|
1553
|
+
dependencies = [
|
|
1554
|
+
"num-traits",
|
|
1555
|
+
]
|
|
1556
|
+
|
|
1557
|
+
[[package]]
|
|
1558
|
+
name = "quick-error"
|
|
1559
|
+
version = "2.0.1"
|
|
1560
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1561
|
+
checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3"
|
|
1562
|
+
|
|
1290
1563
|
[[package]]
|
|
1291
1564
|
name = "quote"
|
|
1292
1565
|
version = "1.0.43"
|
|
@@ -1635,6 +1908,12 @@ dependencies = [
|
|
|
1635
1908
|
"libc",
|
|
1636
1909
|
]
|
|
1637
1910
|
|
|
1911
|
+
[[package]]
|
|
1912
|
+
name = "simd-adler32"
|
|
1913
|
+
version = "0.3.8"
|
|
1914
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1915
|
+
checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2"
|
|
1916
|
+
|
|
1638
1917
|
[[package]]
|
|
1639
1918
|
name = "slab"
|
|
1640
1919
|
version = "0.4.11"
|
|
@@ -1761,6 +2040,20 @@ dependencies = [
|
|
|
1761
2040
|
"syn",
|
|
1762
2041
|
]
|
|
1763
2042
|
|
|
2043
|
+
[[package]]
|
|
2044
|
+
name = "tiff"
|
|
2045
|
+
version = "0.10.3"
|
|
2046
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2047
|
+
checksum = "af9605de7fee8d9551863fd692cce7637f548dbd9db9180fcc07ccc6d26c336f"
|
|
2048
|
+
dependencies = [
|
|
2049
|
+
"fax",
|
|
2050
|
+
"flate2",
|
|
2051
|
+
"half",
|
|
2052
|
+
"quick-error",
|
|
2053
|
+
"weezl",
|
|
2054
|
+
"zune-jpeg",
|
|
2055
|
+
]
|
|
2056
|
+
|
|
1764
2057
|
[[package]]
|
|
1765
2058
|
name = "tokio"
|
|
1766
2059
|
version = "1.49.0"
|
|
@@ -1944,16 +2237,19 @@ checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
|
|
1944
2237
|
|
|
1945
2238
|
[[package]]
|
|
1946
2239
|
name = "voice-bird-cli"
|
|
1947
|
-
version = "0.2.
|
|
2240
|
+
version = "0.2.2"
|
|
1948
2241
|
dependencies = [
|
|
1949
2242
|
"anyhow",
|
|
2243
|
+
"arboard",
|
|
1950
2244
|
"chrono",
|
|
1951
2245
|
"cpal",
|
|
1952
2246
|
"crossterm",
|
|
1953
2247
|
"dirs",
|
|
2248
|
+
"fern",
|
|
1954
2249
|
"futures-util",
|
|
1955
2250
|
"hound",
|
|
1956
2251
|
"http",
|
|
2252
|
+
"log",
|
|
1957
2253
|
"ratatui",
|
|
1958
2254
|
"rubato",
|
|
1959
2255
|
"screencapturekit",
|
|
@@ -2060,6 +2356,12 @@ dependencies = [
|
|
|
2060
2356
|
"wasm-bindgen",
|
|
2061
2357
|
]
|
|
2062
2358
|
|
|
2359
|
+
[[package]]
|
|
2360
|
+
name = "weezl"
|
|
2361
|
+
version = "0.1.12"
|
|
2362
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2363
|
+
checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88"
|
|
2364
|
+
|
|
2063
2365
|
[[package]]
|
|
2064
2366
|
name = "winapi"
|
|
2065
2367
|
version = "0.3.9"
|
|
@@ -2546,6 +2848,23 @@ version = "0.51.0"
|
|
|
2546
2848
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2547
2849
|
checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5"
|
|
2548
2850
|
|
|
2851
|
+
[[package]]
|
|
2852
|
+
name = "x11rb"
|
|
2853
|
+
version = "0.13.2"
|
|
2854
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2855
|
+
checksum = "9993aa5be5a26815fe2c3eacfc1fde061fc1a1f094bf1ad2a18bf9c495dd7414"
|
|
2856
|
+
dependencies = [
|
|
2857
|
+
"gethostname",
|
|
2858
|
+
"rustix 1.1.3",
|
|
2859
|
+
"x11rb-protocol",
|
|
2860
|
+
]
|
|
2861
|
+
|
|
2862
|
+
[[package]]
|
|
2863
|
+
name = "x11rb-protocol"
|
|
2864
|
+
version = "0.13.2"
|
|
2865
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2866
|
+
checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd"
|
|
2867
|
+
|
|
2549
2868
|
[[package]]
|
|
2550
2869
|
name = "zerocopy"
|
|
2551
2870
|
version = "0.8.33"
|
|
@@ -2571,3 +2890,18 @@ name = "zmij"
|
|
|
2571
2890
|
version = "1.0.15"
|
|
2572
2891
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2573
2892
|
checksum = "94f63c051f4fe3c1509da62131a678643c5b6fbdc9273b2b79d4378ebda003d2"
|
|
2893
|
+
|
|
2894
|
+
[[package]]
|
|
2895
|
+
name = "zune-core"
|
|
2896
|
+
version = "0.4.12"
|
|
2897
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2898
|
+
checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a"
|
|
2899
|
+
|
|
2900
|
+
[[package]]
|
|
2901
|
+
name = "zune-jpeg"
|
|
2902
|
+
version = "0.4.21"
|
|
2903
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2904
|
+
checksum = "29ce2c8a9384ad323cf564b67da86e21d3cfdff87908bc1223ed5c99bc792713"
|
|
2905
|
+
dependencies = [
|
|
2906
|
+
"zune-core",
|
|
2907
|
+
]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "voice-bird-cli"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.2"
|
|
4
4
|
edition = "2021"
|
|
5
5
|
description = "Voice Bird CLI - Terminal audio streaming for voice transcription"
|
|
6
6
|
readme = "README.md"
|
|
@@ -25,6 +25,13 @@ tokio-tungstenite = { version = "0.23", features = ["connect", "native-tls"], de
|
|
|
25
25
|
futures-util = "0.3"
|
|
26
26
|
http = "1.0"
|
|
27
27
|
|
|
28
|
+
# Logging
|
|
29
|
+
log = "0.4"
|
|
30
|
+
fern = "0.7"
|
|
31
|
+
|
|
32
|
+
# Clipboard
|
|
33
|
+
arboard = "3"
|
|
34
|
+
|
|
28
35
|
# Utilities
|
|
29
36
|
anyhow = "1.0"
|
|
30
37
|
serde = { version = "1.0", features = ["derive"] }
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
use std::path::PathBuf;
|
|
1
2
|
use std::sync::{Arc, Mutex};
|
|
2
3
|
use uuid::Uuid;
|
|
3
4
|
|
|
@@ -69,6 +70,12 @@ pub struct App {
|
|
|
69
70
|
|
|
70
71
|
/// Status message to display
|
|
71
72
|
pub status_message: Option<String>,
|
|
73
|
+
|
|
74
|
+
/// Shared error channel — recording threads write errors here
|
|
75
|
+
pub error_channel: Arc<Mutex<Option<String>>>,
|
|
76
|
+
|
|
77
|
+
/// Path to the current log file
|
|
78
|
+
pub log_path: Option<PathBuf>,
|
|
72
79
|
}
|
|
73
80
|
|
|
74
81
|
impl App {
|
|
@@ -90,6 +97,8 @@ impl App {
|
|
|
90
97
|
api_key_input: String::new(),
|
|
91
98
|
should_quit: false,
|
|
92
99
|
status_message: None,
|
|
100
|
+
error_channel: Arc::new(Mutex::new(None)),
|
|
101
|
+
log_path: None,
|
|
93
102
|
}
|
|
94
103
|
}
|
|
95
104
|
|
|
@@ -191,6 +200,15 @@ impl App {
|
|
|
191
200
|
self.api_key_input.clear();
|
|
192
201
|
}
|
|
193
202
|
|
|
203
|
+
/// Check for errors from recording threads and update status
|
|
204
|
+
pub fn check_error(&mut self) {
|
|
205
|
+
if let Ok(mut err) = self.error_channel.lock() {
|
|
206
|
+
if let Some(msg) = err.take() {
|
|
207
|
+
self.status = RecordingStatus::Error(msg);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
194
212
|
/// Toggle help display
|
|
195
213
|
pub fn toggle_help(&mut self) {
|
|
196
214
|
self.mode = if self.mode == AppMode::Help {
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
use anyhow::Result;
|
|
2
|
+
use chrono::Local;
|
|
3
|
+
use std::fs;
|
|
4
|
+
use std::path::PathBuf;
|
|
5
|
+
|
|
6
|
+
/// Initialize file-based logging for the CLI.
|
|
7
|
+
///
|
|
8
|
+
/// Logs to `~/.voice-bird-cli/logs/voice_bird_cli_YYYY-MM-DD_HH-MM-SS.log`.
|
|
9
|
+
/// All levels (DEBUG+) go to file only — nothing to terminal (TUI owns the screen).
|
|
10
|
+
/// Returns the log file path so the app can display it.
|
|
11
|
+
pub fn init() -> Result<PathBuf> {
|
|
12
|
+
let logs_dir = dirs::home_dir()
|
|
13
|
+
.ok_or_else(|| anyhow::anyhow!("Could not determine home directory"))?
|
|
14
|
+
.join(".voice-bird-cli")
|
|
15
|
+
.join("logs");
|
|
16
|
+
|
|
17
|
+
fs::create_dir_all(&logs_dir)?;
|
|
18
|
+
|
|
19
|
+
let log_filename = format!(
|
|
20
|
+
"voice_bird_cli_{}.log",
|
|
21
|
+
Local::now().format("%Y-%m-%d_%H-%M-%S")
|
|
22
|
+
);
|
|
23
|
+
let log_path = logs_dir.join(log_filename);
|
|
24
|
+
|
|
25
|
+
let log_file = fs::OpenOptions::new()
|
|
26
|
+
.create(true)
|
|
27
|
+
.write(true)
|
|
28
|
+
.truncate(true)
|
|
29
|
+
.open(&log_path)?;
|
|
30
|
+
|
|
31
|
+
fern::Dispatch::new()
|
|
32
|
+
.format(|out, message, record| {
|
|
33
|
+
out.finish(format_args!(
|
|
34
|
+
"[{} {} {}] {}",
|
|
35
|
+
Local::now().format("%Y-%m-%d %H:%M:%S"),
|
|
36
|
+
record.level(),
|
|
37
|
+
record.target(),
|
|
38
|
+
message
|
|
39
|
+
))
|
|
40
|
+
})
|
|
41
|
+
.level(log::LevelFilter::Debug)
|
|
42
|
+
.chain(log_file)
|
|
43
|
+
.apply()
|
|
44
|
+
.map_err(|e| anyhow::anyhow!("Failed to initialize logger: {}", e))?;
|
|
45
|
+
|
|
46
|
+
Ok(log_path)
|
|
47
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
mod app;
|
|
2
2
|
mod audio;
|
|
3
3
|
mod config;
|
|
4
|
+
mod logger;
|
|
4
5
|
mod platform;
|
|
5
6
|
mod streaming;
|
|
6
7
|
mod ui;
|
|
@@ -21,6 +22,17 @@ use uuid::Uuid;
|
|
|
21
22
|
use app::{App, AppMode, RecordingStatus, ActiveSession};
|
|
22
23
|
|
|
23
24
|
fn main() -> Result<()> {
|
|
25
|
+
// Initialize file logger before TUI takes over the screen
|
|
26
|
+
let log_path = match logger::init() {
|
|
27
|
+
Ok(path) => Some(path),
|
|
28
|
+
Err(e) => {
|
|
29
|
+
eprintln!("Warning: failed to initialize logger: {}", e);
|
|
30
|
+
None
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
log::info!("Voice Bird CLI starting");
|
|
35
|
+
|
|
24
36
|
// Setup terminal
|
|
25
37
|
enable_raw_mode()?;
|
|
26
38
|
let mut stdout = io::stdout();
|
|
@@ -30,8 +42,11 @@ fn main() -> Result<()> {
|
|
|
30
42
|
|
|
31
43
|
// Create app and run
|
|
32
44
|
let mut app = App::new();
|
|
45
|
+
app.log_path = log_path;
|
|
33
46
|
app.refresh_sessions();
|
|
34
47
|
|
|
48
|
+
log::info!("Found {} audio sessions", app.sessions.len());
|
|
49
|
+
|
|
35
50
|
let result = run_app(&mut terminal, &mut app);
|
|
36
51
|
|
|
37
52
|
// Restore terminal
|
|
@@ -44,9 +59,12 @@ fn main() -> Result<()> {
|
|
|
44
59
|
terminal.show_cursor()?;
|
|
45
60
|
|
|
46
61
|
if let Err(e) = result {
|
|
62
|
+
log::error!("Application error: {}", e);
|
|
47
63
|
eprintln!("Error: {}", e);
|
|
48
64
|
}
|
|
49
65
|
|
|
66
|
+
log::info!("Voice Bird CLI exiting");
|
|
67
|
+
|
|
50
68
|
Ok(())
|
|
51
69
|
}
|
|
52
70
|
|
|
@@ -55,6 +73,9 @@ fn run_app<B: Backend>(terminal: &mut Terminal<B>, app: &mut App) -> Result<()>
|
|
|
55
73
|
// Update duration if recording
|
|
56
74
|
app.update_duration();
|
|
57
75
|
|
|
76
|
+
// Check for errors from recording threads
|
|
77
|
+
app.check_error();
|
|
78
|
+
|
|
58
79
|
// Draw UI
|
|
59
80
|
terminal.draw(|f| ui::render(f, app))?;
|
|
60
81
|
|
|
@@ -109,6 +130,12 @@ fn handle_normal_mode(app: &mut App, key: KeyCode) {
|
|
|
109
130
|
KeyCode::Enter => {
|
|
110
131
|
toggle_recording(app);
|
|
111
132
|
}
|
|
133
|
+
KeyCode::Char('l') => {
|
|
134
|
+
copy_error_to_clipboard(app);
|
|
135
|
+
}
|
|
136
|
+
KeyCode::Char('L') => {
|
|
137
|
+
copy_log_path_to_clipboard(app);
|
|
138
|
+
}
|
|
112
139
|
_ => {}
|
|
113
140
|
}
|
|
114
141
|
}
|
|
@@ -140,6 +167,36 @@ fn handle_help_mode(app: &mut App, key: KeyCode) {
|
|
|
140
167
|
}
|
|
141
168
|
}
|
|
142
169
|
|
|
170
|
+
fn copy_error_to_clipboard(app: &mut App) {
|
|
171
|
+
if let RecordingStatus::Error(ref msg) = app.status {
|
|
172
|
+
let text = msg.clone();
|
|
173
|
+
match arboard::Clipboard::new().and_then(|mut cb| cb.set_text(&text)) {
|
|
174
|
+
Ok(()) => {
|
|
175
|
+
app.status_message = Some("Error copied to clipboard".to_string());
|
|
176
|
+
}
|
|
177
|
+
Err(e) => {
|
|
178
|
+
log::warn!("Failed to copy to clipboard: {}", e);
|
|
179
|
+
app.status_message = Some(format!("Clipboard error: {}", e));
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
fn copy_log_path_to_clipboard(app: &mut App) {
|
|
186
|
+
if let Some(ref path) = app.log_path {
|
|
187
|
+
let text = path.display().to_string();
|
|
188
|
+
match arboard::Clipboard::new().and_then(|mut cb| cb.set_text(&text)) {
|
|
189
|
+
Ok(()) => {
|
|
190
|
+
app.status_message = Some("Log path copied to clipboard".to_string());
|
|
191
|
+
}
|
|
192
|
+
Err(e) => {
|
|
193
|
+
log::warn!("Failed to copy to clipboard: {}", e);
|
|
194
|
+
app.status_message = Some(format!("Clipboard error: {}", e));
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
143
200
|
fn toggle_recording(app: &mut App) {
|
|
144
201
|
match &app.status {
|
|
145
202
|
RecordingStatus::Idle | RecordingStatus::Error(_) => {
|
|
@@ -176,6 +233,7 @@ fn start_recording(app: &mut App) {
|
|
|
176
233
|
let session_id = Uuid::new_v4();
|
|
177
234
|
let stop_signal = Arc::new(Mutex::new(false));
|
|
178
235
|
let audio_level = app.audio_level.clone();
|
|
236
|
+
let error_channel = app.error_channel.clone();
|
|
179
237
|
|
|
180
238
|
let server_url_clone = server_url.clone();
|
|
181
239
|
let api_key_clone = api_key.clone();
|
|
@@ -184,6 +242,11 @@ fn start_recording(app: &mut App) {
|
|
|
184
242
|
let stop_signal_clone = stop_signal.clone();
|
|
185
243
|
let audio_level_clone = audio_level.clone();
|
|
186
244
|
|
|
245
|
+
log::info!(
|
|
246
|
+
"Starting recording: session={}, device={}, input={}",
|
|
247
|
+
session_id_str, session_clone.device_name, session_clone.is_input
|
|
248
|
+
);
|
|
249
|
+
|
|
187
250
|
// Spawn recording thread
|
|
188
251
|
std::thread::spawn(move || {
|
|
189
252
|
let result = if session_clone.is_input {
|
|
@@ -209,7 +272,11 @@ fn start_recording(app: &mut App) {
|
|
|
209
272
|
};
|
|
210
273
|
|
|
211
274
|
if let Err(e) = result {
|
|
212
|
-
|
|
275
|
+
let msg = format!("Recording error: {}", e);
|
|
276
|
+
log::error!("{}", msg);
|
|
277
|
+
if let Ok(mut err) = error_channel.lock() {
|
|
278
|
+
*err = Some(msg);
|
|
279
|
+
}
|
|
213
280
|
}
|
|
214
281
|
});
|
|
215
282
|
|
|
@@ -229,6 +296,8 @@ fn start_recording(app: &mut App) {
|
|
|
229
296
|
}
|
|
230
297
|
|
|
231
298
|
fn stop_all_sessions(app: &mut App) {
|
|
299
|
+
log::info!("Stopping all sessions");
|
|
300
|
+
|
|
232
301
|
for session in &app.active_sessions {
|
|
233
302
|
if let Ok(mut stop) = session.stop_signal.lock() {
|
|
234
303
|
*stop = true;
|
|
@@ -46,16 +46,21 @@ fn check_macos_version() -> Result<String> {
|
|
|
46
46
|
|
|
47
47
|
/// Enumerate audio sessions on macOS using ScreenCaptureKit
|
|
48
48
|
pub fn enumerate_audio_sessions() -> Result<Vec<AudioSession>> {
|
|
49
|
-
check_macos_version()?;
|
|
49
|
+
let version = check_macos_version()?;
|
|
50
|
+
|
|
51
|
+
log::info!("Enumerating macOS audio sessions (macOS {})", version);
|
|
50
52
|
|
|
51
53
|
let content = SCShareableContent::get()
|
|
52
|
-
.map_err(|e|
|
|
53
|
-
"
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
54
|
+
.map_err(|e| {
|
|
55
|
+
log::error!("SCShareableContent::get() failed: {:?}", e);
|
|
56
|
+
anyhow::anyhow!(
|
|
57
|
+
"Screen Recording permission is required for audio capture.\n\n\
|
|
58
|
+
Grant permission in:\n \
|
|
59
|
+
System Settings > Privacy & Security > Screen Recording\n\n\
|
|
60
|
+
After granting permission, restart the application.\n\
|
|
61
|
+
Error: {:?}", e
|
|
62
|
+
)
|
|
63
|
+
})?;
|
|
59
64
|
|
|
60
65
|
let mut sessions = Vec::new();
|
|
61
66
|
|
|
@@ -122,14 +127,22 @@ pub fn start_output_recording(
|
|
|
122
127
|
) -> Result<()> {
|
|
123
128
|
let macos_version = check_macos_version()?;
|
|
124
129
|
|
|
130
|
+
log::info!(
|
|
131
|
+
"Starting macOS output recording: app={}, device={}, macOS {}",
|
|
132
|
+
session.app_name, session.device_name, macos_version
|
|
133
|
+
);
|
|
134
|
+
|
|
125
135
|
let content = SCShareableContent::get()
|
|
126
|
-
.map_err(|e|
|
|
127
|
-
"
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
136
|
+
.map_err(|e| {
|
|
137
|
+
log::error!("SCShareableContent::get() failed in start_output_recording: {:?}", e);
|
|
138
|
+
anyhow::anyhow!(
|
|
139
|
+
"Screen Recording permission is required for audio capture.\n\n\
|
|
140
|
+
Grant permission in:\n \
|
|
141
|
+
System Settings > Privacy & Security > Screen Recording\n\n\
|
|
142
|
+
After granting permission, restart the application.\n\
|
|
143
|
+
Error: {:?}", e
|
|
144
|
+
)
|
|
145
|
+
})?;
|
|
133
146
|
|
|
134
147
|
let (tx, rx) = mpsc::channel::<Vec<f32>>();
|
|
135
148
|
|
|
@@ -245,6 +258,7 @@ pub fn start_output_recording(
|
|
|
245
258
|
stream.add_output_handler(handler, SCStreamOutputType::Audio);
|
|
246
259
|
stream.start_capture()
|
|
247
260
|
.map_err(|e| {
|
|
261
|
+
log::error!("SCStream::start_capture() failed: {:?}", e);
|
|
248
262
|
let err_str = format!("{:?}", e);
|
|
249
263
|
let hint = if err_str.contains("CoreGraphicsErrorDomain") || err_str.contains("1003") {
|
|
250
264
|
format!(
|
|
@@ -40,12 +40,22 @@ fn render_title(frame: &mut Frame, area: Rect, app: &App) {
|
|
|
40
40
|
Span::styled(" [API Key: Not Set]", Style::default().fg(Color::Yellow))
|
|
41
41
|
};
|
|
42
42
|
|
|
43
|
+
let log_info = if let Some(ref path) = app.log_path {
|
|
44
|
+
Span::styled(
|
|
45
|
+
format!(" [log: {}]", path.display()),
|
|
46
|
+
Style::default().fg(Color::DarkGray),
|
|
47
|
+
)
|
|
48
|
+
} else {
|
|
49
|
+
Span::raw("")
|
|
50
|
+
};
|
|
51
|
+
|
|
43
52
|
let title = Line::from(vec![
|
|
44
53
|
Span::styled(
|
|
45
54
|
format!(" Voice Bird CLI v{} ", env!("CARGO_PKG_VERSION")),
|
|
46
55
|
Style::default().fg(Color::Cyan).add_modifier(Modifier::BOLD),
|
|
47
56
|
),
|
|
48
57
|
api_status,
|
|
58
|
+
log_info,
|
|
49
59
|
Span::raw(" "),
|
|
50
60
|
Span::styled("[q]", Style::default().fg(Color::DarkGray)),
|
|
51
61
|
Span::raw("uit "),
|
|
@@ -185,6 +195,20 @@ fn render_controls(frame: &mut Frame, area: Rect, app: &App) {
|
|
|
185
195
|
Span::raw("onfig "),
|
|
186
196
|
]);
|
|
187
197
|
|
|
198
|
+
// Show copy controls when there's an error or log path
|
|
199
|
+
if matches!(app.status, RecordingStatus::Error(_)) {
|
|
200
|
+
all_controls.extend(vec![
|
|
201
|
+
Span::styled("[l]", Style::default().fg(Color::Yellow)),
|
|
202
|
+
Span::raw(" copy error "),
|
|
203
|
+
]);
|
|
204
|
+
}
|
|
205
|
+
if app.log_path.is_some() {
|
|
206
|
+
all_controls.extend(vec![
|
|
207
|
+
Span::styled("[L]", Style::default().fg(Color::Yellow)),
|
|
208
|
+
Span::raw(" copy log path "),
|
|
209
|
+
]);
|
|
210
|
+
}
|
|
211
|
+
|
|
188
212
|
let controls_line = Line::from(all_controls);
|
|
189
213
|
|
|
190
214
|
let block = Block::default()
|
|
@@ -259,6 +283,10 @@ fn render_help_dialog(frame: &mut Frame) {
|
|
|
259
283
|
" Configuration:",
|
|
260
284
|
" c Configure API key",
|
|
261
285
|
"",
|
|
286
|
+
" Diagnostics:",
|
|
287
|
+
" l Copy error text to clipboard",
|
|
288
|
+
" L Copy log file path to clipboard",
|
|
289
|
+
"",
|
|
262
290
|
" Other:",
|
|
263
291
|
" ? Toggle this help",
|
|
264
292
|
" q Quit application",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|