예제 #1
0
	def is_request_needed(self):
		global _request_interval
		global _request_sequence
		if not self.sid in _request_interval:
			_request_interval[self.sid] = cache.get_station(self.sid, "request_interval")
			if not _request_interval[self.sid]:
				_request_interval[self.sid] = 0
		if not self.sid in _request_sequence:
			_request_sequence[self.sid] = cache.get_station(self.sid, "request_sequence")
			if not _request_sequence[self.sid]:
				_request_sequence[self.sid] = 0
				
		# If we're ready for a request sequence, start one
		return_value = None
		if _request_interval[self.sid] <= 0 and _request_sequence[self.sid] <= 0:
			line_length = db.c.fetch_var("SELECT COUNT(*) FROM r4_request_line WHERE sid = %s", (self.sid,))
			_request_sequence[self.sid] = 1 + math.floor(line_length / config.get_station(self.sid, "request_interval_scale"))
			_request_interval[self.sid] = config.get_station(self.sid, "request_interval_gap")
			return_value = True
		# If we are in a request sequence, do one
		elif _request_sequence[self.sid] > 0:
			return_value = True
		else:
			_request_interval[self.sid] -= 1
			return_value = False

		cache.set_station(self.sid, "request_interval", _request_interval[self.sid])
		cache.set_station(self.sid, "request_sequence", _request_sequence[self.sid])
		return return_value
예제 #2
0
	def start_cooldown(self, sid, cool_time = False):
		if sid == 0:
			return

		if cool_time:
			pass
		elif self.data['cool_override']:
			cool_time = self.data['cool_override']
		else:
			cool_rating = self.rating_precise
			if not cool_rating or cool_rating == 0:
				cool_rating = 3
			# AlbumCD = minAlbumCD + ((maxAlbumR - albumR)/(maxAlbumR - minAlbumR)*(maxAlbumCD - minAlbumCD))
			# old: auto_cool = cooldown.cooldown_config[sid]['min_album_cool'] + (((4 - (cool_rating - 1)) / 4.0) * (cooldown.cooldown_config[sid]['max_album_cool'] - cooldown.cooldown_config[sid]['min_album_cool']))
			auto_cool = cooldown.cooldown_config[sid]['min_album_cool'] + (((5 - cool_rating) / 4.0) * (cooldown.cooldown_config[sid]['max_album_cool'] - cooldown.cooldown_config[sid]['min_album_cool']))
			album_song_count = self.get_num_songs(sid)
			log.debug("cooldown", "min_album_cool: %s .. max_album_cool: %s .. auto_cool: %s .. album_song_count: %s .. rating: %s" % (cooldown.cooldown_config[sid]['min_album_cool'], cooldown.cooldown_config[sid]['max_album_cool'], auto_cool, album_song_count, cool_rating))
			cool_size_multiplier = config.get_station(sid, "cooldown_size_min_multiplier") + (config.get_station(sid, "cooldown_size_max_multiplier") - config.get_station(sid, "cooldown_size_min_multiplier")) / (1 + math.pow(2.7183, (config.get_station(sid, "cooldown_size_slope") * (album_song_count - config.get_station(sid, "cooldown_size_slope_start")))) / 2)
			cool_age_multiplier = cooldown.get_age_cooldown_multiplier(self.data['added_on'])
			cool_time = int(auto_cool * cool_size_multiplier * cool_age_multiplier * self.data['cool_multiply'])
			log.debug("cooldown", "auto_cool: %s .. cool_size_multiplier: %s .. cool_age_multiplier: %s .. cool_multiply: %s .. cool_time: %s" %
					  (auto_cool, cool_size_multiplier, cool_age_multiplier, self.data['cool_multiply'], cool_time))
		updated_album_ids[sid][self.id] = True
		log.debug("cooldown", "Album ID %s Station ID %s cool_time period: %s" % (self.id, sid, cool_time))
		return self._start_cooldown_db(sid, cool_time)
예제 #3
0
def prepare_cooldown_algorithm(sid):
	"""
	Prepares pre-calculated variables that relate to calculating cooldown.
	Should pull all variables fresh from the DB, for algorithm
	refer to jfinalfunk.
	"""
	global cooldown_config
	
	if not sid in cooldown_config:
		cooldown_config[sid] = { "time": 0 }
	if cooldown_config[sid]['time'] > (time.time() - 3600):
		return
	
	# Variable names from here on down are from jf's proposal at: http://rainwave.cc/forums/viewtopic.php?f=13&t=1267
	sum_aasl = db.c.fetch_var("SELECT SUM(aasl) FROM (SELECT AVG(song_length) AS aasl FROM r4_album_sid JOIN r4_song_album USING (album_id) JOIN r4_songs USING (song_id) WHERE r4_album_sid.sid = %s AND r4_songs.song_verified = TRUE GROUP BY r4_album_sid.album_id) AS jfiscrazy", (sid,))
	if not sum_aasl:
		sum_aasl = 100
	# print "sumAASL: %s" % sum_aasl
	avg_album_rating = db.c.fetch_var("SELECT AVG(album_rating) FROM r4_album_sid JOIN r4_albums USING (album_id) WHERE r4_album_sid.sid = %s AND r4_album_sid.album_exists = TRUE", (sid,)) 
	if not avg_album_rating:
		avg_album_rating = 3.5
	# print "avg_album_rating: %s" % avg_album_rating
	multiplier_adjustment = db.c.fetch_var("SELECT SUM(tempvar) FROM (SELECT r4_album_sid.album_id, AVG(album_cool_multiply) * AVG(song_length) AS tempvar FROM r4_album_sid JOIN r4_song_album USING (album_id) JOIN r4_songs USING (song_id) WHERE r4_album_sid.sid = %s AND r4_songs.song_verified = TRUE GROUP BY r4_album_sid.album_id) AS hooooboy", (sid,))
	if not multiplier_adjustment:
		multiplier_adjustment = 1
	# print "multi: %s" % multiplier_adjustment
	base_album_cool = float(config.get_station(sid, "cooldown_percentage")) * float(sum_aasl) / float(multiplier_adjustment)
	# print "base_album_cool: %s" % base_album_cool
	base_rating = db.c.fetch_var("SELECT SUM(tempvar) FROM (SELECT r4_album_sid.album_id, AVG(album_rating) * AVG(song_length) AS tempvar FROM r4_albums JOIN r4_album_sid ON (r4_albums.album_id = r4_album_sid.album_id AND r4_album_sid.sid = %s) JOIN r4_song_album ON (r4_albums.album_id = r4_song_album.album_id) JOIN r4_songs USING (song_id) WHERE r4_songs.song_verified = TRUE GROUP BY r4_album_sid.album_id) AS hooooboy", (sid,))
	if not base_rating:
		base_rating = 4
	# print "base rating: %s" % base_rating
	min_album_cool = config.get_station(sid, "cooldown_highest_rating_multiplier") * base_album_cool
	# print "min_album_cool: %s" % min_album_cool
	max_album_cool = min_album_cool + ((5 - 2.5) * ((base_album_cool - min_album_cool) / (5 - base_rating)))
	# print "max_album_cool: %s" % max_album_cool
	
	cooldown_config[sid]['sum_aasl'] = sum_aasl
	cooldown_config[sid]['avg_album_rating'] = avg_album_rating
	cooldown_config[sid]['multiplier_adjustment'] = multiplier_adjustment
	cooldown_config[sid]['base_album_cool'] = base_album_cool
	cooldown_config[sid]['base_rating'] = base_rating
	cooldown_config[sid]['min_album_cool'] = min_album_cool
	cooldown_config[sid]['max_album_cool'] = max_album_cool
	cooldown_config[sid]['time'] = time.time()
	
	average_song_length = db.c.fetch_var("SELECT AVG(song_length) FROM r4_songs JOIN r4_song_sid USING (song_id) WHERE song_exists = TRUE AND sid = %s", (sid,))
	# print "average_song_length: %s" % average_song_length
	if not average_song_length:
		average_song_length = 160
	number_songs = db.c.fetch_var("SELECT COUNT(song_id) FROM r4_song_sid WHERE song_exists = TRUE AND sid = %s", (sid,))
	if not number_songs:
		number_songs = 1
	# print "number_songs: %s" % number_songs
	cooldown_config[sid]['max_song_cool'] = float(average_song_length) * (number_songs * config.get_station(sid, "cooldown_song_max_multiplier"))
	cooldown_config[sid]['min_song_cool'] = cooldown_config[sid]['max_song_cool'] * config.get_station(sid, "cooldown_song_min_multiplier")
예제 #4
0
파일: info.py 프로젝트: Abchrisabc/rainwave
def attach_dj_info_to_request(request):
	request.append("dj_info", {
		"pause_requested": cache.get_station(request.sid, "backend_paused"),
		"pause_active": cache.get_station(request.sid, "backend_paused_playing"),
		"pause_title": cache.get_station(request.sid, "pause_title"),
		"dj_password": cache.get_station(request.sid, "dj_password"),
		"mount_host": config.get_station(request.sid, "liquidsoap_harbor_host"),
		"mount_port": config.get_station(request.sid, "liquidsoap_harbor_port"),
		"mount_url": config.get_station(request.sid, "liquidsoap_harbor_mount")
	})
예제 #5
0
def _get_socket(sid):
	client = None
	if hasattr(socket,"AF_UNIX") and config.has_station(sid, "liquidsoap_socket_path") and os.path.exists(config.get_station(sid, "liquidsoap_socket_path")):
		client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
		client.connect(config.get_station(sid, "liquidsoap_socket_path"))
	elif config.has_station(sid, "liquidsoap_telnet_host"):
		client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    	client.settimeout(2)
    	client.connect((config.get_station(sid, "liquidsoap_telnet_host"), config.get_station(sid, "liquidsoap_telnet_port")))
	return client
예제 #6
0
파일: event.py 프로젝트: Reani/rainwave
	def reset_request_sequence(self):
		if _request_interval[self.sid] <= 0 and _request_sequence[self.sid] <= 0:
			line_length = db.c.fetch_var("SELECT COUNT(*) FROM r4_request_line WHERE sid = %s", (self.sid,))
			log.debug("requests", "Ready for sequence, line length %s" % line_length)
			# This sequence variable gets set AFTER a request has already been marked as fulfilled
			# If we have a +1 to this math we'll actually get 2 requests in a row, one now (is_request_needed will return true)
			# and then again when sequence_length will go from 1 to 0.
			_request_sequence[self.sid] = int(math.floor(line_length / config.get_station(self.sid, "request_sequence_scale")))
			_request_interval[self.sid] = config.get_station(self.sid, "request_interval")
			log.debug("requests", "Sequence length: %s" % _request_sequence[self.sid])
예제 #7
0
	def start_cooldown(self, sid, cool_time = False):
		global cooldown_config

		if cool_time:
			pass
		elif self.cool_override:
			self._start_cooldown_db(sid, self.cool_override)
		else:
			auto_cool = cooldown_config[sid]['min_album_cool'] + ((self.data['rating'] - 2.5) * (cooldown_config[sid]['max_album_cool'] - cooldown_config[sid]['min_album_cool']))
			album_num_songs = db.c.fetch_var("SELECT COUNT(r4_song_album.song_id) FROM r4_song_album JOIN r4_song_sid USING (song_id) WHERE r4_song_album.album_id = %s AND r4_song_sid.song_exists = TRUE AND r4_song_sid.sid = %s", (self.id, sid))
			cool_size_multiplier = config.get_station(sid, "cooldown_size_min_multiplier") + (config.get_station(sid, "cooldown_size_max_multiplier") - config.get_station(sid, "cooldown_size_min_multiplier")) / (1 + math.pow(2.7183, (config.get_station(sid, "cooldown_size_slope") * (album_num_songs - config.get_station(sid, "cooldown_size_slope_start")))) / 2);
			cool_time = auto_cool * cool_size_multiplier * get_age_cooldown_multiplier(self.data['added_on']) * self.cool_multiply
		updated_album_ids[sid][self.id] = True
		return self._start_cooldown_db(sid, cool_time)
예제 #8
0
	def reset_request_sequence(self):
		if _request_interval[self.sid] <= 0 and _request_sequence[self.sid] <= 0:
			line_length = cache.get_station(self.sid, 'request_valid_positions')
			if not line_length:
				for entry in (cache.get_station(self.sid, "request_line") or []):
					if entry['song_id']:
						line_length += 1
				log.debug("requests", "Ready for sequence, entries in request line with valid songs: %s" % line_length)
			else:
				log.debug("requests", "Ready for sequence, valid positions: %s" % line_length)
			# This sequence variable gets set AFTER a request has already been marked as fulfilled
			# If we have a +1 to this math we'll actually get 2 requests in a row, one now (is_request_needed will return true)
			# and then again when sequence_length will go from 1 to 0.
			_request_sequence[self.sid] = int(math.floor(line_length / config.get_station(self.sid, "request_sequence_scale")))
			_request_interval[self.sid] = config.get_station(self.sid, "request_interval")
			log.debug("requests", "Sequence length: %s" % _request_sequence[self.sid])
예제 #9
0
	def get(self):
		self.mobile = self.request.headers.get("User-Agent").lower().find("mobile") != -1 or self.request.headers.get("User-Agent").lower().find("android") != -1
		info.attach_info_to_request(self, extra_list=self.get_cookie("r4_active_list"))
		self.append("api_info", { "time": int(time.time()) })
		self.render(self.page_template, request=self,
					site_description=self.locale.translate("station_description_id_%s" % self.sid),
					revision_number=config.build_number,
					jsfiles=self.jsfiles,
					api_url=config.get("api_external_url_prefix"),
					cookie_domain=config.get("cookie_domain"),
					locales=api.locale.locale_names_json,
					relays=config.public_relays_json[self.sid],
					stream_filename=config.get_station(self.sid, "stream_filename"),
					station_list=config.station_list_json,
					apple_home_screen_icon=config.get_station(self.sid, "apple_home_screen_icon"),
					mobile=self.mobile)
예제 #10
0
def start_icecast_sync():
	global all_returned
	
	stream_names = {}
	for sid in config.station_ids:
		stream_names[sid] = config.get_station(sid)['stream_filename']
	
	if all_returned:
		log.warn("icecast_sync", "Previous operation did not finish!")

	all_returned = {}
	listener_ids = {}
	for relay, relay_info in config.get("relays").iteritems():
		listener_ids[relay] = []
		relay_base_url = "%s%s:%s/admin/listclients?mount=/" % (relay_info['protocol'], relay_info['ip_address'], relay_info['port'])
		for sid in relay_info['sids']:
			# Commented out since the beta version of the site doesn't do MP3
			#all_returned["%s_%s_mp3" % (relay, sid)] = False
			#handler = IcecastSyncCallback(relay, relay_info, "%s_%s_mp3" % (relay, sid), sid)
			#http_client = tornado.httpclient.AsyncHTTPClient()
			#http_client.fetch(relay_base_url + stream_names[sid] + ".mp3",
			#				  handler.respond,
			#				  auth_username=relay_info['admin_username'],
			#				  auth_password=relay_info['admin_password'])

			all_returned["%s_%s_ogg" % (relay, sid)] = False
			handler2 = IcecastSyncCallback(relay, relay_info, "%s_%s_ogg" % (relay, sid), sid)
			http_client2 = tornado.httpclient.AsyncHTTPClient()
			http_client2.fetch(relay_base_url + stream_names[sid] + ".ogg",
							  handler2.respond,
							  auth_username=relay_info['admin_username'],
							  auth_password=relay_info['admin_password'])
예제 #11
0
	def _start_cooldown_db(self, sid, cool_time):
		if config.has_station(sid, "cooldown_enable_for_categories") and not config.get_station(sid, "cooldown_enable_for_categories"):
			return

		cool_end = int(cool_time + timestamp())
		log.debug("cooldown", "Group ID %s Station ID %s cool_time period: %s" % (self.id, sid, cool_time))
		# Make sure to update both the if and else SQL statements if doing any updates
		if db.c.allows_join_on_update:
			db.c.update("UPDATE r4_song_sid SET song_cool = TRUE, song_cool_end = %s "
						"FROM r4_song_group "
						"WHERE r4_song_sid.song_id = r4_song_group.song_id AND r4_song_group.group_id = %s "
							"AND r4_song_sid.sid = %s AND r4_song_sid.song_exists = TRUE AND r4_song_sid.song_cool_end <= %s ",
						(cool_end, self.id, sid, cool_end))
			request_only_end = cool_end + 300
			db.c.update("UPDATE r4_song_sid SET song_request_only = TRUE, song_request_only_end = %s "
						"FROM r4_song_group "
						"WHERE r4_song_sid.song_id = r4_song_group.song_id AND r4_song_group.group_id = %s "
							"AND r4_song_sid.sid = %s AND r4_song_sid.song_exists = TRUE AND r4_song_sid.song_cool_end <= %s "
							"AND song_request_only_end IS NOT NULL",
						(request_only_end, self.id, sid, cool_end))
		else:
			song_ids = db.c.fetch_list(
				"SELECT song_id "
				"FROM r4_song_group JOIN r4_song_sid USING (song_id) "
				"WHERE r4_song_group.group_id = %s AND r4_song_sid.sid = %s AND r4_song_sid.song_exists = TRUE AND r4_song_sid.song_cool_end < %s",
				(self.id, sid, timestamp() - cool_time))
			for song_id in song_ids:
				db.c.update("UPDATE r4_song_sid SET song_cool = TRUE, song_cool_end = %s WHERE song_id = %s AND sid = %s", (cool_end, song_id, sid))
예제 #12
0
파일: album.py 프로젝트: rmcauley/rainwave
 def _start_cooldown_db(self, sid, cool_time):
     cool_end = int(cool_time + timestamp())
     if db.c.allows_join_on_update:
         db.c.update(
             "UPDATE r4_song_sid "
             "SET song_cool = TRUE, song_cool_end = %s "
             "FROM r4_songs "
             "WHERE r4_song_sid.song_id = r4_songs.song_id AND album_id = %s AND sid = %s AND song_cool_end <= %s ",
             (cool_end, self.id, sid, cool_end),
         )
         request_only_end = cool_end + config.get_station(sid, "cooldown_request_only_period")
         db.c.update(
             "UPDATE r4_song_sid "
             "SET song_request_only = TRUE, song_request_only_end = %s "
             "FROM r4_songs "
             "WHERE r4_song_sid.song_id = r4_songs.song_id AND album_id = %s AND sid = %s AND song_cool_end <= %s "
             "AND song_request_only_end IS NOT NULL",
             (request_only_end, self.id, sid, cool_end),
         )
     else:
         songs = db.c.fetch_list(
             "SELECT song_id FROM r4_song_sid JOIN r4_songs USING (song_id) WHERE album_id = %s AND sid = %s AND song_exists = TRUE AND song_cool_end < %s",
             (self.id, sid, cool_end),
         )
         for song_id in songs:
             db.c.update(
                 "UPDATE r4_song_sid SET song_cool = TRUE, song_cool_end = %s WHERE song_id = %s AND song_cool_end < %s AND sid = %s",
                 (cool_end, song_id, cool_end, sid),
             )
예제 #13
0
	def _get_annotated(self, e):
		string = "annotate:crossfade=\""
		if e.use_crossfade:
			string += "1"
		else:
			string += "0"
		string += "\","

		string += "use_suffix=\""
		if e.use_tag_suffix:
			string += "1"
		else:
			string += "0"
		string += "\""

		if hasattr(e, 'songs'):
			string += ",suffix=\"%s\"" % config.get_station(self.sid, "stream_suffix")
		elif e.name:
			string += ",title=\"%s\"" % e.name

		if hasattr(e, "replay_gain") and e.replay_gain:
			string += ",replay_gain=\"%s\"" % e.replay_gain

		string += ":" + e.get_filename()
		return string
예제 #14
0
def _start(callback):
	global in_process
	if in_process:
		log.warn("icecast_sync", "Previous operation did not finish!")

	stream_names = {}
	for sid in config.station_ids:
		stream_names[sid] = config.get_station(sid, 'stream_filename')

	for relay, relay_info in config.get("relays").iteritems():
		relay_base_url = "%s%s:%s/admin/listclients?mount=/" % (relay_info['protocol'], relay_info['ip_address'], relay_info['port'])
		for sid in relay_info['sids']:
			for ftype in ('.mp3', '.ogg'):
				try:
					handler = IcecastSyncCallback(relay, relay_info, ftype, sid, callback)
					in_process[handler] = False
					http_client = tornado.httpclient.HTTPClient()
					http_client.fetch(relay_base_url + stream_names[sid] + ftype,
										auth_username=relay_info['admin_username'],
										auth_password=relay_info['admin_password'],
										callback=handler.process)
				except Exception as e:
					log.exception("icecast_sync", "Could not sync %s %s.%s" % (relay, stream_names[sid], ftype), e)

	callback()
예제 #15
0
def get_random_song_timed(sid, target_seconds = None, target_delta = None):
	"""
	Fetch a random song abiding by all election block, request block, and
	availability rules, but giving priority to the target song length
	provided.  Falls back to get_random_song on failure.
	"""
	if not target_seconds:
		return get_random_song(sid)
	if not target_delta:
		target_delta = config.get_station(sid, "song_lookup_length_delta")

	sql_query = ("FROM r4_song_sid "
					"JOIN r4_songs USING (song_id) "
					"JOIN r4_album_sid ON (r4_album_sid.album_id = r4_songs.album_id AND r4_album_sid.sid = r4_song_sid.sid) "
				"WHERE r4_song_sid.sid = %s "
					"AND song_exists = TRUE "
					"AND song_cool = FALSE "
					"AND song_elec_blocked = FALSE "
					"AND album_requests_pending IS NULL "
					"AND song_request_only = FALSE "
					"AND song_length >= %s AND song_length <= %s")
	lower_target_bound = target_seconds - (target_delta / 2)
	upper_target_bound = target_seconds + (target_delta / 2)
	num_available = db.c.fetch_var("SELECT COUNT(r4_song_sid.song_id) " + sql_query, (sid, lower_target_bound, upper_target_bound))
	log.info("song_select", "Song pool size (cooldown, blocks, requests, timed) [target %s delta %s]: %s" % (target_seconds, target_delta, num_available))
	if num_available == 0:
		log.warn("song_select", "No songs available with target_seconds %s and target_delta %s." % (target_seconds, target_delta))
		log.debug("song_select", "Song select query: SELECT COUNT(r4_song_sid.song_id) " + sql_query % (sid, lower_target_bound, upper_target_bound))
		return get_random_song(sid)
	else:
		offset = random.randint(1, num_available) - 1
		song_id = db.c.fetch_var("SELECT r4_song_sid.song_id " + sql_query + " LIMIT 1 OFFSET %s", (sid, lower_target_bound, upper_target_bound, offset))
		return Song.load_from_id(song_id, sid)
예제 #16
0
def start_icecast_sync():
	global all_returned
	global listener_ids
	global blargh
	
	stream_names = {}
	for sid in config.station_ids:
		stream_names[sid] = config.get_station(sid, 'stream_filename')
	
	if all_returned:
		log.warn("icecast_sync", "Previous operation did not finish!")

	all_returned = {}
	listener_ids = {}
	for relay, relay_info in config.get("relays").iteritems():
		listener_ids[relay] = []
		relay_base_url = "%s%s:%s/admin/listclients?mount=/" % (relay_info['protocol'], relay_info['ip_address'], relay_info['port'])
		for sid in relay_info['sids']:
			all_returned["%s_%s_mp3" % (relay, sid)] = False
			handler = IcecastSyncCallback(relay, relay_info, "%s_%s_mp3" % (relay, sid), sid)
			http_client = tornado.httpclient.HTTPClient()
			http_client.fetch(relay_base_url + stream_names[sid] + ".mp3",
				                         auth_username=relay_info['admin_username'],
										 auth_password=relay_info['admin_password'],
			                             callback=handler.respond)

			all_returned["%s_%s_ogg" % (relay, sid)] = False
			handler2 = IcecastSyncCallback(relay, relay_info, "%s_%s_ogg" % (relay, sid), sid)
			http_client2 = tornado.httpclient.HTTPClient()
			http_client2.fetch(relay_base_url + stream_names[sid] + ".ogg",
				                         auth_username=relay_info['admin_username'],
										 auth_password=relay_info['admin_password'],
			                             callback=handler2.respond)
	_process()
예제 #17
0
파일: tune_in.py 프로젝트: keabard/rainwave
def get_stream_filename(sid, filetype = "mp3", user = None):
	filename = config.get_station(sid, "stream_filename")

	if user is None or user.is_anonymous():
		return "%s.%s" % (filename, filetype)
	else:
		return "%s.%s?%s:%s" % (filename, filetype, user.id, user.data['listen_key'])
예제 #18
0
파일: event.py 프로젝트: Reani/rainwave
	def __init__(self, sid = None):
		super(Election, self).__init__()
		self._num_requests = 1
		if sid:
			self._num_songs = config.get_station(sid, "songs_in_election")
		else:
			self._num_songs = 3
예제 #19
0
	def post(self):
		station_list = []
		for station_id in config.station_ids:
			station_list.append({
				"id": station_id,
				"name": config.station_id_friendly[station_id],
				"description": self.locale.translate("station_description_id_%s" % station_id),
				"stream": "http://%s:%s/%s" % (config.get_station(station_id, "round_robin_relay_host"), config.get_station(station_id, "round_robin_relay_port"), api_requests.tune_in.get_stream_filename(station_id, user=self.user)),
			})
		self.append(self.return_name, station_list)
예제 #20
0
파일: event.py 프로젝트: Reani/rainwave
	def add_song(self, song):
		if not song:
			return False
		entry_id = db.c.get_next_id("r4_election_entries", "entry_id")
		song.data['entry_id'] = entry_id
		song.data['entry_position'] = len(self.songs)
		if not 'entry_type' in song.data:
			song.data['entry_type'] = ElecSongTypes.normal
		db.c.update("INSERT INTO r4_election_entries (entry_id, song_id, elec_id, entry_position, entry_type) VALUES (%s, %s, %s, %s, %s)", (entry_id, song.id, self.id, len(self.songs), song.data['entry_type']))
		song.start_election_block(self.sid, config.get_station(self.sid, "num_planned_elections") + 1)
		self.songs.append(song)
		return True
예제 #21
0
파일: index.py 프로젝트: Sicno/rainwave
	def get(self):
		info.attach_info_to_request(self, extra_list=self.get_cookie("r4_active_list"))
		self.append("api_info", { "time": int(time.time()) })
		self.render("r4_index.html", request=self,
					site_description=self.locale.translate("station_description_id_%s" % self.sid),
					revision_number=config.build_number,
					jsfiles=self.jsfiles,
					api_url=config.get("api_external_url_prefix"),
					cookie_domain=config.get("cookie_domain"),
					locales=api.locale.locale_names_json,
					relays=config.public_relays_json[self.sid],
					stream_filename=config.get_station(self.sid, "stream_filename"),
					station_list=config.station_list_json)
예제 #22
0
def _send_command(sid, cmd):
	cmd += "\n"
	socket_path = config.get_station(sid, "liquidsoap_socket_path")
	if os.path.exists(socket_path):
		client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
		client.connect(socket_path)
		client.send(cmd)
		to_ret = client.recv(1024)
		client.close()
		to_ret = to_ret.strip().strip("END").strip()
		return to_ret
	else:
		raise APIException("internal_error", "Could not connect to Liquidsoap. (station %s)" % sid)
예제 #23
0
파일: schedule.py 프로젝트: Reani/rainwave
def set_next_start_times(sid):
	"""
	Calibrate the start points of each scheduled event until we reach the number of future elections planned.
	This has not been fully tested and will likely require some tweaking to be done in the future.
	"""
	if len(next[sid]) == 0 or config.get_station(sid, "num_planned_elections") == 0:
		return
	i = 1
	next[sid][0].start_predicted = current[sid].start_actual + current[sid].length()
	while (i < len(next[sid])):
		if not next[sid][i].start_predicted or ((next[sid][i].start_predicted - next[sid][i - 1].start_predicted) <= 30) or next[sid][i].is_election:
			next[sid][i].start_predicted = next[sid][i - 1].start_predicted + next[sid][i - 1].length()
			i += 1
		else:
			break
예제 #24
0
	def post(self):
		info.attach_info_to_request(self, live_voting=True)
		self.append("build_version", config.build_number)
		self.append("locale", self.locale.code)
		self.append("locales", api.locale.locale_names)
		self.append("cookie_domain", config.get("cookie_domain"))
		self.append("on_init", [])
		self.append("on_measure", [])
		self.append("on_draw", [])
		self.append("websocket_host", config.get("websocket_host"))
		self.append("stream_filename", config.get_station(self.sid, "stream_filename"))
		self.append("station_list", config.station_list)
		self.append("relays", config.public_relays[self.sid])
		if self.is_mobile:
			self.append("mobile", True)
		else:
			self.append("mobile", False)
예제 #25
0
파일: index.py 프로젝트: Dinir/rainwave
 def get(self):
     self.mobile = self.request.headers.get("User-Agent").lower().find(
         "mobile") != -1 or self.request.headers.get(
             "User-Agent").lower().find("android") != -1
     info.attach_info_to_request(
         self, extra_list=self.get_cookie("r4_active_list"))
     self.append("api_info", {"time": int(time.time())})
     self.render(self.page_template,
                 request=self,
                 site_description=self.locale.translate(
                     "station_description_id_%s" % self.sid),
                 revision_number=config.build_number,
                 jsfiles=self.jsfiles,
                 api_url=config.get("api_external_url_prefix"),
                 cookie_domain=config.get("cookie_domain"),
                 locales=api.locale.locale_names_json,
                 relays=config.public_relays_json[self.sid],
                 stream_filename=config.get_station(self.sid,
                                                    "stream_filename"),
                 station_list=config.station_list_json,
                 mobile=self.mobile)
예제 #26
0
 def add_song(self, song):
     if not song:
         return False
     entry_id = db.c.get_next_id("r4_election_entries", "entry_id")
     song.data['entry_id'] = entry_id
     song.data['entry_position'] = len(self.songs)
     if not 'entry_type' in song.data:
         song.data['entry_type'] = ElecSongTypes.normal
     if not 'entry_votes' in song.data:
         song.data['entry_votes'] = 0
     db.c.update(
         "INSERT INTO r4_election_entries (entry_id, song_id, elec_id, entry_position, entry_type, entry_votes) VALUES (%s, %s, %s, %s, %s, %s)",
         (entry_id, song.id, self.id, len(self.songs),
          song.data['entry_type'], song.data['entry_votes']))
     song.start_election_block(
         self.sid,
         config.get_station(self.sid, "num_planned_elections") + 1)
     self.songs.append(song)
     if song.data['entry_type'] == ElecSongTypes.request:
         request.update_line(self.sid)
     return True
예제 #27
0
파일: server.py 프로젝트: Reani/rainwave
	def _get_annotated(self, e):
		string = "annotate:crossfade=\""
		if e.use_crossfade:
			string += "1"
		else:
			string += "0"
		string += "\","

		string += "use_suffix=\""
		if e.use_tag_suffix:
			string += "1"
		else:
			string += "0"
		string += "\""

		string += ",suffix=\"%s\"" % config.get_station(self.sid, "stream_suffix")

		if e.name:
			string += ",title=\"%s\"" % event.name

		string += ":" + e.get_filename()
		return string
예제 #28
0
파일: song.py 프로젝트: khakionion/rainwave
	def start_cooldown(self, sid):
		"""
		Calculates cooldown based on jfinalfunk's crazy algorithms.
		Cooldown may be overriden by song_cool_* rules found in database.
		Cooldown is only applied if the song exists on the given station
		"""

		if (self.sid != sid) or (not self.sid in self.data['sids']):
			return

		for metadata in self.groups:
			log.debug("song_cooldown", "Starting group cooldown on group %s" % metadata.id)
			metadata.start_cooldown(sid)
		# Albums always have to go last since album records in the DB store cached cooldown values
		for metadata in self.albums:
			log.debug("song_cooldown", "Starting album cooldown on album %s" % metadata.id)
			metadata.start_cooldown(sid)

		cool_time = cooldown.cooldown_config[sid]['max_song_cool']
		if self.data['cool_override']:
			cool_time = self.data['cool_override']
		else:
			cool_rating = self.data['rating']
			# If no rating exists, give it a middle rating
			if not self.data['rating'] or self.data['rating'] == 0:
				cool_rating = cooldown.cooldown_config[sid]['base_rating']
			auto_cool = cooldown.cooldown_config[sid]['min_song_cool'] + (((4 - (cool_rating - 1)) / 4.0) * (cooldown.cooldown_config[sid]['max_song_cool'] - cooldown.cooldown_config[sid]['min_song_cool']))
			cool_time = auto_cool * cooldown.get_age_cooldown_multiplier(self.data['added_on']) * self.data['cool_multiply']

		log.debug("cooldown", "Song ID %s Station ID %s cool_time period: %s" % (self.id, sid, cool_time))
		cool_time = int(cool_time + time.time())
		db.c.update("UPDATE r4_song_sid SET song_cool = TRUE, song_cool_end = %s WHERE song_id = %s AND sid = %s AND song_cool_end < %s", (cool_time, self.id, sid, cool_time))
		self.data['cool'] = True
		self.data['cool_end'] = cool_time

		if 'request_only_end' in self.data and self.data['request_only_end'] != None:
			self.data['request_only_end'] = self.data['cool_end'] + config.get_station(sid, "cooldown_request_only_period")
			self.data['request_only'] = True
			db.c.update("UPDATE r4_song_sid SET song_request_only = TRUE, song_request_only_end = %s WHERE song_id = %s AND sid = %s", (self.data['request_only_end'], self.id, sid))
예제 #29
0
파일: song.py 프로젝트: Siqo53/rainwave
	def start_cooldown(self, sid):
		"""
		Calculates cooldown based on jfinalfunk's crazy algorithms.
		Cooldown may be overriden by song_cool_* rules found in database.
		Cooldown is only applied if the song exists on the given station
		"""

		if (self.sid != sid) or (not self.sid in self.data['sids']) or sid == 0:
			return

		for metadata in self.groups:
			log.debug("song_cooldown", "Starting group cooldown on group %s" % metadata.id)
			metadata.start_cooldown(sid)
		# Albums always have to go last since album records in the DB store cached cooldown values
		for metadata in self.albums:
			log.debug("song_cooldown", "Starting album cooldown on album %s" % metadata.id)
			metadata.start_cooldown(sid)

		cool_time = cooldown.cooldown_config[sid]['max_song_cool']
		if self.data['cool_override']:
			cool_time = self.data['cool_override']
		else:
			cool_rating = self.data['rating']
			# If no rating exists, give it a middle rating
			if not self.data['rating'] or self.data['rating'] == 0:
				cool_rating = cooldown.cooldown_config[sid]['base_rating']
			auto_cool = cooldown.cooldown_config[sid]['min_song_cool'] + (((4 - (cool_rating - 1)) / 4.0) * (cooldown.cooldown_config[sid]['max_song_cool'] - cooldown.cooldown_config[sid]['min_song_cool']))
			cool_time = auto_cool * cooldown.get_age_cooldown_multiplier(self.data['added_on']) * self.data['cool_multiply']

		log.debug("cooldown", "Song ID %s Station ID %s cool_time period: %s" % (self.id, sid, cool_time))
		cool_time = int(cool_time + timestamp())
		db.c.update("UPDATE r4_song_sid SET song_cool = TRUE, song_cool_end = %s WHERE song_id = %s AND sid = %s AND song_cool_end < %s", (cool_time, self.id, sid, cool_time))
		self.data['cool'] = True
		self.data['cool_end'] = cool_time

		if 'request_only_end' in self.data and self.data['request_only_end'] != None:
			self.data['request_only_end'] = self.data['cool_end'] + config.get_station(sid, "cooldown_request_only_period")
			self.data['request_only'] = True
			db.c.update("UPDATE r4_song_sid SET song_request_only = TRUE, song_request_only_end = %s WHERE song_id = %s AND sid = %s AND song_request_only_end IS NOT NULL", (self.data['request_only_end'], self.id, sid))
예제 #30
0
def start_icecast_sync():
    global all_returned
    global listener_ids
    global blargh

    stream_names = {}
    for sid in config.station_ids:
        stream_names[sid] = config.get_station(sid, 'stream_filename')

    if all_returned:
        log.warn("icecast_sync", "Previous operation did not finish!")

    all_returned = {}
    listener_ids = {}
    for relay, relay_info in config.get("relays").iteritems():
        listener_ids[relay] = []
        relay_base_url = "%s%s:%s/admin/listclients?mount=/" % (
            relay_info['protocol'], relay_info['ip_address'],
            relay_info['port'])
        for sid in relay_info['sids']:
            all_returned["%s_%s_mp3" % (relay, sid)] = False
            handler = IcecastSyncCallback(relay, relay_info,
                                          "%s_%s_mp3" % (relay, sid), sid)
            http_client = tornado.httpclient.HTTPClient()
            http_client.fetch(relay_base_url + stream_names[sid] + ".mp3",
                              auth_username=relay_info['admin_username'],
                              auth_password=relay_info['admin_password'],
                              callback=handler.respond)

            all_returned["%s_%s_ogg" % (relay, sid)] = False
            handler2 = IcecastSyncCallback(relay, relay_info,
                                           "%s_%s_ogg" % (relay, sid), sid)
            http_client2 = tornado.httpclient.HTTPClient()
            http_client2.fetch(relay_base_url + stream_names[sid] + ".ogg",
                               auth_username=relay_info['admin_username'],
                               auth_password=relay_info['admin_password'],
                               callback=handler2.respond)
    _process()
예제 #31
0
    def _get_annotated(self, e):
        string = "annotate:crossfade=\""
        if e.use_crossfade:
            string += "1"
        else:
            string += "0"
        string += "\","

        string += "use_suffix=\""
        if e.use_tag_suffix:
            string += "1"
        else:
            string += "0"
        string += "\""

        string += ",suffix=\"%s\"" % config.get_station(
            self.sid, "stream_suffix")

        if e.name:
            string += ",title=\"%s\"" % event.name

        string += ":" + e.get_filename()
        return string
예제 #32
0
def _start(callback):
    global in_process
    if in_process:
        log.warn("icecast_sync", "Previous operation did not finish!")

    stream_names = {}
    for sid in config.station_ids:
        stream_names[sid] = config.get_station(sid, "stream_filename")

    for relay, relay_info in config.get("relays").items():
        relay_base_url = "%s%s:%s/admin/listclients?mount=/" % (
            relay_info["protocol"],
            relay_info["ip_address"],
            relay_info["port"],
        )
        for sid in relay_info["sids"]:
            for ftype in (".mp3", ".ogg"):
                try:
                    handler = IcecastSyncCallback(relay, relay_info, ftype,
                                                  sid, callback)
                    in_process[handler] = False
                    http_client = tornado.httpclient.HTTPClient()
                    http_client.fetch(
                        relay_base_url + stream_names[sid] + ftype,
                        auth_username=relay_info["admin_username"],
                        auth_password=relay_info["admin_password"],
                        callback=handler.process,
                    )
                except Exception as e:
                    log.exception(
                        "icecast_sync",
                        "Could not sync %s %s.%s" %
                        (relay, stream_names[sid], ftype),
                        e,
                    )

    callback()
예제 #33
0
파일: songgroup.py 프로젝트: nv043/rainwave
    def _start_cooldown_db(self, sid, cool_time):
        if config.has_station(
                sid,
                "cooldown_enable_for_categories") and not config.get_station(
                    sid, "cooldown_enable_for_categories"):
            return

        cool_end = int(cool_time + timestamp())
        log.debug(
            "cooldown", "Group ID %s Station ID %s cool_time period: %s" %
            (self.id, sid, cool_time))
        # Make sure to update both the if and else SQL statements if doing any updates
        if db.c.allows_join_on_update:
            db.c.update(
                "UPDATE r4_song_sid SET song_cool = TRUE, song_cool_end = %s "
                "FROM r4_song_group "
                "WHERE r4_song_sid.song_id = r4_song_group.song_id AND r4_song_group.group_id = %s "
                "AND r4_song_sid.sid = %s AND r4_song_sid.song_exists = TRUE AND r4_song_sid.song_cool_end <= %s ",
                (cool_end, self.id, sid, cool_end))
            request_only_end = cool_end + 300
            db.c.update(
                "UPDATE r4_song_sid SET song_request_only = TRUE, song_request_only_end = %s "
                "FROM r4_song_group "
                "WHERE r4_song_sid.song_id = r4_song_group.song_id AND r4_song_group.group_id = %s "
                "AND r4_song_sid.sid = %s AND r4_song_sid.song_exists = TRUE AND r4_song_sid.song_cool_end <= %s "
                "AND song_request_only_end IS NOT NULL",
                (request_only_end, self.id, sid, cool_end))
        else:
            song_ids = db.c.fetch_list(
                "SELECT song_id "
                "FROM r4_song_group JOIN r4_song_sid USING (song_id) "
                "WHERE r4_song_group.group_id = %s AND r4_song_sid.sid = %s AND r4_song_sid.song_exists = TRUE AND r4_song_sid.song_cool_end < %s",
                (self.id, sid, timestamp() - cool_time))
            for song_id in song_ids:
                db.c.update(
                    "UPDATE r4_song_sid SET song_cool = TRUE, song_cool_end = %s WHERE song_id = %s AND sid = %s",
                    (cool_end, song_id, sid))
예제 #34
0
 def __init__(self, sid):
     super(ElectionProducer, self).__init__(sid)
     self.plan_ahead_limit = config.get_station(sid,
                                                "num_planned_elections")
     self.elec_type = "Election"
     self.elec_class = Election
예제 #35
0
	def __init__(self, sid):
		super(ElectionProducer, self).__init__(sid)
		self.plan_ahead_limit = config.get_station(sid, "num_planned_elections")
		self.elec_type = "Election"
		self.elec_class = Election
예제 #36
0
	def post(self):
		info.attach_info_to_request(self, live_voting=True)
		self.append("stream_filename", config.get_station(self.sid, "stream_filename"))
		self.append("station_list", config.station_list)
		self.append("relays", config.public_relays[self.sid])
예제 #37
0
    def start_cooldown(self, sid, cool_time=False):
        if sid == 0:
            return

        if cool_time:
            pass
        elif self.data["cool_override"]:
            cool_time = self.data["cool_override"]
        else:
            cool_rating = self.rating_precise
            if not cool_rating or cool_rating == 0:
                cool_rating = 3
            # AlbumCD = minAlbumCD + ((maxAlbumR - albumR)/(maxAlbumR - minAlbumR)*(maxAlbumCD - minAlbumCD))
            # old: auto_cool = cooldown.cooldown_config[sid]['min_album_cool'] + (((4 - (cool_rating - 1)) / 4.0) * (cooldown.cooldown_config[sid]['max_album_cool'] - cooldown.cooldown_config[sid]['min_album_cool']))
            auto_cool = cooldown.cooldown_config[sid]["min_album_cool"] + (
                ((5 - cool_rating) / 4.0)
                * (
                    cooldown.cooldown_config[sid]["max_album_cool"]
                    - cooldown.cooldown_config[sid]["min_album_cool"]
                )
            )
            album_song_count = self.get_num_songs(sid)
            log.debug(
                "cooldown",
                "min_album_cool: %s .. max_album_cool: %s .. auto_cool: %s .. album_song_count: %s .. rating: %s"
                % (
                    cooldown.cooldown_config[sid]["min_album_cool"],
                    cooldown.cooldown_config[sid]["max_album_cool"],
                    auto_cool,
                    album_song_count,
                    cool_rating,
                ),
            )
            cool_size_multiplier = config.get_station(
                sid, "cooldown_size_min_multiplier"
            ) + (
                config.get_station(sid, "cooldown_size_max_multiplier")
                - config.get_station(sid, "cooldown_size_min_multiplier")
            ) / (
                1
                + math.pow(
                    2.7183,
                    (
                        config.get_station(sid, "cooldown_size_slope")
                        * (
                            album_song_count
                            - config.get_station(sid, "cooldown_size_slope_start")
                        )
                    ),
                )
                / 2
            )
            cool_age_multiplier = cooldown.get_age_cooldown_multiplier(
                self.data["added_on"]
            )
            cool_time = int(
                auto_cool
                * cool_size_multiplier
                * cool_age_multiplier
                * self.data["cool_multiply"]
            )
            log.debug(
                "cooldown",
                "auto_cool: %s .. cool_size_multiplier: %s .. cool_age_multiplier: %s .. cool_multiply: %s .. cool_time: %s"
                % (
                    auto_cool,
                    cool_size_multiplier,
                    cool_age_multiplier,
                    self.data["cool_multiply"],
                    cool_time,
                ),
            )
        updated_album_ids[sid][self.id] = True
        log.debug(
            "cooldown",
            "Album ID %s Station ID %s cool_time period: %s"
            % (self.id, sid, cool_time),
        )
        self._start_cooldown_db(sid, cool_time)
예제 #38
0
파일: tune_in.py 프로젝트: keabard/rainwave
def get_round_robin_url(sid, filetype = "mp3", user = None):
	return "http://%s:%s/%s" % (config.get_station(sid, "round_robin_relay_host"), config.get_station(sid, "round_robin_relay_port"), get_stream_filename(sid, filetype, user))
예제 #39
0
	def prepare(self):
		self._startclock = time.time()
		self.user = None

		if self.local_only and not self.request.remote_ip in config.get("api_trusted_ip_addresses"):
			log.info("api", "Rejected %s request from %s" % (self.url, self.request.remote_ip))
			self.set_status(403)
			self.finish()

		if not isinstance(self.locale, locale.RainwaveLocale):
			self.locale = self.get_browser_locale()

		if not self.return_name:
			self.return_name = self.url[self.url.rfind("/")+1:] + "_result"
		else:
			self.return_name = self.return_name

		if self.admin_required or self.dj_required:
			self.login_required = True

		if 'in_order' in self.request.arguments:
			self._output = []
			self._output_array = True
		else:
			self._output = {}
			self._output_array = False

		self.sid = fieldtypes.integer(self.get_cookie("r4_sid", "1"))
		if "sid" in self.request.arguments:
			self.sid = int(self.get_argument("sid"))
		elif not self.sid:
			for possible_sid in config.station_ids:
				if self.request.host == config.get_station(possible_sid, "host"):
					self.sid = possible_sid
					break
		if not self.sid and self.sid_required:
			raise APIException("missing_station_id", http_code=400)
		if self.sid and not self.sid in config.station_ids:
			raise APIException("invalid_station_id", http_code=400)
		self.set_cookie("r4_sid", str(self.sid), expires_days=365, domain=config.get("cookie_domain"))

		for field, field_attribs in self.__class__.fields.iteritems():
			type_cast, required = field_attribs
			if required and field not in self.request.arguments:
				raise APIException("missing_argument", argument=field, http_code=400)
			elif not required and field not in self.request.arguments:
				self.cleaned_args[field] = None
			else:
				parsed = type_cast(self.get_argument(field), self)
				if parsed == None and required != None:
					raise APIException("invalid_argument", argument=field, reason=getattr(fieldtypes, "%s_error" % type_cast.__name__), http_code=400)
				else:
					self.cleaned_args[field] = parsed

		if self.phpbb_auth:
			self.do_phpbb_auth()
		else:
			self.rainwave_auth()

		if self.auth_required and not self.user:
			raise APIException("auth_required", http_code=403)

		if self.login_required and (not self.user or self.user.is_anonymous()):
			raise APIException("login_required", http_code=403)
		if self.tunein_required and (not self.user or not self.user.is_tunedin()):
			raise APIException("tunein_required", http_code=403)
		if self.admin_required and (not self.user or not self.user.is_admin()):
			raise APIException("admin_required", http_code=403)
		if self.dj_required and (not self.user or not self.user.is_dj()):
			raise APIException("dj_required", http_code=403)
		if self.perks_required and (not self.user or not self.user.has_perks()):
			raise APIException("perks_required", http_code=403)

		if self.unlocked_listener_only and not self.user:
			raise APIException("auth_required", http_code=403)
		elif self.unlocked_listener_only and self.user.data['listener_lock'] and self.user.data['listener_lock_sid'] != self.sid:
			raise APIException("unlocked_only", station=config.station_id_friendly[self.user.data['listener_lock_sid']], lock_counter=self.user.data['listener_lock_counter'], http_code=403)
예제 #40
0
def skip(sid):
	return _send_command(sid, "%s(dot)mp3.skip" % config.get_station(sid, "stream_filename"))
예제 #41
0
파일: index.py 프로젝트: Siqo53/rainwave
 def post(self):
     info.attach_info_to_request(self, extra_list=self.get_cookie("r4_active_list"))
     self.append("stream_filename", config.get_station(self.sid, "stream_filename"))
     self.append("station_list", config.station_list)
     self.append("relays", config.public_relays[self.sid])
예제 #42
0
 def start_event(self):
     super(OneUp, self).start_event()
     self.songs[0].start_election_block(
         self.sid,
         config.get_station(self.sid, "num_planned_elections") + 1)
예제 #43
0
def prepare_cooldown_algorithm(sid):
    """
	Prepares pre-calculated variables that relate to calculating cooldown.
	Should pull all variables fresh from the DB, for algorithm
	refer to jfinalfunk.
	"""
    global cooldown_config

    if not sid in cooldown_config:
        cooldown_config[sid] = {"time": 0}
    if cooldown_config[sid]['time'] > (timestamp() - 3600):
        return

    # Variable names from here on down are from jf's proposal at: http://rainwave.cc/forums/viewtopic.php?f=13&t=1267
    sum_aasl = db.c.fetch_var(
        "SELECT SUM(aasl) FROM ("
        "SELECT AVG(song_length) AS aasl "
        "FROM r4_album_sid "
        "JOIN r4_songs USING (album_id) "
        "JOIN r4_song_sid USING (song_id) "
        "WHERE r4_album_sid.sid = %s AND r4_songs.song_verified = TRUE "
        "GROUP BY r4_album_sid.album_id) AS jfiscrazy", (sid, ))
    if not sum_aasl:
        sum_aasl = 100000
    log.debug("cooldown", "SID %s: sumAASL: %s" % (sid, sum_aasl))
    avg_album_rating = db.c.fetch_var(
        "SELECT AVG(album_rating) FROM r4_album_sid WHERE r4_album_sid.sid = %s AND r4_album_sid.album_exists = TRUE",
        (sid, ))
    if not avg_album_rating:
        avg_album_rating = 3.5
    avg_album_rating = min(max(1, avg_album_rating), 5)
    log.debug("cooldown",
              "SID %s: avg_album_rating: %s" % (sid, avg_album_rating))
    multiplier_adjustment = db.c.fetch_var(
        "SELECT SUM(tempvar) FROM (SELECT r4_album_sid.album_id, AVG(album_cool_multiply) * AVG(song_length) AS tempvar FROM r4_album_sid JOIN r4_songs USING (album_id) JOIN r4_song_sid USING (song_id) WHERE r4_album_sid.sid = %s AND r4_songs.song_verified = TRUE GROUP BY r4_album_sid.album_id) AS hooooboy",
        (sid, ))
    if not multiplier_adjustment:
        multiplier_adjustment = 1
    multiplier_adjustment = multiplier_adjustment / float(sum_aasl)
    multiplier_adjustment = min(max(0.5, multiplier_adjustment), 4)
    log.debug("cooldown", "SID %s: multi: %s" % (sid, multiplier_adjustment))
    base_album_cool = float(config.get_station(sid, "cooldown_percentage")
                            ) * float(sum_aasl) / float(multiplier_adjustment)
    base_album_cool = max(min(base_album_cool, 1000000), 1)
    log.debug("cooldown",
              "SID %s: base_album_cool: %s" % (sid, base_album_cool))
    base_rating = db.c.fetch_var(
        "SELECT SUM(tempvar) FROM ("
        "SELECT r4_album_sid.album_id, AVG(album_rating) * AVG(song_length) AS tempvar "
        "FROM r4_album_sid "
        "JOIN r4_songs USING (album_id) "
        "JOIN r4_song_sid USING (song_id) "
        "WHERE r4_album_sid.sid = %s AND r4_songs.song_verified = TRUE "
        "GROUP BY r4_album_sid.album_id"
        ") AS hooooboy", (sid, ))
    if not base_rating:
        base_rating = 4
    base_rating = min(max(1, float(base_rating) / float(sum_aasl)), 5)
    log.debug("cooldown", "SID %s: base rating: %s" % (sid, base_rating))
    min_album_cool = config.get_station(
        sid, "cooldown_highest_rating_multiplier") * base_album_cool
    log.debug("cooldown", "SID %s: min_album_cool: %s" % (sid, min_album_cool))
    max_album_cool = min_album_cool + ((5 - 2.5) *
                                       ((base_album_cool - min_album_cool) /
                                        (5 - base_rating)))
    log.debug("cooldown", "SID %s: max_album_cool: %s" % (sid, max_album_cool))

    cooldown_config[sid]['sum_aasl'] = int(sum_aasl)
    cooldown_config[sid]['avg_album_rating'] = float(avg_album_rating)
    cooldown_config[sid]['multiplier_adjustment'] = float(
        multiplier_adjustment)
    cooldown_config[sid]['base_album_cool'] = int(base_album_cool)
    cooldown_config[sid]['base_rating'] = float(base_rating)
    cooldown_config[sid]['min_album_cool'] = int(min_album_cool)
    cooldown_config[sid]['max_album_cool'] = int(max_album_cool)
    cooldown_config[sid]['time'] = int(timestamp())

    average_song_length = db.c.fetch_var(
        "SELECT AVG(song_length) FROM r4_songs JOIN r4_song_sid USING (song_id) WHERE song_exists = TRUE AND sid = %s",
        (sid, ))
    log.debug("cooldown",
              "SID %s: average_song_length: %s" % (sid, average_song_length))
    cooldown_config[sid]['average_song_length'] = float(average_song_length)
    if not average_song_length:
        average_song_length = 160
    number_songs = db.c.fetch_var(
        "SELECT COUNT(song_id) FROM r4_song_sid WHERE song_exists = TRUE AND sid = %s",
        (sid, ))
    if not number_songs:
        number_songs = 1
    log.debug("cooldown", "SID %s: number_songs: %s" % (sid, number_songs))
    cooldown_config[sid]['max_song_cool'] = float(average_song_length) * (
        number_songs * config.get_station(sid, "cooldown_song_max_multiplier"))
    cooldown_config[sid]['min_song_cool'] = cooldown_config[
        sid]['max_song_cool'] * config.get_station(
            sid, "cooldown_song_min_multiplier")
예제 #44
0
def get_round_robin_url(sid, filetype = "mp3", user = None):
	return "http://%s:8000/%s" % (config.get_station(sid, "round_robin_relay_host"), get_stream_filename(sid, filetype, user))
예제 #45
0
def skip(sid):
    return _send_command(
        sid, "%s(dot)mp3.skip" % config.get_station(sid, "stream_filename"))
예제 #46
0
파일: schedule.py 프로젝트: Reani/rainwave
def _create_elections(sid):
    # Step, er, 0: Update the request cache first, so elections have the most recent data to work with
    # (the entire requests module depends on its caches)
    request.update_cache(sid)

    max_sched_id, max_elec_id, num_elections = _get_schedule_stats(sid)
    log.debug(
        "create_elec",
        "Max sched ID: %s // Max elec ID: %s // Num elections already existing: %s // Size of next: %s"
        % (max_sched_id, max_elec_id, num_elections, len(next[sid])))

    # Step 2: Load up any elections that have been added while we've been idle and append them to the list
    unused_elec_id = db.c.fetch_list(
        "SELECT elec_id FROM r4_elections WHERE sid = %s AND elec_id > %s AND elec_used = FALSE AND elec_priority = FALSE ORDER BY elec_id",
        (sid, max_elec_id))
    unused_elecs = []
    for elec_id in unused_elec_id:
        unused_elecs.append(event.Election.load_by_id(elec_id))

    # Step 3: Insert elections where there's time and adjust predicted start times as necessary, if num_elections < 2 then create them where necessary
    i = 1
    running_time = current[sid].start_actual + current[sid].length()
    if len(next[sid]) > 0:
        next[sid][0].start = running_time
    while i < len(next[sid]):
        next_start = next[sid][i].start
        gap = next_start - running_time
        next_elec_i = None
        next_elec_length = playlist.get_average_song_length(sid)
        j = i
        while j < len(next[sid]):
            if next[sid][j].is_election:
                next_elec = j
                next_elec_length = next[sid][j].length()
                break
        if not next_elec_i and len(unused_elecs) > 0:
            next_elec_length = unused_elecs[0].length()

        # TODO: This algorithm DEFINITELY needs code/concept review
        # There are potential holes - it is not as comprehensive a scheduler as the previous
        # Rainwave scheduler, however it is vastly simplified.
        # One drawback is that you cannot schedule elections themselves to run at certain times.

        create_elecs = False
        # If the event we're looking at collides with the previous event, adjust this event to start later
        if gap <= 0:
            next[sid][i].start = running_time
            running_time += next[sid][i].length()
        # If we have no elections current in the next list and there's enough time to fit a song, stuff an election in
        # (this automatically takes into account unused elections, based on next_elec_length definition above)
        elif not next_elec_i and gap <= (next_elec_length * 1.4):
            next_elec = None
            # If we have an existing unused election, we can use that (as next_elec_length is already based on the first unused elec, this can happen)
            if len(unused_elecs) > 0:
                next_elec = unused_elecs.pop(0)
            # If not, create a new election timed to the gap (next_elec_length will be the average song length*1.4, so this will happen frequently)
            else:
                next_elec = _create_election(sid, running_time, gap)
            num_elections += 1
            next_elec.start = running_time
            running_time += next_elec.length()
            next[sid].insert(i, next_elec)
        # If it's more accurate to squeeze a created election in here than adjust the next event, move the event
        # *OR* the next event is too far out and we have elections in hand
        elif next_elec_i and ((gap <= (next_elec_length / 2)) or
                              (gap > (next_elec_length * 1.5))):
            next_elec = next[sid].pop(next_elec_i)
            next_elec.start = running_time
            running_time += next_elec.length()
            next[sid].insert(i, next_elec)
        # The next event is better off aligned
        else:
            next[sid][i].start = running_time
            running_time += next[sid][i].length()
        i += 1

    needed_elecs = config.get_station(sid,
                                      "num_planned_elections") - num_elections
    log.debug(
        "create_elec",
        "Before: Needed elecs: %s // Unused elecs: %s // Current num elections: %s // Next size: %s"
        % (needed_elecs, len(unused_elecs), num_elections, len(next[sid])))
    # Step 5: If we're at less than X elections available, create them (or use unused ones) and append them
    # No timing is required here, since we're simply outright appending to the end
    # (any elections appearing before a scheduled item would be handled by the block above)
    failures = 0
    while needed_elecs > 0 and failures <= 2:
        next_elec = None
        if len(unused_elecs) > 0:
            next_elec = unused_elecs.pop(0)
        else:
            next_elec = _create_election(sid, running_time)
        next_elec_length = next_elec.length()
        if next_elec_length > 0:
            next_elec.start = running_time
            running_time += next_elec.length()
            next[sid].append(next_elec)
            num_elections += 1
            needed_elecs -= 1
        else:
            log.error("create_elec",
                      "Election ID %s was faulty - zero length.  Deleting.")
            next_elec.delete()
            failures += 1
    if failures >= 2:
        log.error("create_elec", "Total failure when creating elections.")
    log.debug(
        "create_elec",
        "After: Unused elecs: %s // Current num elections: %s // Next size: %s"
        % (len(unused_elecs), num_elections, len(next[sid])))
예제 #47
0
async def _start():
    loop = asyncio.get_running_loop()

    stream_names = {}
    for sid in config.station_ids:
        stream_names[sid] = config.get_station(sid, "stream_filename")

    calls = []
    requests = []
    clients = []
    for relay, relay_info in config.get("relays").items():
        client = aiohttp.ClientSession(
            loop=loop,
            timeout=aiohttp.ClientTimeout(total=5),
            auth=aiohttp.BasicAuth(
                login=relay_info["admin_username"],
                password=relay_info["admin_password"],
            ))
        clients.append(client)
        relay_base_url = "%s%s:%s/admin/listclients?mount=/" % (
            relay_info["protocol"],
            relay_info["ip_address"],
            relay_info["port"],
        )
        for sid in relay_info["sids"]:
            for ftype in (".mp3", ".ogg"):
                call = IcecastSyncCall(relay, relay_info, ftype, sid)
                calls.append(call)
                requests.append(
                    call.request(
                        client=client,
                        url=relay_base_url + stream_names[sid] + ftype,
                    ))

    try:
        await asyncio.gather(*requests)
    finally:
        for client in clients:
            await client.close()

    log.debug("icecast_sync", "All responses came back for counting.")

    try:
        stations = {}
        for sid in config.station_ids:
            stations[sid] = 0

        relays = {}
        for relay, _relay_info in config.get("relays").items():
            relays[relay] = 0

        for call in calls:
            listeners = call.get_listeners()
            stations[call.sid] += len(listeners)
            relays[call.relay_name] += len(listeners)

        for sid, listener_count in stations.items():
            log.debug(
                "icecast_sync",
                "%s has %s listeners." %
                (config.station_id_friendly[sid], listener_count),
            )
            db.c.update(
                "INSERT INTO r4_listener_counts (sid, lc_guests) VALUES (%s, %s)",
                (sid, listener_count),
            )

        for relay, count in relays.items():
            log.debug("icecast_sync",
                      "%s total listeners: %s" % (relay, count))

        cache.set_global("relay_status", relays)

        # db.c.update("DELETE FROM r4_listener_counts WHERE lc_time <= %s", (current_time - config.get("trim_history_length"),))
    except Exception as e:
        log.exception("icecast_sync", "Could not finish counting listeners.",
                      e)
예제 #48
0
def post_process(sid):
    try:
        db.c.start_transaction()
        start_time = timestamp()
        playlist.prepare_cooldown_algorithm(sid)
        rainwave.playlist_objects.album.clear_updated_albums(sid)
        log.debug("post", "Playlist prepare time: %.6f" % (timestamp() - start_time,))

        start_time = timestamp()
        current[sid].finish()
        for sched_id in db.c.fetch_list(
            "SELECT sched_id FROM r4_schedule WHERE sched_end < %s AND sched_used = FALSE",
            (timestamp(),),
        ):
            t_evt = events.event.BaseProducer.load_producer_by_id(sched_id)
            t_evt.finish()
        log.debug("post", "Current finish time: %.6f" % (timestamp() - start_time,))

        start_time = timestamp()
        last_song = current[sid].get_song()
        if last_song:
            db.c.update(
                "INSERT INTO r4_song_history (sid, song_id) VALUES (%s, %s)",
                (sid, last_song.id),
            )
        log.debug("post", "Last song insertion time: %s" % (timestamp() - start_time,))

        start_time = timestamp()
        history[sid].insert(0, current[sid])
        while len(history[sid]) > 5:
            history[sid].pop()
        log.debug("post", "History management: %.6f" % (timestamp() - start_time,))

        start_time = timestamp()
        current[sid] = upnext[sid].pop(0)
        current[sid].start_event()
        log.debug("advance", "Current management: %.6f" % (timestamp() - start_time,))

        start_time = timestamp()
        playlist.warm_cooled_songs(sid)
        playlist.warm_cooled_albums(sid)
        log.debug("advance", "Cooldown warming: %.6f" % (timestamp() - start_time,))

        start_time = timestamp()
        _trim(sid)
        user.trim_listeners(sid)
        cache.update_user_rating_acl(sid, history[sid][0].get_song().id)
        user.unlock_listeners(sid)
        db.c.update(
            "UPDATE r4_listeners SET listener_voted_entry = NULL WHERE sid = %s", (sid,)
        )
        log.debug(
            "advance",
            "User management and trimming: %.6f" % (timestamp() - start_time,),
        )

        start_time = timestamp()
        # reduce song blocks has to come first, otherwise it wll reduce blocks generated by _create_elections
        playlist.reduce_song_blocks(sid)
        # update_cache updates both the line and expiry times
        # this is expensive and must be done before and after every request is filled
        # DO THIS AFTER EVERYTHING ELSE, RIGHT BEFORE NEXT MANAGEMENT, OR PEOPLE'S REQUESTS SLIP THROUGH THE CRACKS
        request.update_line(sid)
        # add to the event list / update start times for events
        manage_next(sid)
        # update expire times AFTER manage_next, so people who aren't in line anymore don't see expiry times
        request.update_expire_times()
        log.debug(
            "advance",
            "Request and upnext management: %.6f" % (timestamp() - start_time,),
        )

        update_memcache(sid)

        sync_to_front.sync_frontend_all(sid)
        db.c.commit()
    except:
        db.c.rollback()
        raise

    if (
        current[sid]
        and config.has_station(sid, "tunein_partner_key")
        and config.get_station(sid, "tunein_partner_key")
    ):
        ti_song = current[sid].get_song()
        if ti_song:
            ti_title = ti_song.data["title"]
            ti_album = ti_song.albums[0].data["name"]
            ti_artist = ", ".join([a.data["name"] for a in ti_song.artists])

            params = {
                "id": config.get_station(sid, "tunein_id"),
                "title": ti_title,
                "artist": ti_artist,
                "album": ti_album,
            }

            try:
                req = requests.Request(
                    "GET", "http://air.radiotime.com/Playing.ashx", params=params
                )
                p = req.prepare()
                # Must be done here rather than in params because of odd strings TuneIn creates
                p.url += "&partnerId=%s" % config.get_station(sid, "tunein_partner_id")
                p.url += "&partnerKey=%s" % config.get_station(
                    sid, "tunein_partner_key"
                )
                s = requests.Session()
                resp = s.send(p, timeout=3)
                log.debug(
                    "advance", "TuneIn updated (%s): %s" % (resp.status_code, resp.text)
                )
            except Exception as e:
                log.exception("advance", "Could not update TuneIn.", e)