def program_start(program_id): from programs.models import Program from streams.models import Channel logger.info( "Launching program with id {0}" .format(program_id) ) try: program = Program.objects.get(pk=program_id) channel = Channel.objects.get(program=program) sck = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) sck.connect(LS_SOCKET_BASE_CHANNEL_PATH.format(channel.pk)) sck.send( LSTN_CMD_PROGRAM_ADD.format(program_id).encode(encoding='utf_8')) sck.send( LSTN_CMD_EXIT.encode(encoding="utf_8")) sck.close() except Program.DoesNotExist: logger.error( "Program with id {0} does not exist" .format(program_id) ) logger.info( "Launched program with id {0}" .format(program_id) ) return
def channel_end(channel_id): from .models import Channel, ChannelProc logger.info("Closing channel with id {0}".format(channel_id)) channel = Channel.objects.get(pk=channel_id) try: channel_proc = ChannelProc.objects.get(channel=channel) try: proc = psutil.Process(channel_proc.pid) proc.kill() except psutil.NoSuchProcess: logger.warning( "Channel proc with pid {0} does not exist" .format(channel_proc.pid) ) channel_proc.delete() except ChannelProc.DoesNotExist: logger.warning( "There's no proc info for channel with id {0}" .format(channel_id) ) logger.info("Closed channel with id {0}".format(channel_id)) return
def recording_capture(recording_source_id): from .models import RecordingSource logger.info( "Starting recording for external source with id {0}" .format(recording_source_id) ) try: recording = RecordingSource.objects.get(pk=recording_source_id) recording.location = create_recording_path(recording) recording.save() subprocess.Popen([ LIQUIDSOAP_BIN_PATH, LS_RECORD_SCRIPT, "--", str(recording_source_id), str(SWR_API_ROOT), ]) logger.info( "Started recording for external source with id {0}" .format(recording_source_id) ) except RecordingSource.DoesNotExist: logger.error( "Recording with id {0} does not exist" .format(recording_source_id) ) return
def podcast_check(podcast_id): from sources.models import PodcastSource logger.info("Checking PodcastSource with id {0}".format(podcast_id)) try: podcast = PodcastSource.objects.get(pk=podcast_id) feed = feedparser.parse(podcast.url) last_entry = feed.entries[0] publish_date = parser.parse(last_entry.published) urls = [] for enclosure in last_entry.enclosures: urls.append(enclosure.href) if ((podcast.last_date is None) or (publish_date > podcast.last_date) or (podcast.last_url not in urls)): download_podcast.delay(podcast_id, last_entry.published, urls[0]) except PodcastSource.DoesNotExist: logger.error( "PodcastSource with id {0} does not exist".format(podcast_id) ) except IndexError: logger.warning( "Feed for PodcastSource with id {0} has no content".format( podcast_id) ) return
def check_channels(): from .models import Channel logger.info("Checking status of all channels") channel_list = Channel.objects.all() logger.info("{0} channels to check".format(channel_list.count())) for channel in channel_list: manage_channel_proc.delay(channel.pk, False) return
def mount_start(mount_id): from .models import Mount, MountProc logger.info("Starting mount with id {0}".format(mount_id)) mount = Mount.objects.get(pk=mount_id) init_proc = subprocess.Popen([ LIQUIDSOAP_BIN_PATH, LS_MOUNT_SCRIPT, "--", str(mount_id), str(SWR_API_ROOT), ]) logger.info("Started mount with id {0}".format(mount_id)) logger.info( "Storing init_proc info for mount with id {0}".format(mount_id) ) proc = psutil.Process(init_proc.pid) mount_proc = MountProc() mount_proc.mount = mount mount_proc.pid = init_proc.pid mount_proc.hash = (hash(proc)) mount_proc.save() logger.info( "Stored init_proc info for mount with id {0}".format(mount_id) ) return
def folder_check(folder_id): from .models import FolderSource logger.info("Checking FolderSource with id {0}".format(folder_id)) try: folder_source = FolderSource.objects.get(pk=folder_id) if not location_exists(folder_source.location): logger.error( "FolderSource with id {0} no longer exists".format(folder_id)) folder_source.delete() except FolderSource.DoesNotExist: logger.error( "FolderSource with id {0} does not exist".format(folder_id) ) return
def check_programmation(): from .models import Program logger.info("Checking programs") now = timezone.localtime(timezone.now()) + TIME_AHEAD future = (now + PROGRAMMING_TIMEDELTA) need_programming = Program.objects.filter( channel__enabled=True, start__gte=now, start__lt=future ) for program in need_programming: program_start.delay(program.pk) logger.info("Checked programmations") return
def recording_check(recording_id): from .models import RecordingSource logger.info("Checking RecordingSource with id {0}".format(recording_id)) try: recording_source = RecordingSource.objects.get(pk=recording_id) if (recording_source.location is not None) and \ (not location_exists(recording_source.location)): logger.error( "RecordingSource with id {0} no longer exists".format( recording_id)) recording_source.delete() except RecordingSource.DoesNotExist: logger.error( "RecordingSource with id {0} does not exist".format(recording_id) ) return
def channel_notify_save(channel_id): from .models import Channel logger.info( "Notifying save to channel with id {0}" .format(channel_id) ) try: channel = Channel.objects.get(pk=channel_id) sck = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) sck.connect(LS_SOCKET_BASE_CHANNEL_PATH.format(channel.pk)) sck.send(LSTN_CMD_NOTIFY_SAVE.encode(encoding='utf_8')) sck.send(LSTN_CMD_EXIT.encode(encoding="utf_8")) sck.close() logger.info( "Notified save to channel with id {0}" .format(channel_id) ) except Channel.DoesNotExist: logger.info( "Channel with id {0} does not exist" .format(channel_id) ) return
def media_check(): from sources.models import FileSource, FolderSource, RecordingSource,\ PodcastSource logger.info("Checking media files") # Recordings to recording_capture # This check goes first because the recordings need to be launched now = timezone.localtime(timezone.now()) + TIME_AHEAD future = (now + MEDIA_CHECK_TIMEDELTA) need_record_set = RecordingSource.objects.filter( start__gte=now, start__lt=future ) for recording in need_record_set: recording_capture.delay(recording.pk) # Check files file_set = FileSource.objects.all() for file in file_set: file_check.delay(file.pk) # Check folders folder_set = FolderSource.objects.all() for folder in folder_set: folder_check.delay(folder.pk) # Check captured records already_recorded_set = RecordingSource.objects.filter( start__lt=now) for recording in already_recorded_set: recording_check.delay(recording.pk) # Check podcasts podcast_set = PodcastSource.objects.all() for podcast in podcast_set: podcast_check.delay(podcast.pk) return
def mount_notify_save(mount_id): from .models import Mount logger.info( "Notifying save to mount with id {0}" .format(mount_id) ) mount = Mount.objects.get(pk=mount_id) sck = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) sck.connect(LS_SOCKET_BASE_MOUNT_PATH.format(mount.pk)) sck.send(LSTN_CMD_NOTIFY_SAVE.encode(encoding='utf_8')) sck.send(LSTN_CMD_EXIT.encode(encoding="utf_8")) sck.close() logger.info( "Notified save to mount with id {0}" .format(mount_id) ) return
def mount_end(mount_id): from .models import Mount, MountProc logger.info("Ending mount with id {0}".format(mount_id)) mount = Mount.objects.get(pk=mount_id) try: mount_proc = MountProc.objects.get(mount=mount) try: proc = psutil.Process(mount_proc.pid) proc.kill() except psutil.NoSuchProcess: logger.warning( "Mount proc with pid {0} does not exist" .format(mount_proc.pid) ) mount_proc.delete() except MountProc.DoesNotExist: logger.warning( "There's no proc info for mount with id {0}" .format(mount_id) ) logger.info("Ended mount with id {0}".format(mount_id)) return
def channel_start(channel_id): from .models import Channel, ChannelProc logger.info("Starting channel with id {0}".format(channel_id)) try: channel = Channel.objects.get(pk=channel_id) init_proc = subprocess.Popen([ LIQUIDSOAP_BIN_PATH, LS_CHANNEL_SCRIPT, "--", str(channel_id), str(SWR_API_ROOT), ]) logger.info("Started channel with id {0}".format(channel_id)) logger.info( "Storing init_proc info " "for channel with id {0}".format(channel_id) ) proc = psutil.Process(init_proc.pid) channel_proc = ChannelProc() channel_proc.channel = channel channel_proc.pid = init_proc.pid channel_proc.hash = (hash(proc)) channel_proc.save() logger.info( "Stored init_proc info " "for channel with id {0}".format(channel_id) ) except Channel.DoesNotExist: logger.error( "Channel with id {0} does not exist" .format(channel_id) ) return
def manage_mount_proc(mount_id, is_post_save): from .models import Mount, MountProc logger.info("Managing status of mount with id {0}".format(mount_id)) try: # Recover mount info mount = Mount.objects.get(pk=mount_id) mount_proc = None try: mount_proc = MountProc.objects.get(mount=mount) except MountProc.DoesNotExist: mount_proc = None # Manage stream status if (mount.channel.enabled): if (mount_proc is None): # Launch mount logger.info( "Launching mount with id {0}".format(mount_id) ) mount_start.delay(mount.pk) else: # Check if mount is running try: proc = psutil.Process(mount_proc.pid) if proc.status() == psutil.STATUS_ZOMBIE: logger.warning( "Mount is not running (zombie process pid {0})" .format(mount_proc.pid) ) mount_proc.delete() mount_start.delay(mount_id) elif hash(proc) != mount_proc.hash: logger.warning( "Mount is not running (diff hash for pid {0})" .format(mount_proc.pid) ) mount_proc.delete() mount_start.delay(mount_id) else: logger.info( "Mount is running with pid {0}" .format(mount_proc.pid) ) if is_post_save: mount_notify_save.delay(mount_id) except psutil.NoSuchProcess: # If it's not running, restart logger.warning( "Mount proc with pid {0} does not exist" .format(mount_proc.pid) ) logger.info( "Restarting mount with id {0}".format(mount_id) ) mount_proc.delete() mount_start.delay(mount_id) elif (not mount.channel.enabled) and (mount_proc is not None): # Close mount logger.info( "Closing mount with id {0}".format(mount_id) ) mount_end.delay(mount.pk) logger.info("Managed status of mount with id {0}".format(mount_id)) except Mount.DoesNotExist: logger.error("Mount with id {0} does not exist".format(mount_id)) return
def manage_channel_proc(channel_id, is_post_save): from .models import Channel, ChannelProc logger.info("Managing status of channel with id {0}".format(channel_id)) try: # Recover channel info channel = Channel.objects.get(pk=channel_id) channel_proc = None try: channel_proc = ChannelProc.objects.get(channel=channel) except ChannelProc.DoesNotExist: channel_proc = None if (channel.enabled): if (channel_proc is None): # Launch channel logger.info( "Launching channel with id {0}".format(channel_id) ) channel_start.delay(channel_id) else: # Check if channel is running try: proc = psutil.Process(channel_proc.pid) if proc.status() == psutil.STATUS_ZOMBIE: logger.warning( "Channel is not running (zombie process pid {0})" .format(channel_proc.pid) ) channel_proc.delete() channel_start.delay(channel_id) elif hash(proc) != channel_proc.hash: logger.warning( "Channel is not running (diff hash for pid {0})" .format(channel_proc.pid) ) channel_proc.delete() channel_start.delay(channel_id) else: logger.info( "Channel is running with pid {0}" .format(channel_proc.pid) ) if is_post_save: channel_notify_save.delay(channel_id) except psutil.NoSuchProcess: # If it's not running, restart logger.warning( "Channel proc with pid {0} does not exist" .format(channel_proc.pid) ) logger.info( "Restarting channel with id {0}".format(channel_id) ) channel_proc.delete() channel_start.delay(channel_id) elif (not channel.enabled) and (channel_proc is not None): # Close channel logger.info( "Closing channel with id {0}".format(channel_id) ) channel_end.delay(channel.pk) for mount in channel.mount_set.all(): manage_mount_proc.delay(mount.pk, is_post_save) logger.info( "Managed status of channel with id {0}".format(channel_id)) except Channel.DoesNotExist: logger.error("Channel with id {0} does not exist".format(channel_id)) return