2014-10-27 16:29:04 -06:00
# -*- coding: utf-8 -*-
import sys
import url_shortener
import audio_services
import os
import logging as original_logger
log = original_logger . getLogger ( "sound" )
import paths
2017-07-19 15:25:09 +02:00
import sound_lib
2014-10-27 16:29:04 -06:00
import subprocess
import platform
2014-11-12 20:41:29 -06:00
import output
2018-02-16 17:58:57 -06:00
import youtube_utils
2018-02-20 11:47:33 -06:00
import vlc
2014-10-27 16:29:04 -06:00
system = platform . system ()
from mysc.repeating_timer import RepeatingTimer
2015-05-14 10:01:37 -04:00
from mysc.thread_utils import call_threaded
2015-04-19 19:10:34 -04:00
import application
2016-01-30 17:14:41 +01:00
import tempfile
import glob
2015-01-20 15:40:33 -06:00
URLPlayer = None
2014-10-27 16:29:04 -06:00
def setup ():
2015-01-20 15:40:33 -06:00
global URLPlayer
2014-11-12 20:41:29 -06:00
if not URLPlayer :
2015-01-18 17:19:39 -06:00
log . debug ( "creating stream URL player..." )
2014-11-12 20:41:29 -06:00
URLPlayer = URLStream ()
2014-10-27 16:29:04 -06:00
def recode_audio ( filename , quality = 4.5 ):
global system
if system == "Windows" : subprocess . call ( r '" %s " -q %r " %s "' % ( paths . app_path ( 'oggenc2.exe' ), quality , filename ))
def recording ( filename ):
# try:
2017-07-19 15:25:09 +02:00
val = sound_lib . recording . WaveRecording ( filename = filename )
2014-10-27 16:29:04 -06:00
# except sound_lib.main.BassError:
# sound_lib.input.Input()
# val = sound_lib.recording.WaveRecording(filename=filename)
return val
class soundSystem ( object ):
def check_soundpack ( self ):
""" Checks if the folder where live the current soundpack exists."""
self . soundpack_OK = False
2015-01-20 15:40:33 -06:00
if os . path . exists ( paths . sound_path ( self . config [ "current_soundpack" ])):
self . path = paths . sound_path ( self . config [ "current_soundpack" ])
2014-10-27 16:29:04 -06:00
self . soundpack_OK = True
elif os . path . exists ( paths . sound_path ( "default" )):
2015-01-18 17:19:39 -06:00
log . error ( "The soundpack does not exist, using default..." )
2014-10-27 16:29:04 -06:00
self . path = paths . sound_path ( "default" )
self . soundpack_OK = True
else :
2015-04-19 19:10:34 -04:00
log . error ( "The current soundpack could not be found and the default soundpack has been deleted, " + application . name + " will not play sounds." )
2014-10-27 16:29:04 -06:00
self . soundpack_OK = False
2015-01-20 15:40:33 -06:00
def __init__ ( self , soundConfig ):
2014-10-27 16:29:04 -06:00
""" Sound Player."""
2015-01-20 15:40:33 -06:00
self . config = soundConfig
2014-10-27 16:29:04 -06:00
# Set the output and input default devices.
2017-07-19 15:23:34 +02:00
try :
2017-07-19 15:25:09 +02:00
self . output = sound_lib . output . Output ()
self . input = sound_lib . input . Input ()
except :
2017-07-19 15:23:34 +02:00
pass
2017-07-19 15:25:09 +02:00
# Try to use the selected device from the configuration. It can fail if the machine does not has a mic.
2017-07-19 15:23:34 +02:00
try :
log . debug ( "Setting input and output devices..." )
self . output . set_device ( self . output . find_device_by_name ( self . config [ "output_device" ]))
self . input . set_device ( self . input . find_device_by_name ( self . config [ "input_device" ]))
except :
2017-07-19 15:25:09 +02:00
log . error ( "Error in input or output devices, using defaults..." )
2017-07-19 15:23:34 +02:00
self . config [ "output_device" ] = "Default"
self . config [ "input_device" ] = "Default"
2014-10-27 16:29:04 -06:00
self . files = []
self . cleaner = RepeatingTimer ( 60 , self . clear_list )
self . cleaner . start ()
self . check_soundpack ()
def clear_list ( self ):
2014-11-12 20:41:29 -06:00
if len ( self . files ) == 0 : return
try :
for i in range ( 0 , len ( self . files )):
if self . files [ i ] . is_playing == False :
self . files [ i ] . free ()
self . files . pop ( i )
except IndexError :
pass
2014-10-27 16:29:04 -06:00
def play ( self , sound , argument = False ):
if self . soundpack_OK == False : return
2015-03-11 17:17:29 -06:00
if self . config [ "session_mute" ] == True : return
2017-07-19 15:25:09 +02:00
sound_object = sound_lib . stream . FileStream ( file = " %s / %s " % ( self . path , sound ))
2015-01-20 15:40:33 -06:00
sound_object . volume = float ( self . config [ "volume" ])
2014-10-27 16:29:04 -06:00
self . files . append ( sound_object )
sound_object . play ()
2014-11-12 20:41:29 -06:00
class URLStream ( object ):
2018-02-20 11:47:33 -06:00
""" URL Stream Player implementation."""
def __init__ ( self ):
# URL status. Should be True after URL expansion and transformation.
2014-10-27 16:29:04 -06:00
self . prepared = False
2015-03-11 06:11:42 -06:00
log . debug ( "URL Player initialized" )
2018-02-20 11:47:33 -06:00
# LibVLC controls.
self . instance = vlc . Instance ()
self . player = self . instance . media_player_new ()
2014-10-27 16:29:04 -06:00
2014-11-12 20:41:29 -06:00
def prepare ( self , url ):
2018-02-20 11:47:33 -06:00
""" Takes an URL and prepares it to be streamed. This function will try to unshorten the passed URL and, if needed, to transform it into a valid URL."""
2015-03-11 06:11:42 -06:00
log . debug ( "Preparing URL: %s " % ( url ,))
2014-10-27 16:29:04 -06:00
self . prepared = False
2014-11-12 20:41:29 -06:00
self . url = url_shortener . unshorten ( url )
2017-12-10 10:22:12 -06:00
if self . url == None :
self . url = url
2018-02-20 11:47:33 -06:00
log . debug ( "Expanded URL: %s " % ( self . url ,))
2014-11-12 20:41:29 -06:00
if self . url != None :
transformer = audio_services . find_url_transformer ( self . url )
2018-02-20 11:47:33 -06:00
transformed_url = transformer ( self . url )
2018-02-16 17:58:57 -06:00
self . url = transformed_url
2017-12-10 10:22:12 -06:00
log . debug ( "Transformed URL: %s . Prepared" % ( self . url ,))
2017-09-22 17:38:03 +02:00
self . prepared = True
2014-10-27 16:29:04 -06:00
2018-02-20 11:47:33 -06:00
def seek ( self , step ):
pos = self . player . get_time ()
2016-08-10 21:59:19 -05:00
pos += step
2018-02-20 11:47:33 -06:00
pos = self . player . set_time ( pos )
2016-08-10 21:59:19 -05:00
def playpause ( self ):
2018-02-20 11:47:33 -06:00
if self . player . is_playing () == True :
self . player . pause ()
2016-08-10 21:59:19 -05:00
else :
2018-02-20 11:47:33 -06:00
self . player . play ()
2016-08-10 21:59:19 -05:00
2018-02-20 11:47:33 -06:00
def play ( self , url = None , volume = 1.0 , announce = True ):
2015-07-03 17:23:25 -05:00
if announce :
output . speak ( _ ( u "Playing..." ))
log . debug ( "Attempting to play an URL..." )
if url != None :
self . prepare ( url )
if self . prepared == True :
2018-02-20 11:47:33 -06:00
media = self . instance . media_new ( self . url )
self . player . set_media ( media )
self . player . audio_set_volume ( int ( volume * 100 ))
self . player . play ()
log . debug ( "played" )
2018-02-16 17:58:57 -06:00
self . prepared = False
2015-05-14 10:01:37 -04:00
2018-02-20 11:47:33 -06:00
def stop_audio ( self ):
output . speak ( _ ( u "Stopped." ), True )
self . player . stop ()