|
1 | | - |
2 | 1 | import subprocess |
3 | 2 | import sys |
4 | 3 | import time |
5 | | -import typer |
6 | 4 | from pathlib import Path |
| 5 | + |
| 6 | +import typer |
7 | 7 | from rich import print |
8 | | -from rich.progress import BarColumn |
9 | | -from rich.progress import Progress |
10 | | -from rich.progress import TaskProgressColumn |
11 | | -from rich.progress import TextColumn |
12 | | -from rich.progress import TimeRemainingColumn |
| 8 | +from rich.progress import BarColumn, Progress, TaskProgressColumn, TextColumn, TimeRemainingColumn |
13 | 9 | from rich.rule import Rule |
14 | 10 | from rich.style import Style |
15 | 11 |
|
16 | 12 | from isdb_scanner import __version__ |
17 | | -from isdb_scanner.analyzer import TransportStreamAnalyzeError |
18 | | -from isdb_scanner.analyzer import TransportStreamAnalyzer |
19 | | -from isdb_scanner.constants import LNBVoltage |
20 | | -from isdb_scanner.constants import TransportStreamInfo |
21 | | -from isdb_scanner.formatter import EDCBChSet4TxtFormatter |
22 | | -from isdb_scanner.formatter import EDCBChSet5TxtFormatter |
23 | | -from isdb_scanner.formatter import JSONFormatter |
24 | | -from isdb_scanner.formatter import MirakcConfigYmlFormatter |
25 | | -from isdb_scanner.formatter import MirakurunChannelsYmlFormatter |
26 | | -from isdb_scanner.formatter import MirakurunTunersYmlFormatter |
27 | | -from isdb_scanner.tuner import ISDBTuner |
28 | | -from isdb_scanner.tuner import TunerOpeningError |
29 | | -from isdb_scanner.tuner import TunerOutputError |
30 | | -from isdb_scanner.tuner import TunerTuningError |
| 13 | +from isdb_scanner.analyzer import TransportStreamAnalyzeError, TransportStreamAnalyzer |
| 14 | +from isdb_scanner.constants import LNBVoltage, TransportStreamInfo |
| 15 | +from isdb_scanner.formatter import ( |
| 16 | + EDCBChSet4TxtFormatter, |
| 17 | + EDCBChSet5TxtFormatter, |
| 18 | + JSONFormatter, |
| 19 | + MirakcConfigYmlFormatter, |
| 20 | + MirakurunChannelsYmlFormatter, |
| 21 | + MirakurunTunersYmlFormatter, |
| 22 | +) |
| 23 | +from isdb_scanner.tuner import ISDBTuner, TunerOpeningError, TunerOutputError, TunerTuningError |
31 | 24 |
|
32 | 25 |
|
33 | 26 | def version(value: bool): |
34 | 27 | if value is True: |
35 | 28 | typer.echo(f'ISDBScanner version {__version__}') |
36 | 29 | raise typer.Exit() |
37 | 30 |
|
| 31 | + |
38 | 32 | app = typer.Typer() |
39 | 33 |
|
40 | | -@app.command(help='ISDBScanner: Scans Japanese TV broadcast channels (ISDB-T/ISDB-S) and outputs results in various formats (depends on recisdb)') |
| 34 | + |
| 35 | +@app.command( |
| 36 | + help='ISDBScanner: Scans Japanese TV broadcast channels (ISDB-T/ISDB-S) and outputs results in various formats (depends on recisdb)' |
| 37 | +) |
41 | 38 | def main( |
42 | 39 | output: Path = typer.Argument(Path('scanned/'), help='Output scan results to the specified directory.'), |
43 | | - exclude_pay_tv: bool = typer.Option(False, help='Exclude pay-TV channels from scan results and include only free-to-air terrestrial and BS channels.'), |
| 40 | + exclude_pay_tv: bool = typer.Option( |
| 41 | + False, |
| 42 | + help='Exclude pay-TV channels from scan results and include only free-to-air terrestrial and BS channels.', |
| 43 | + ), |
44 | 44 | output_recisdb_log: bool = typer.Option(False, help='Output recisdb log to stderr.'), |
45 | 45 | list_tuners: bool = typer.Option(False, help='List available ISDB-T/ISDB-S tuners and exit.'), |
46 | 46 | lnb: LNBVoltage = typer.Option(LNBVoltage.LOW, help='LNB voltage for satellite antenna power supply.'), |
47 | 47 | version: bool = typer.Option(None, '--version', callback=version, is_eager=True, help='Show version information.'), |
48 | 48 | ): |
49 | | - |
50 | | - print(Rule( |
51 | | - title = f'ISDBScanner version {__version__}', |
52 | | - characters='=', |
53 | | - style = Style(color='#E33157'), |
54 | | - align = 'center', |
55 | | - )) |
| 49 | + print( |
| 50 | + Rule( |
| 51 | + title=f'ISDBScanner version {__version__}', |
| 52 | + characters='=', |
| 53 | + style=Style(color='#E33157'), |
| 54 | + align='center', |
| 55 | + ) |
| 56 | + ) |
56 | 57 |
|
57 | 58 | # recisdb の実行ファイルがインストールされているか確認 |
58 | 59 | if subprocess.run(['/bin/bash', '-c', 'type recisdb'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL).returncode != 0: |
@@ -108,15 +109,14 @@ def main( |
108 | 109 |
|
109 | 110 | # プログレスバーを開始 |
110 | 111 | progress = Progress( |
111 | | - TextColumn("[progress.description]{task.description}"), |
| 112 | + TextColumn('[progress.description]{task.description}'), |
112 | 113 | BarColumn(bar_width=9999), |
113 | 114 | TaskProgressColumn(), |
114 | 115 | TimeRemainingColumn(), |
115 | 116 | transient=True, |
116 | 117 | ) |
117 | | - task = progress.add_task("[bright_red]Scanning...", total=total_channel_count) |
| 118 | + task = progress.add_task('[bright_red]Scanning...', total=total_channel_count) |
118 | 119 | with progress: |
119 | | - |
120 | 120 | # ***** 地上波のチャンネルスキャン ***** |
121 | 121 |
|
122 | 122 | print('Scanning ISDB-T (Terrestrial) channels...') |
@@ -195,14 +195,15 @@ def main( |
195 | 195 |
|
196 | 196 | # 同一 TSID を持つ物理チャンネルのうち、信号レベルが最も高い物理チャンネルのみを残す |
197 | 197 | for ts_infos in tsid_grouped_physical_channels.values(): |
198 | | - |
199 | 198 | # 同一 TSID を持つ物理チャンネルが1つだけ (正常) の場合は何もしない |
200 | 199 | if len(ts_infos) == 1: |
201 | 200 | continue |
202 | 201 |
|
203 | 202 | print(Rule(characters='-', style=Style(color='#E33157'))) |
204 | | - print(f'[yellow]{ts_infos[0].network_name} (TSID: {ts_infos[0].transport_stream_id}) ' |
205 | | - 'was detected redundantly across multiple physical channels.[/yellow]') |
| 203 | + print( |
| 204 | + f'[yellow]{ts_infos[0].network_name} (TSID: {ts_infos[0].transport_stream_id}) ' |
| 205 | + 'was detected redundantly across multiple physical channels.[/yellow]' |
| 206 | + ) |
206 | 207 | print('[yellow]Outputs only the physical channel with the highest signal level...[/yellow]') |
207 | 208 |
|
208 | 209 | # それぞれの物理チャンネルの信号レベルを計測 |
@@ -231,8 +232,10 @@ def main( |
231 | 232 | if signal_level != max_signal_level: |
232 | 233 | tr_ts_infos.remove(ts_info) |
233 | 234 | else: |
234 | | - print(f'[green]Selected Physical Channel: {ts_info.physical_channel.replace("T", "")}ch | ' |
235 | | - f'Signal Level: {signal_level:.2f} dB[/green]') |
| 235 | + print( |
| 236 | + f'[green]Selected Physical Channel: {ts_info.physical_channel.replace("T", "")}ch | ' |
| 237 | + f'Signal Level: {signal_level:.2f} dB[/green]' |
| 238 | + ) |
236 | 239 |
|
237 | 240 | # 物理チャンネル順にソート |
238 | 241 | tr_ts_infos = sorted(tr_ts_infos, key=lambda x: x.physical_channel) |
@@ -326,54 +329,90 @@ def main( |
326 | 329 | ## JSON のみ常に取得した全チャンネルを出力 |
327 | 330 | JSONFormatter( |
328 | 331 | output / 'Channels.json', |
329 | | - tr_ts_infos, bs_ts_infos, cs_ts_infos, |
330 | | - exclude_pay_tv = False).save() |
| 332 | + tr_ts_infos, |
| 333 | + bs_ts_infos, |
| 334 | + cs_ts_infos, |
| 335 | + exclude_pay_tv=False, |
| 336 | + ).save() |
331 | 337 | EDCBChSet4TxtFormatter( |
332 | 338 | output / 'EDCB-Wine/BonDriver_mirakc(BonDriver_mirakc).ChSet4.txt', |
333 | | - tr_ts_infos, bs_ts_infos, cs_ts_infos, |
334 | | - exclude_pay_tv).save() |
| 339 | + tr_ts_infos, |
| 340 | + bs_ts_infos, |
| 341 | + cs_ts_infos, |
| 342 | + exclude_pay_tv, |
| 343 | + ).save() |
335 | 344 | EDCBChSet4TxtFormatter( |
336 | 345 | output / 'EDCB-Wine/BonDriver_mirakc_T(BonDriver_mirakc).ChSet4.txt', |
337 | | - tr_ts_infos, [], [], |
338 | | - exclude_pay_tv).save() |
| 346 | + tr_ts_infos, |
| 347 | + [], |
| 348 | + [], |
| 349 | + exclude_pay_tv, |
| 350 | + ).save() |
339 | 351 | EDCBChSet4TxtFormatter( |
340 | 352 | output / 'EDCB-Wine/BonDriver_mirakc_S(BonDriver_mirakc).ChSet4.txt', |
341 | | - [], bs_ts_infos, cs_ts_infos, |
342 | | - exclude_pay_tv).save() |
| 353 | + [], |
| 354 | + bs_ts_infos, |
| 355 | + cs_ts_infos, |
| 356 | + exclude_pay_tv, |
| 357 | + ).save() |
343 | 358 | EDCBChSet5TxtFormatter( |
344 | 359 | output / 'EDCB-Wine/ChSet5.txt', |
345 | | - tr_ts_infos, bs_ts_infos, cs_ts_infos, |
346 | | - exclude_pay_tv).save() |
| 360 | + tr_ts_infos, |
| 361 | + bs_ts_infos, |
| 362 | + cs_ts_infos, |
| 363 | + exclude_pay_tv, |
| 364 | + ).save() |
347 | 365 | MirakurunChannelsYmlFormatter( |
348 | 366 | output / 'Mirakurun/channels.yml', |
349 | | - tr_ts_infos, bs_ts_infos, cs_ts_infos, |
350 | | - exclude_pay_tv).save() |
| 367 | + tr_ts_infos, |
| 368 | + bs_ts_infos, |
| 369 | + cs_ts_infos, |
| 370 | + exclude_pay_tv, |
| 371 | + ).save() |
351 | 372 | MirakurunChannelsYmlFormatter( |
352 | 373 | output / 'Mirakurun/channels_recpt1.yml', |
353 | | - tr_ts_infos, bs_ts_infos, cs_ts_infos, |
354 | | - exclude_pay_tv, recpt1_compatible = True).save() |
| 374 | + tr_ts_infos, |
| 375 | + bs_ts_infos, |
| 376 | + cs_ts_infos, |
| 377 | + exclude_pay_tv, |
| 378 | + recpt1_compatible=True, |
| 379 | + ).save() |
355 | 380 | MirakurunTunersYmlFormatter( |
356 | | - output / 'Mirakurun/tuners.yml', |
357 | | - available_isdbt_tuners, available_isdbs_tuners, available_multi_tuners).save() |
| 381 | + output / 'Mirakurun/tuners.yml', available_isdbt_tuners, available_isdbs_tuners, available_multi_tuners |
| 382 | + ).save() |
358 | 383 | MirakurunTunersYmlFormatter( |
359 | 384 | output / 'Mirakurun/tuners_recpt1.yml', |
360 | | - available_isdbt_tuners, available_isdbs_tuners, available_multi_tuners, |
361 | | - recpt1_compatible = True).save() |
| 385 | + available_isdbt_tuners, |
| 386 | + available_isdbs_tuners, |
| 387 | + available_multi_tuners, |
| 388 | + recpt1_compatible=True, |
| 389 | + ).save() |
362 | 390 | MirakcConfigYmlFormatter( |
363 | 391 | output / 'mirakc/config.yml', |
364 | | - available_isdbt_tuners, available_isdbs_tuners, available_multi_tuners, |
365 | | - tr_ts_infos, bs_ts_infos, cs_ts_infos, |
366 | | - exclude_pay_tv).save() |
| 392 | + available_isdbt_tuners, |
| 393 | + available_isdbs_tuners, |
| 394 | + available_multi_tuners, |
| 395 | + tr_ts_infos, |
| 396 | + bs_ts_infos, |
| 397 | + cs_ts_infos, |
| 398 | + exclude_pay_tv, |
| 399 | + ).save() |
367 | 400 | MirakcConfigYmlFormatter( |
368 | 401 | output / 'mirakc/config_recpt1.yml', |
369 | | - available_isdbt_tuners, available_isdbs_tuners, available_multi_tuners, |
370 | | - tr_ts_infos, bs_ts_infos, cs_ts_infos, |
371 | | - exclude_pay_tv, recpt1_compatible = True).save() |
| 402 | + available_isdbt_tuners, |
| 403 | + available_isdbs_tuners, |
| 404 | + available_multi_tuners, |
| 405 | + tr_ts_infos, |
| 406 | + bs_ts_infos, |
| 407 | + cs_ts_infos, |
| 408 | + exclude_pay_tv, |
| 409 | + recpt1_compatible=True, |
| 410 | + ).save() |
372 | 411 |
|
373 | 412 | print(Rule(characters='=', style=Style(color='#E33157'))) |
374 | 413 | print(f'Finished in {time.time() - scan_start_time:.2f} seconds.') |
375 | 414 | print(Rule(characters='=', style=Style(color='#E33157'))) |
376 | 415 |
|
377 | 416 |
|
378 | | -if __name__ == "__main__": |
| 417 | +if __name__ == '__main__': |
379 | 418 | app() |
0 commit comments