Package deefuzzer :: Module station
[hide private]
[frames] | no frames]

Source Code for Module deefuzzer.station

  1  #!/usr/bin/python 
  2  # -*- coding: utf-8 -*- 
  3  # 
  4  # Copyright (C) 2006-2011 Guillaume Pellerin 
  5   
  6  # <yomguy@parisson.com> 
  7   
  8  # This software is a computer program whose purpose is to stream audio 
  9  # and video data through icecast2 servers. 
 10   
 11  # This software is governed by the CeCILL license under French law and 
 12  # abiding by the rules of distribution of free software. You can use, 
 13  # modify and/ or redistribute the software under the terms of the CeCILL 
 14  # license as circulated by CEA, CNRS and INRIA at the following URL 
 15  # "http://www.cecill.info". 
 16   
 17  # As a counterpart to the access to the source code and  rights to copy, 
 18  # modify and redistribute granted by the license, users are provided only 
 19  # with a limited warranty and the software's author, the holder of the 
 20  # economic rights, and the successive licensors have only limited 
 21  # liability. 
 22   
 23  # In this respect, the user's attention is drawn to the risks associated 
 24  # with loading, using,  modifying and/or developing or reproducing the 
 25  # software by the user in light of its specific status of free software, 
 26  # that may mean that it is complicated to manipulate, and that also 
 27  # therefore means that it is reserved for developers and  experienced 
 28  # professionals having in-depth computer knowledge. Users are therefore 
 29  # encouraged to load and test the software's suitability as regards their 
 30  # requirements in conditions enabling the security of their systems and/or 
 31  # data to be ensured and, more generally, to use and operate it in the 
 32  # same conditions as regards security. 
 33   
 34  # The fact that you are presently reading this means that you have had 
 35  # knowledge of the CeCILL license and that you accept its terms. 
 36   
 37  # Author: Guillaume Pellerin <yomguy@parisson.com> 
 38   
 39  import os 
 40  import sys 
 41  import time 
 42  import datetime 
 43  import string 
 44  import random 
 45  import shout 
 46  import urllib 
 47  import mimetypes 
 48  import json 
 49   
 50  from threading import Thread 
 51  from player import * 
 52  from recorder import * 
 53  from relay import * 
 54  from streamer import * 
 55  from tools import * 
 56   
 57   
58 -class Station(Thread):
59 """a DeeFuzzer shouting station thread""" 60 61 id = 0 62 valid = False 63 counter = 0 64 delay = 0 65 start_time = time.time() 66 server_ping = False 67 playlist = [] 68 media_source = None 69 lp = 1 70 player_mode = 1 71 osc_control_mode = 0 72 twitter_mode = 0 73 jingles_mode = 0 74 relay_mode = 0 75 record_mode = 0 76 run_mode = 1 77 appendtype = 0 78 feeds_json = 0 79 feeds_rss = 1 80 feeds_mode = 1 81 feeds_playlist = 1 82 feeds_showfilepath = 0 83 feeds_showfilename = 0 84 short_name = '' 85 channelIsOpen = False 86 starting_id = -1 87 jingles_frequency = 2 88 statusfile = '' 89 base_directory = '' 90
91 - def __init__(self, station, q, logqueue, m3u):
92 Thread.__init__(self) 93 self.station = station 94 self.q = q 95 self.logqueue = logqueue 96 self.m3u = m3u 97 98 self.current_media_obj = MediaBase() 99 100 if 'station_statusfile' in self.station: 101 self.statusfile = station['station_statusfile'] 102 try: 103 if os.path.exists(self.statusfile): 104 f = open(self.statusfile, 'r') 105 self.starting_id = int(f.read()) 106 f.close() 107 except: 108 pass 109 110 if 'base_dir' in self.station: 111 self.base_directory = self.station['base_dir'].strip() 112 113 # Media 114 if 'm3u' in self.station['media']: 115 if not self.station['media']['m3u'].strip() == '': 116 self.media_source = self._path_add_base(self.station['media']['m3u']) 117 118 if 'dir' in self.station['media']: 119 if not self.station['media']['dir'].strip() == '': 120 self.media_source = self._path_add_base(self.station['media']['dir']) 121 122 if 'source' in self.station['media']: 123 if not self.station['media']['source'].strip() == '': 124 self.media_source = self._path_add_base(self.station['media']['source']) 125 126 self.media_format = self.station['media']['format'] 127 self.shuffle_mode = int(self.station['media']['shuffle']) 128 self.bitrate = int(self.station['media']['bitrate']) 129 self.ogg_quality = int(self.station['media']['ogg_quality']) 130 self.samplerate = int(self.station['media']['samplerate']) 131 self.voices = int(self.station['media']['voices']) 132 133 # Server 134 if 'mountpoint' in self.station['server']: 135 self.mountpoint = self.station['server']['mountpoint'] 136 elif 'short_name' in self.station['infos']: 137 self.mountpoint = self.station['infos']['short_name'] 138 else: 139 self.mountpoint = 'default' 140 141 self.short_name = self.mountpoint 142 143 if 'appendtype' in self.station['server']: 144 self.appendtype = int(self.station['server']['appendtype']) 145 146 if 'type' in self.station['server']: 147 self.type = self.station['server']['type'] # 'icecast' | 'stream-m' 148 else: 149 self.type = 'icecast' 150 151 if 'stream-m' in self.type: 152 self.channel = HTTPStreamer() 153 self.channel.mount = '/publish/' + self.mountpoint 154 elif 'icecast' in self.type: 155 self.channel = shout.Shout() 156 self.channel.mount = '/' + self.mountpoint 157 if self.appendtype: 158 self.channel.mount = self.channel.mount + '.' + self.media_format 159 else: 160 self._err('Not a compatible server type. Choose "stream-m" or "icecast".') 161 return 162 163 self.channel.url = self.station['infos']['url'] 164 self.channel.name = self.station['infos']['name'] 165 self.channel.genre = self.station['infos']['genre'] 166 self.channel.description = self.station['infos']['description'] 167 self.channel.format = self.media_format 168 self.channel.host = self.station['server']['host'] 169 self.channel.port = int(self.station['server']['port']) 170 self.channel.user = 'source' 171 self.channel.password = self.station['server']['sourcepassword'] 172 self.channel.public = int(self.station['server']['public']) 173 if self.channel.format == 'mp3': 174 self.channel.audio_info = {'bitrate': str(self.bitrate), 175 'samplerate': str(self.samplerate), 176 'channels': str(self.voices), } 177 else: 178 self.channel.audio_info = {'bitrate': str(self.bitrate), 179 'samplerate': str(self.samplerate), 180 'quality': str(self.ogg_quality), 181 'channels': str(self.voices), } 182 183 self.server_url = 'http://' + self.channel.host + ':' + str(self.channel.port) 184 self.channel_url = self.server_url + self.channel.mount 185 186 # RSS 187 if 'feeds' in self.station: 188 self.station['rss'] = self.station['feeds'] 189 190 if 'rss' in self.station: 191 if 'mode' in self.station['rss']: 192 self.feeds_mode = int(self.station['rss']['mode']) 193 self.feeds_dir = self._path_add_base(self.station['rss']['dir']) 194 self.feeds_enclosure = int(self.station['rss']['enclosure']) 195 if 'json' in self.station['rss']: 196 self.feeds_json = int(self.station['rss']['json']) 197 if 'rss' in self.station['rss']: 198 self.feeds_rss = int(self.station['rss']['rss']) 199 if 'playlist' in self.station['rss']: 200 self.feeds_playlist = int(self.station['rss']['playlist']) 201 if 'showfilename' in self.station['rss']: 202 self.feeds_showfilename = int(self.station['rss']['showfilename']) 203 if 'showfilepath' in self.station['rss']: 204 self.feeds_showfilepath = int(self.station['rss']['showfilepath']) 205 206 self.feeds_media_url = self.channel.url + '/media/' 207 if 'media_url' in self.station['rss']: 208 if not self.station['rss']['media_url'] == '': 209 self.feeds_media_url = self.station['rss']['media_url'] 210 211 self.base_name = self.feeds_dir + os.sep + self.short_name + '_' + self.channel.format 212 self.feeds_current_file = self.base_name + '_current' 213 self.feeds_playlist_file = self.base_name + '_playlist' 214 215 # Logging 216 self._info('Opening ' + self.short_name + ' - ' + self.channel.name) 217 218 self.metadata_relative_dir = 'metadata' 219 self.metadata_url = self.channel.url + '/rss/' + self.metadata_relative_dir 220 self.metadata_dir = self.feeds_dir + os.sep + self.metadata_relative_dir 221 if not os.path.exists(self.metadata_dir): 222 os.makedirs(self.metadata_dir) 223 224 # The station's player 225 self.player = Player(self.type) 226 227 # OSCing 228 # mode = 0 means Off, mode = 1 means On 229 if 'control' in self.station: 230 self.osc_control_mode = int(self.station['control']['mode']) 231 if self.osc_control_mode: 232 self.osc_port = int(self.station['control']['port']) 233 self.osc_controller = OSCController(self.osc_port) 234 # OSC paths and callbacks 235 self.osc_controller.add_method('/media/next', 'i', self.media_next_callback) 236 self.osc_controller.add_method('/media/relay', 'i', self.relay_callback) 237 self.osc_controller.add_method('/twitter', 'i', self.twitter_callback) 238 self.osc_controller.add_method('/jingles', 'i', self.jingles_callback) 239 self.osc_controller.add_method('/record', 'i', self.record_callback) 240 self.osc_controller.add_method('/player', 'i', self.player_callback) 241 self.osc_controller.add_method('/run', 'i', self.run_callback) 242 self.osc_controller.start() 243 244 # Jingling between each media. 245 if 'jingles' in self.station: 246 if 'mode' in self.station['jingles']: 247 self.jingles_mode = int(self.station['jingles']['mode']) 248 if 'shuffle' in self.station['jingles']: 249 self.jingles_shuffle = int(self.station['jingles']['shuffle']) 250 if 'frequency' in self.station['jingles']: 251 self.jingles_frequency = int(self.station['jingles']['frequency']) 252 if 'dir' in self.station['jingles']: 253 self.jingles_dir = self._path_add_base(self.station['jingles']['dir']) 254 if self.jingles_mode == 1: 255 self.jingles_callback('/jingles', [1]) 256 257 # Relaying 258 if 'relay' in self.station: 259 self.relay_mode = int(self.station['relay']['mode']) 260 self.relay_url = self.station['relay']['url'] 261 self.relay_author = self.station['relay']['author'] 262 if self.relay_mode == 1: 263 self.relay_callback('/media/relay', [1]) 264 265 # Twitting 266 if 'twitter' in self.station: 267 self.twitter_mode = int(self.station['twitter']['mode']) 268 self.twitter_key = self.station['twitter']['key'] 269 self.twitter_secret = self.station['twitter']['secret'] 270 self.twitter_tags = self.station['twitter']['tags'].split(' ') 271 try: 272 self.twitter_messages = self.station['twitter']['message'] 273 if isinstance(self.twitter_messages, dict): 274 self.twitter_messages = list(self.twitter_messages) 275 except: 276 pass 277 278 if self.twitter_mode: 279 self.twitter_callback('/twitter', [1]) 280 281 # Recording 282 if 'record' in self.station: 283 self.record_mode = int(self.station['record']['mode']) 284 self.record_dir = self._path_add_base(self.station['record']['dir']) 285 if self.record_mode: 286 self.record_callback('/record', [1]) 287 288 self.valid = True
289
290 - def _path_add_base(self, a):
291 return os.path.join(self.base_directory, a)
292
293 - def _path_m3u_rel(self, a):
294 return os.path.join(os.path.dirname(self.source), a)
295
296 - def _log(self, level, msg):
297 try: 298 obj = {'msg': 'Station ' + str(self.channel_url) + ': ' + str(msg), 'level': str(level)} 299 self.logqueue.put(obj) 300 except: 301 pass
302
303 - def _info(self, msg):
304 self._log('info', msg)
305
306 - def _err(self, msg):
307 self._log('err', msg)
308
309 - def run_callback(self, path, value):
310 value = value[0] 311 self.run_mode = value 312 message = "received OSC message '%s' with arguments '%d'" % (path, value) 313 self._info(message)
314
315 - def media_next_callback(self, path, value):
316 value = value[0] 317 self.next_media = value 318 message = "received OSC message '%s' with arguments '%d'" % (path, value) 319 self._info(message)
320
321 - def relay_callback(self, path, value):
322 value = value[0] 323 if value: 324 self.relay_mode = 1 325 if self.type == 'icecast': 326 self.player.start_relay(self.relay_url) 327 else: 328 self.relay_mode = 0 329 if self.type == 'icecast': 330 self.player.stop_relay() 331 332 self.id = 0 333 self.next_media = 1 334 message = "received OSC message '%s' with arguments '%d'" % (path, value) 335 self._info(message) 336 message = "relaying : %s" % self.relay_url 337 self._info(message)
338
339 - def twitter_callback(self, path, value):
340 value = value[0] 341 self.twitter = Twitter(self.twitter_key, self.twitter_secret) 342 self.twitter_mode = value 343 message = "received OSC message '%s' with arguments '%d'" % (path, value) 344 345 # IMPROVEMENT: The URL paths should be configurable because they're 346 # server-implementation specific 347 self.m3u_url = self.channel.url + '/m3u/' + self.m3u.split(os.sep)[-1] 348 self.feeds_url = self.channel.url + '/rss/' + self.feeds_playlist_file.split(os.sep)[-1] 349 self._info(message)
350
351 - def jingles_callback(self, path, value):
352 value = value[0] 353 if value: 354 self.jingles_list = self.get_jingles() 355 self.jingles_length = len(self.jingles_list) 356 self.jingle_id = 0 357 self.jingles_mode = value 358 message = "received OSC message '%s' with arguments '%d'" % (path, value) 359 self._info(message)
360
361 - def record_callback(self, path, value):
362 value = value[0] 363 if value: 364 if not os.path.exists(self.record_dir): 365 os.makedirs(self.record_dir) 366 self.rec_file = self.short_name.replace('/', '_') + '-' 367 self.rec_file += datetime.datetime.now().strftime("%x-%X").replace('/', '_') 368 self.rec_file += '.' + self.channel.format 369 self.recorder = Recorder(self.record_dir) 370 self.recorder.open(self.rec_file) 371 else: 372 try: 373 self.recorder.recording = False 374 self.recorder.close() 375 except: 376 pass 377 378 if self.type == 'icecast': 379 date = datetime.datetime.now().strftime("%Y") 380 media = None 381 if self.channel.format == 'mp3': 382 media = Mp3(self.record_dir + os.sep + self.rec_file) 383 if self.channel.format == 'ogg': 384 media = Ogg(self.record_dir + os.sep + self.rec_file) 385 if media: 386 media.metadata = {'artist': self.artist.encode('utf-8'), 387 'title': self.title.encode('utf-8'), 388 'album': self.short_name.encode('utf-8'), 389 'genre': self.channel.genre.encode('utf-8'), 390 'date': date.encode('utf-8'), } 391 media.write_tags() 392 393 self.record_mode = value 394 message = "received OSC message '%s' with arguments '%d'" % (path, value) 395 self._info(message)
396
397 - def player_callback(self, path, value):
398 value = value[0] 399 self.player_mode = value 400 message = "received OSC message '%s' with arguments '%d'" % (path, value) 401 self._info(message)
402
403 - def get_playlist(self):
404 file_list = [] 405 406 try: 407 if os.path.isdir(self.media_source): 408 self.q.get(1) 409 try: 410 for root, dirs, files in os.walk(self.media_source): 411 for file in files: 412 s = file.split('.') 413 ext = s[len(s) - 1] 414 if ext.lower() == self.channel.format and not os.sep + '.' in file: 415 file_list.append(root + os.sep + file) 416 file_list.sort() 417 except: 418 pass 419 self.q.task_done() 420 421 if os.path.isfile(self.media_source): 422 self.q.get(1) 423 try: 424 f = open(self.media_source, 'r') 425 try: 426 for path in f.readlines(): 427 path = path.strip() 428 if '#' != path[0]: 429 fp = self._path_m3u_rel(path) 430 if os.path.isfile(fp): 431 file_list.append(fp) 432 except: 433 f.close() 434 except: 435 pass 436 self.q.task_done() 437 except: 438 pass 439 440 return file_list
441
442 - def get_jingles(self):
443 file_list = [] 444 for root, dirs, files in os.walk(self.jingles_dir): 445 for file in files: 446 s = file.split('.') 447 ext = s[len(s) - 1] 448 if ext.lower() == self.channel.format and not os.sep + '.' in file: 449 file_list.append(root + os.sep + file) 450 file_list.sort() 451 return file_list
452
453 - def tweet(self):
454 if len(self.new_tracks): 455 new_tracks_objs = self.media_to_objs(self.new_tracks) 456 for media_obj in new_tracks_objs: 457 title, artist, song = self.get_songmeta(media_obj) 458 459 artist_names = artist.split(' ') 460 artist_tags = ' #'.join(list(set(artist_names) - {'&', '-'})) 461 message = '#NEWTRACK ! %s %s on #%s' % \ 462 (song, artist_tags.strip(), self.short_name) 463 message = message[:113] + self.feeds_url 464 self.update_twitter(message)
465
466 - def get_next_media(self):
467 # Init playlist 468 if self.lp: 469 playlist = self.playlist 470 new_playlist = self.get_playlist() 471 lp_new = len(new_playlist) 472 473 if not self.counter: 474 self.id = 0 475 if -1 < self.starting_id < lp_new: 476 self.id = self.starting_id 477 self.playlist = new_playlist 478 self.lp = lp_new 479 480 # Shake it, Fuzz it ! 481 if self.shuffle_mode: 482 random.shuffle(self.playlist) 483 484 self._info('Generating new playlist (' + str(self.lp) + ' tracks)') 485 486 elif lp_new != self.lp: 487 self.id += 1 488 if self.id >= lp_new: 489 self.id = 0 490 else: 491 self.lp = lp_new 492 493 # Twitting new tracks 494 new_playlist_set = set(new_playlist) 495 playlist_set = set(playlist) 496 new_tracks = new_playlist_set - playlist_set 497 self.new_tracks = list(new_tracks.copy()) 498 499 if self.twitter_mode == 1 and self.counter: 500 self.tweet() 501 502 # Shake it, Fuzz it ! 503 if self.shuffle_mode: 504 random.shuffle(playlist) 505 506 # Play new tracks first 507 for track in self.new_tracks: 508 playlist.insert(0, track) 509 510 self.playlist = playlist 511 512 self._info('Generating new playlist (' + str(self.lp) + ' tracks)') 513 514 if self.jingles_mode and not (self.counter % self.jingles_frequency) and self.jingles_length: 515 media = self.jingles_list[self.jingle_id] 516 self.jingle_id = (self.jingle_id + 1) % self.jingles_length 517 else: 518 media = self.playlist[self.id] 519 self.id = (self.id + 1) % self.lp 520 521 self.q.get(1) 522 try: 523 f = open(self.statusfile, 'w') 524 f.write(str(self.id)) 525 f.close() 526 if self.feeds_playlist: 527 self.update_feeds(self.media_to_objs(self.playlist), self.feeds_playlist_file, '(playlist)') 528 except: 529 pass 530 self.q.task_done() 531 return media 532 else: 533 mess = 'No media in source!' 534 self._err(mess) 535 self.run_mode = 0
536
537 - def media_to_objs(self, media_list):
538 media_objs = [] 539 for media in media_list: 540 file_meta = MediaBase() 541 file_name, file_title, file_ext = get_file_info(media) 542 self.q.get(1) 543 try: 544 if file_ext.lower() == 'mp3' or mimetypes.guess_type(media)[0] == 'audio/mpeg': 545 file_meta = Mp3(media) 546 elif file_ext.lower() == 'ogg' or mimetypes.guess_type(media)[0] == 'audio/ogg': 547 file_meta = Ogg(media) 548 elif file_ext.lower() == 'webm' or mimetypes.guess_type(media)[0] == 'video/webm': 549 file_meta = WebM(media) 550 except Exception, e: 551 self._err('Could not get specific media type class for %s' % (media)) 552 self._err('Error: %s' % (str(e))) 553 pass 554 self.q.task_done() 555 media_objs.append(file_meta) 556 return media_objs
557
558 - def update_feeds(self, media_list, rss_file, sub_title):
559 if not self.feeds_mode: 560 return 561 562 rss_item_list = [] 563 if not os.path.exists(self.feeds_dir): 564 os.makedirs(self.feeds_dir) 565 channel_subtitle = self.channel.name + ' ' + sub_title 566 _date_now = datetime.datetime.now() 567 date_now = str(_date_now) 568 media_absolute_playtime = _date_now 569 json_data = [] 570 571 for media in media_list: 572 json_item = {} 573 media_stats = os.stat(media.media) 574 media_date = time.localtime(media_stats[8]) 575 media_date = time.strftime("%a, %d %b %Y %H:%M:%S +0200", media_date) 576 media.metadata['Duration'] = str(media.length).split('.')[0] 577 media.metadata['Bitrate'] = str(media.bitrate) + ' kbps' 578 media.metadata['Next play'] = str(media_absolute_playtime).split('.')[0] 579 580 media_description = '<table>' 581 media_description_item = '<tr><td>%s: </td><td><b>%s</b></td></tr>' 582 583 for key in media.metadata.keys(): 584 if media.metadata[key] != '': 585 if key == 'filepath' and not self.feeds_showfilepath: 586 continue 587 if key == 'filename' and not self.feeds_showfilename: 588 continue 589 media_description += media_description_item % (key.capitalize(), 590 media.metadata[key]) 591 json_item[key] = media.metadata[key] 592 if self.feeds_showfilepath: 593 media_description += media_description_item % ('Filepath', media.media) 594 json_item['filepath'] = media.media 595 if self.feeds_showfilename: 596 media_description += media_description_item % ('Filename', media.file_name) 597 json_item['filename'] = media.file_name 598 media_description += '</table>' 599 600 title, artist, song = self.get_songmeta(media) 601 media_absolute_playtime += media.length 602 603 if self.feeds_enclosure == '1': 604 media_link = self.feeds_media_url + media.file_name 605 media_link = media_link.decode('utf-8') 606 rss_item_list.append(RSSItem( 607 title=song, 608 link=media_link, 609 description=media_description, 610 enclosure=Enclosure(media_link, str(media.size), 'audio/mpeg'), 611 guid=Guid(media_link), 612 pubDate=media_date, ) 613 ) 614 else: 615 media_link = self.metadata_url + '/' + media.file_name + '.xml' 616 try: 617 media_link = media_link.decode('utf-8') 618 except: 619 continue 620 rss_item_list.append(RSSItem( 621 title=song, 622 link=media_link, 623 description=media_description, 624 guid=Guid(media_link), 625 pubDate=media_date, ) 626 ) 627 json_data.append(json_item) 628 629 rss = RSS2(title=channel_subtitle, 630 link=self.channel.url, 631 description=self.channel.description.decode('utf-8'), 632 lastBuildDate=date_now, 633 items=rss_item_list, ) 634 self.q.get(1) 635 try: 636 if self.feeds_rss: 637 f = open(rss_file + '.xml', 'w') 638 rss.write_xml(f, 'utf-8') 639 f.close() 640 except: 641 pass 642 643 try: 644 if self.feeds_json: 645 f = open(rss_file + '.json', 'w') 646 f.write(json.dumps(json_data, separators=(',', ':'))) 647 f.close() 648 except: 649 pass 650 self.q.task_done()
651
652 - def update_twitter(self, message):
653 try: 654 self.twitter.post(message.decode('utf8')) 655 self._info('Twitting : "' + message + '"') 656 except: 657 self._err('Twitting : "' + message + '"')
658
659 - def set_relay_mode(self):
660 self.prefix = '#nowplaying #LIVE' 661 self.get_currentsongmeta() 662 663 if self.type == 'stream-m': 664 relay = URLReader(self.relay_url) 665 self.channel.set_callback(relay.read_callback) 666 if self.record_mode: 667 relay.set_recorder(self.recorder) 668 else: 669 self.stream = self.player.relay_read()
670
671 - def get_songmeta(self, mediaobj):
672 title = "" 673 artist = "" 674 song = "" 675 676 try: 677 title = mediaobj.get_title() 678 artist = mediaobj.get_artist() 679 song = mediaobj.get_song(True) 680 except: 681 pass 682 683 return title, artist, song
684
685 - def get_currentsongmeta(self):
686 self.title = "" 687 self.artist = "" 688 self.song = "" 689 self.current_media_obj = MediaBase() 690 691 try: 692 m = self.media_to_objs([self.media]) 693 self.current_media_obj = m[0] 694 except: 695 self._info("Failed to get media object for %s" % (self.media)) 696 pass 697 698 self.title, self.artist, self.song = self.get_songmeta(self.current_media_obj)
699
700 - def set_read_mode(self):
701 self.prefix = '#nowplaying' 702 703 try: 704 self.get_currentsongmeta() 705 fn = self.current_media_obj.file_name 706 if fn: 707 self.metadata_file = self.metadata_dir + os.sep + fn + '.xml' 708 self.update_feeds([self.current_media_obj], self.feeds_current_file, '(currently playing)') 709 if fn: 710 self._info('DeeFuzzing: id = %s, name = %s' % (self.id, fn)) 711 except: 712 pass 713 self.player.set_media(self.media) 714 715 self.q.get(1) 716 try: 717 if self.player_mode: 718 self.stream = self.player.file_read_slow() 719 else: 720 self.stream = self.player.file_read_fast() 721 except: 722 pass 723 self.q.task_done()
724
725 - def set_webm_read_mode(self):
726 self.channel.set_callback(FileReader(self.media).read_callback)
727
728 - def update_twitter_current(self):
729 if not self.__twitter_should_update(): 730 return 731 message = '%s %s on #%s' % (self.prefix, self.song, self.short_name) 732 tags = '#' + ' #'.join(self.twitter_tags) 733 message = message + ' ' + tags 734 message = message[:108] + ' M3U: ' + self.m3u_url 735 self.update_twitter(message)
736
737 - def channel_open(self):
738 if self.channelIsOpen: 739 return True 740 741 try: 742 self.channel.open() 743 self.channel_delay = self.channel.delay() 744 self._info('channel connected') 745 self.channelIsOpen = True 746 return True 747 except: 748 self._err('channel could not be opened') 749 750 return False
751
752 - def channel_close(self):
753 self.channelIsOpen = False 754 try: 755 self.channel.close() 756 self._info('channel closed') 757 except: 758 self._err('channel could not be closed')
759
760 - def ping_server(self):
761 log = True 762 763 while not self.server_ping: 764 try: 765 server = urllib.urlopen(self.server_url) 766 self.server_ping = True 767 self._info('Channel available.') 768 except: 769 time.sleep(1) 770 if log: 771 self._err('Could not connect the channel. Waiting for channel to become available.') 772 log = False
773
774 - def icecastloop_nextmedia(self):
775 try: 776 self.next_media = 0 777 self.media = self.get_next_media() 778 self.counter += 1 779 self.counter = (self.counter % self.jingles_frequency) + self.jingles_frequency 780 if self.relay_mode: 781 self.set_relay_mode() 782 elif os.path.exists(self.media) and not os.sep + '.' in self.media: 783 if self.lp == 0: 784 self._err('has no media to stream !') 785 return False 786 self.set_read_mode() 787 788 return True 789 except Exception, e: 790 self._err('icecastloop_nextmedia: Error: ' + str(e)) 791 return False
792
793 - def __twitter_should_update(self):
794 """Returns whether or not an update should be sent to Twitter""" 795 if not self.twitter_mode: 796 # Twitter posting disabled. Return false. 797 return False 798 799 if self.relay_mode: 800 # We are in relay mode. Return true. 801 return True 802 803 if self.jingles_mode and (self.counter % self.jingles_frequency): 804 # We should be playing a jingle, and we don't send jingles to Twiitter. 805 return False 806 return True
807
808 - def icecastloop_metadata(self):
809 try: 810 self.update_twitter_current() 811 self.channel.set_metadata({'song': self.song, 'charset': 'utf-8'}) 812 return True 813 except Exception, e: 814 self._err('icecastloop_metadata: Error: ' + str(e)) 815 return False
816
817 - def run(self):
818 self.ping_server() 819 820 if self.type == 'stream-m': 821 if self.relay_mode: 822 self.set_relay_mode() 823 else: 824 self.media = self.get_next_media() 825 self.set_webm_read_mode() 826 if not self.channel_open(): 827 return 828 self.channel.start() 829 830 if self.type == 'icecast': 831 while True: # Do this so that the handlers will still restart the stream 832 while self.run_mode: 833 if not self.channel_open(): 834 return 835 836 if not self.icecastloop_nextmedia(): 837 self._info('Something wrong happened in icecastloop_nextmedia. Ending.') 838 self.channel_close() 839 return 840 841 self.icecastloop_metadata() 842 843 # TEST MODE: Jump thru only the first chunk of each file 844 # first = True 845 for self.chunk in self.stream: 846 # if first: 847 # first = False 848 # else: 849 # break 850 851 if self.next_media or not self.run_mode: 852 break 853 854 if self.record_mode: 855 try: 856 # Record the chunk 857 self.recorder.write(self.chunk) 858 except: 859 self._err('could not write the buffer to the file') 860 861 try: 862 # Send the chunk to the stream 863 self.channel.send(self.chunk) 864 self.channel.sync() 865 except: 866 self._err('could not send the buffer') 867 self.channel_close() 868 if not self.channel_open(): 869 self._err('could not restart the channel') 870 if self.record_mode: 871 self.recorder.close() 872 return 873 try: 874 self.channel.set_metadata({'song': self.song, 'charset': 'utf8', }) 875 self._info('channel restarted') 876 self.channel.send(self.chunk) 877 self.channel.sync() 878 except: 879 self._err('could not send data after restarting the channel') 880 self.channel_close() 881 if self.record_mode: 882 self.recorder.close() 883 return 884 885 # send chunk loop end 886 # while run_mode loop end 887 888 self._info("Play mode ended. Stopping stream.") 889 890 if self.record_mode: 891 self.recorder.close() 892 893 self.channel_close() 894 time.sleep(1)
895