forked from th0ma5w/rtl_fm_python
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrtl_fm_python_common.py
More file actions
179 lines (140 loc) · 4.84 KB
/
rtl_fm_python_common.py
File metadata and controls
179 lines (140 loc) · 4.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# rtl-sdr, turns your Realtek RTL2832 based DVB dongle into a SDR receiver
# Copyright (C) 2012 by Steve Markgraf <steve@steve-m.de>
# Copyright (C) 2012 by Hoernchen <la@tfc-server.de>
# Copyright (C) 2012 by Kyle Keen <keenerd@gmail.com>
# Copyright (C) 2013 by Elias Oenal <EliasOenal@gmail.com>
# Copyright (C) 2014 by Thomas Winningham <winningham@gmail.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import print_function
import ctypes, sys, os
from time import sleep
from threading import Thread
printstderr = lambda x : print(x,file=sys.stderr)
# Track actual auto gain state - starts True because rtl_fm enables auto gain by default
_auto_gain_enabled = True
# Global reference to FFmpeg process for audio streaming
_ffmpeg_stdin = None
def set_audio_output(ffmpeg_stdin):
"""Redirect stdout to FFmpeg stdin for audio streaming"""
global _ffmpeg_stdin
_ffmpeg_stdin = ffmpeg_stdin
if ffmpeg_stdin is not None:
# Redirect stdout to FFmpeg stdin
os.dup2(ffmpeg_stdin.fileno(), sys.stdout.fileno())
fm = ctypes.CDLL('./rtl_fm_python.so')
get_s_level = fm.lib_get_s_level
get_frequency = fm.lib_get_frequency
set_demod_fm = fm.lib_set_demod_fm
set_demod_wbfm = fm.lib_set_demod_wbfm
set_demod_am = fm.lib_set_demod_am
set_demod_lsb = fm.lib_set_demod_lsb
set_demod_usb = fm.lib_set_demod_usb
set_demod_raw = fm.lib_set_demod_raw
set_frequency = lambda f : fm.lib_set_frequency(ctypes.c_uint32(f))
set_squelch = lambda l : fm.lib_set_squelch_level(ctypes.c_int(l))
get_squelch = fm.lib_get_squelch_level
get_demod = lambda : chr(fm.lib_get_demod_mode())
str_to_freq = lambda f : fm.lib_frequency_convert(f.encode('utf-8'))
# Advanced squelch functions
set_squelch_attack_ms = lambda ms : fm.lib_set_squelch_attack_ms(ctypes.c_int(ms))
set_squelch_hang_ms = lambda ms : fm.lib_set_squelch_hang_ms(ctypes.c_int(ms))
set_squelch_hysteresis = lambda h : fm.lib_set_squelch_hysteresis(ctypes.c_int(h))
get_squelch_attack_ms = fm.lib_get_squelch_attack_ms
get_squelch_hang_ms = fm.lib_get_squelch_hang_ms
get_squelch_hysteresis = fm.lib_get_squelch_hysteresis
get_squelch_open = fm.lib_get_squelch_open
# CTCSS tone squelch functions
fm.lib_set_ctcss_freq.argtypes = [ctypes.c_float]
fm.lib_get_ctcss_freq.restype = ctypes.c_float
set_ctcss_freq = lambda freq : fm.lib_set_ctcss_freq(ctypes.c_float(freq))
get_ctcss_freq = fm.lib_get_ctcss_freq
get_ctcss_detected = fm.lib_get_ctcss_detected
def process_args(l):
c=len(l)+1
argc=ctypes.c_int(c)
argv_var=ctypes.c_char_p *c
argu = ['rtl_fm'] + l
argu = [x.encode('ascii') for x in argu]
argv=argv_var(*argu)
return (argc,argv)
def mag(value, e, suffix):
t = float('1e%s' % e)
i = int(value / float(t))
r = int(value % float(t))
r = str(r).rjust(e,'0')
s = "%s.%s" % (i,r)
while (s[-1]=="0" or s[-1]=="."):
if s[-1]==".":
s=s[:-1]
break
s=s[:-1]
return s + suffix
def freq_to_str(f):
if f >= 1000000000:
return mag(f,9,'G')
if f >= 1000000:
return mag(f,6,'M')
if f >= 1000:
return mag(f,3,'K')
return str(f)
set_freq_human = lambda f : set_frequency(str_to_freq(f))
get_freq_human = lambda : freq_to_str(get_frequency())
def set_demod(c):
if c=='w' : set_demod_wbfm()
if c=='f' : set_demod_fm()
if c=='a' : set_demod_am()
if c=='l' : set_demod_lsb()
if c=='u' : set_demod_usb()
if c=='r' : set_demod_raw()
def get_gains():
c=fm.lib_get_tuner_gains_count()
b=(ctypes.c_int * c)()
fm.lib_get_tuner_gains(b)
return list(b)
def set_gain(g):
fm.lib_set_real_gain(g)
def get_gain():
return fm.lib_get_gain()
def get_auto_gain():
return _auto_gain_enabled
def set_gain_human(g):
global _auto_gain_enabled
_auto_gain_enabled = False
fm.lib_set_gain(g)
def set_auto_gain():
global _auto_gain_enabled
_auto_gain_enabled = True
fm.lib_set_auto_gain()
def set_gain(g):
global _auto_gain_enabled
_auto_gain_enabled = False
fm.lib_set_real_gain(g)
def rtl_fm(args=["--help"]):
fm.main(*process_args(args))
def rtl_fm_setup_and_go(args):
fm.lib_init_first()
fm.lib_process_args_and_go(*process_args(args))
def rtl_fm_loop():
fm.lib_loop()
def rtl_fm_finish():
fm.lib_stop()
fm.lib_output_close()
def rtl_fm_wrapped(args=["--help"]):
rtl_fm_setup_and_go(args)
try:
while True:
sleep(0.01)
except KeyboardInterrupt:
rtl_fm_finish()