├── LGPL3.txt ├── README.md ├── WTFPL.txt ├── automation ├── getlogin.py ├── getnext.py ├── getpromo.py └── login.py ├── icecast └── icecast.xml └── liquidsoap └── radio.liq /LGPL3.txt: -------------------------------------------------------------------------------- 1 | 2 | GNU LESSER GENERAL PUBLIC LICENSE 3 | Version 3, 29 June 2007 4 | 5 | Copyright (C) 2007 Free Software Foundation, Inc. 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | 10 | This version of the GNU Lesser General Public License incorporates 11 | the terms and conditions of version 3 of the GNU General Public 12 | License, supplemented by the additional permissions listed below. 13 | 14 | 0. Additional Definitions. 15 | 16 | As used herein, "this License" refers to version 3 of the GNU Lesser 17 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 18 | General Public License. 19 | 20 | "The Library" refers to a covered work governed by this License, 21 | other than an Application or a Combined Work as defined below. 22 | 23 | An "Application" is any work that makes use of an interface provided 24 | by the Library, but which is not otherwise based on the Library. 25 | Defining a subclass of a class defined by the Library is deemed a mode 26 | of using an interface provided by the Library. 27 | 28 | A "Combined Work" is a work produced by combining or linking an 29 | Application with the Library. The particular version of the Library 30 | with which the Combined Work was made is also called the "Linked 31 | Version". 32 | 33 | The "Minimal Corresponding Source" for a Combined Work means the 34 | Corresponding Source for the Combined Work, excluding any source code 35 | for portions of the Combined Work that, considered in isolation, are 36 | based on the Application, and not on the Linked Version. 37 | 38 | The "Corresponding Application Code" for a Combined Work means the 39 | object code and/or source code for the Application, including any data 40 | and utility programs needed for reproducing the Combined Work from the 41 | Application, but excluding the System Libraries of the Combined Work. 42 | 43 | 1. Exception to Section 3 of the GNU GPL. 44 | 45 | You may convey a covered work under sections 3 and 4 of this License 46 | without being bound by section 3 of the GNU GPL. 47 | 48 | 2. Conveying Modified Versions. 49 | 50 | If you modify a copy of the Library, and, in your modifications, a 51 | facility refers to a function or data to be supplied by an Application 52 | that uses the facility (other than as an argument passed when the 53 | facility is invoked), then you may convey a copy of the modified 54 | version: 55 | 56 | a) under this License, provided that you make a good faith effort to 57 | ensure that, in the event an Application does not supply the 58 | function or data, the facility still operates, and performs 59 | whatever part of its purpose remains meaningful, or 60 | 61 | b) under the GNU GPL, with none of the additional permissions of 62 | this License applicable to that copy. 63 | 64 | 3. Object Code Incorporating Material from Library Header Files. 65 | 66 | The object code form of an Application may incorporate material from 67 | a header file that is part of the Library. You may convey such object 68 | code under terms of your choice, provided that, if the incorporated 69 | material is not limited to numerical parameters, data structure 70 | layouts and accessors, or small macros, inline functions and templates 71 | (ten or fewer lines in length), you do both of the following: 72 | 73 | a) Give prominent notice with each copy of the object code that the 74 | Library is used in it and that the Library and its use are 75 | covered by this License. 76 | 77 | b) Accompany the object code with a copy of the GNU GPL and this license 78 | document. 79 | 80 | 4. Combined Works. 81 | 82 | You may convey a Combined Work under terms of your choice that, 83 | taken together, effectively do not restrict modification of the 84 | portions of the Library contained in the Combined Work and reverse 85 | engineering for debugging such modifications, if you also do each of 86 | the following: 87 | 88 | a) Give prominent notice with each copy of the Combined Work that 89 | the Library is used in it and that the Library and its use are 90 | covered by this License. 91 | 92 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 93 | document. 94 | 95 | c) For a Combined Work that displays copyright notices during 96 | execution, include the copyright notice for the Library among 97 | these notices, as well as a reference directing the user to the 98 | copies of the GNU GPL and this license document. 99 | 100 | d) Do one of the following: 101 | 102 | 0) Convey the Minimal Corresponding Source under the terms of this 103 | License, and the Corresponding Application Code in a form 104 | suitable for, and under terms that permit, the user to 105 | recombine or relink the Application with a modified version of 106 | the Linked Version to produce a modified Combined Work, in the 107 | manner specified by section 6 of the GNU GPL for conveying 108 | Corresponding Source. 109 | 110 | 1) Use a suitable shared library mechanism for linking with the 111 | Library. A suitable mechanism is one that (a) uses at run time 112 | a copy of the Library already present on the user's computer 113 | system, and (b) will operate properly with a modified version 114 | of the Library that is interface-compatible with the Linked 115 | Version. 116 | 117 | e) Provide Installation Information, but only if you would otherwise 118 | be required to provide such information under section 6 of the 119 | GNU GPL, and only to the extent that such information is 120 | necessary to install and execute a modified version of the 121 | Combined Work produced by recombining or relinking the 122 | Application with a modified version of the Linked Version. (If 123 | you use option 4d0, the Installation Information must accompany 124 | the Minimal Corresponding Source and Corresponding Application 125 | Code. If you use option 4d1, you must provide the Installation 126 | Information in the manner specified by section 6 of the GNU GPL 127 | for conveying Corresponding Source.) 128 | 129 | 5. Combined Libraries. 130 | 131 | You may place library facilities that are a work based on the 132 | Library side by side in a single library together with other library 133 | facilities that are not Applications and are not covered by this 134 | License, and convey such a combined library under terms of your 135 | choice, if you do both of the following: 136 | 137 | a) Accompany the combined library with a copy of the same work based 138 | on the Library, uncombined with any other library facilities, 139 | conveyed under the terms of this License. 140 | 141 | b) Give prominent notice with the combined library that part of it 142 | is a work based on the Library, and explaining where to find the 143 | accompanying uncombined form of the same work. 144 | 145 | 6. Revised Versions of the GNU Lesser General Public License. 146 | 147 | The Free Software Foundation may publish revised and/or new versions 148 | of the GNU Lesser General Public License from time to time. Such new 149 | versions will be similar in spirit to the present version, but may 150 | differ in detail to address new problems or concerns. 151 | 152 | Each version is given a distinguishing version number. If the 153 | Library as you received it specifies that a certain numbered version 154 | of the GNU Lesser General Public License "or any later version" 155 | applies to it, you have the option of following the terms and 156 | conditions either of that published version or of any later version 157 | published by the Free Software Foundation. If the Library as you 158 | received it does not specify a version number of the GNU Lesser 159 | General Public License, you may choose any version of the GNU Lesser 160 | General Public License ever published by the Free Software Foundation. 161 | 162 | If the Library as you received it specifies that a proxy can decide 163 | whether future versions of the GNU Lesser General Public License shall 164 | apply, that proxy's public statement of acceptance of any version is 165 | permanent authorization for you to choose that version for the 166 | Library. 167 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Radio Scripts 2 | ============= 3 | 4 | These are some old radio scripts that I used (that still work) to run an 5 | Internet radio station using LiquidSoap, Icecast, and Python. You can use them 6 | to create your own Internet radio station. Multiple DJs are supported, which 7 | each DJ specifying their own individual password. The playlist is controlled 8 | by an external Python script. 9 | 10 | Some forms of these scripts have been running for ~6 years now. <3 LiquidSoap. -------------------------------------------------------------------------------- /WTFPL.txt: -------------------------------------------------------------------------------- 1 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 2 | Version 2, December 2004 3 | 4 | Copyright (C) 2004 Sam Hocevar 5 | 6 | Everyone is permitted to copy and distribute verbatim or modified 7 | copies of this license document, and changing it is allowed as long 8 | as the name is changed. 9 | 10 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 11 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 12 | 13 | 0. You just DO WHAT THE FUCK YOU WANT TO. -------------------------------------------------------------------------------- /automation/getlogin.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2005-2011 sk89q 4 | # 5 | 6 | import sys 7 | from optparse import OptionParser 8 | import MySQLdb 9 | import time 10 | 11 | def main(): 12 | parser = OptionParser("%prog harbor") 13 | (options, args) = parser.parse_args() 14 | 15 | if len(args) < 1: 16 | parser.error("Not enough arguments") 17 | 18 | harbor, = args 19 | 20 | conn = MySQLdb.connect(host="localhost", 21 | user="root", 22 | passwd="", 23 | db="radio") 24 | 25 | # Look for a record 26 | cursor = conn.cursor() 27 | cursor.execute("""SELECT idname 28 | FROM dj_logins 29 | WHERE harbor = %s 30 | ORDER BY id DESC 31 | LIMIT 1""", (harbor)) 32 | row = cursor.fetchone() 33 | cursor.close() 34 | 35 | # No login 36 | if row == None: 37 | print "Unknown" 38 | sys.exit(0) 39 | 40 | print row[0] 41 | sys.exit(0) 42 | 43 | if __name__ == "__main__": 44 | main(); -------------------------------------------------------------------------------- /automation/getnext.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2005-2011 sk89q 4 | # 5 | 6 | import os 7 | import os.path 8 | import re 9 | import random 10 | import sys 11 | 12 | src_dir = '/home/radio/music/main/' 13 | 14 | # NOTE! This song selection algorithm MAY VIOLATE COPYRIGHT / LICENSING LAWS 15 | # WITHIN YOUR COUNTRY! 16 | 17 | pool = [] 18 | r = re.compile("\\.(?:mp3|ogg)$", re.I); 19 | for root, dirs, files in os.walk(src_dir): 20 | for file in files: 21 | if r.search(file): 22 | pool.append(os.path.join(root, file)) 23 | if '.__ignore__' in dirs: 24 | dirs.remove('.__ignore__') 25 | print random.choice(pool) -------------------------------------------------------------------------------- /automation/getpromo.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2005-2011 sk89q 4 | # 5 | 6 | import glob 7 | import random 8 | 9 | files = glob.glob("/home/radio/intros/DU_promo.mp3") 10 | print random.choice(files) -------------------------------------------------------------------------------- /automation/login.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2005-2011 sk89q 4 | # 5 | 6 | import sys 7 | from optparse import OptionParser 8 | import MySQLdb 9 | import time 10 | 11 | def main(): 12 | parser = OptionParser("%prog harbor login") 13 | (options, args) = parser.parse_args() 14 | 15 | if len(args) < 2: 16 | parser.error("Not enough arguments") 17 | 18 | harbor, login = args 19 | login = login.split("|", 1) 20 | if len(login) < 2: 21 | parser.error("Invalid login argument") 22 | username, password = login 23 | 24 | conn = MySQLdb.connect(host="localhost", 25 | user="root", 26 | passwd="", 27 | db="radio") 28 | 29 | # Look for a record 30 | cursor = conn.cursor() 31 | cursor.execute("""QUERY WENT HERE""", (username, password)) 32 | row = cursor.fetchone() 33 | cursor.close() 34 | 35 | # No login 36 | if row == None: 37 | print "Failed to authenticate" 38 | sys.exit(1) 39 | 40 | print "Authenticated as %s (%s)" % (row[1], row[0]) 41 | 42 | # Log login 43 | cursor = conn.cursor() 44 | cursor.execute("""INSERT INTO dj_logins 45 | (mid, idname, harbor, time) 46 | VALUES 47 | (%s, %s, %s, %s)""", 48 | (row[0], row[2], harbor, time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime()))) 49 | cursor.close() 50 | 51 | sys.exit(0) 52 | 53 | if __name__ == "__main__": 54 | main(); -------------------------------------------------------------------------------- /icecast/icecast.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 100 4 | 7 5 | 5 6 | 524288 7 | 30 8 | 15 9 | 10 10 | 1 11 | 65535 12 | 13 | 14 | 15 | CHANGEME 16 | CHANGEME 17 | CHANGEME 18 | CHANGEME! 19 | 20 | 21 | 31 | 32 | CHANGEME 33 | 34 | 35 | 36 | 8000 37 | 38 | 39 | 40 | 8001 41 | 42 | 1 43 | 44 | 45 | 1 46 | 47 | 48 | /main.aac 49 | 50 | 51 | /main-low.aac 52 | 53 | 54 | /main.mp3 55 | 56 | 57 | 58 | 59 | /home/radio/icecast 60 | 62 | /home/radio/icecast/logs 63 | /home/radio/icecast/web 64 | /home/radio/icecast/admin 65 | 66 | 67 | 68 | 69 | 70 | access.log 71 | error.log 72 | 73 | 2 74 | 10000 75 | 1 76 | 77 | 78 | 79 | 80 | 81 | radio 82 | radio 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /liquidsoap/radio.liq: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/liquidsoap 2 | # 3 | # Copyright (c) 2008-2011 sk89q 4 | # Available under GNU Lesser General Public License v3 or WTFPL 5 | # 6 | 7 | base_dir = "/home/radio/liquidsoap/" 8 | automation_dir = "/home/radio/automation/" 9 | source_pass = "CHANGEME" 10 | telnet_port = 10000 11 | 12 | # ---------------------------------------- 13 | # Configuration 14 | # ---------------------------------------- 15 | 16 | set("decoding.buffer_length", 20.) 17 | set("frame.channels", 2) 18 | set("frame.samplerate", 44100) 19 | set("harbor.icy", false) 20 | set("harbor.bind_addr", "0.0.0.0") 21 | set("harbor.port", 8004) 22 | set("init.daemon.pidfile.path", base_dir^"