files.new_contents: # Copyright 2017 Mycroft AI Inc.
  #
  # Licensed under the Apache License, Version 2.0 (the "License");
  # you may not use this file except in compliance with the License.
  # You may obtain a copy of the License at
  #
  #    http://www.apache.org/licenses/LICENSE-2.0
  #
  # Unless required by applicable law or agreed to in writing, software
  # distributed under the License is distributed on an "AS IS" BASIS,
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  # See the License for the specific language governing permissions and
  # limitations under the License.
  
  import imp
  import sys
  import time
  from os import listdir
  from os.path import abspath, dirname, basename, isdir, join
  from threading import Lock
  
  from mycroft.configuration import Configuration
  from mycroft.messagebus.message import Message
  from mycroft.util.log import LOG
  
  try:
      import pulsectl
  except ImportError:
      pulsectl = None
  
  MAINMODULE = '__init__'
  sys.path.append(abspath(dirname(__file__)))
  
  
  def create_service_descriptor(service_folder):
      """Prepares a descriptor that can be used together with imp.
  
          Args:
              service_folder: folder that shall be imported.
  
          Returns:
              Dict with import information
      """
      info = imp.find_module(MAINMODULE, [service_folder])
      return {"name": basename(service_folder), "info": info}
  
  
  def get_services(services_folder):
      """
          Load and initialize services from all subfolders.
  
          Args:
              services_folder: base folder to look for services in.
  
          Returns:
              Sorted list of audio services.
      """
      LOG.info("Loading services from " + services_folder)
      services = []
      possible_services = listdir(services_folder)
      for i in possible_services:
          location = join(services_folder, i)
          if (isdir(location) and
                  not MAINMODULE + ".py" in listdir(location)):
              for j in listdir(location):
                  name = join(location, j)
                  if (not isdir(name) or
                          not MAINMODULE + ".py" in listdir(name)):
                      continue
                  try:
                      services.append(create_service_descriptor(name))
                  except Exception:
                      LOG.error
  
  [... the rest is omitted ...]
files.new_path: mycroft/audio/audioservice.py
files.old_contents: # Copyright 2017 Mycroft AI Inc.
  #
  # Licensed under the Apache License, Version 2.0 (the "License");
  # you may not use this file except in compliance with the License.
  # You may obtain a copy of the License at
  #
  #    http://www.apache.org/licenses/LICENSE-2.0
  #
  # Unless required by applicable law or agreed to in writing, software
  # distributed under the License is distributed on an "AS IS" BASIS,
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  # See the License for the specific language governing permissions and
  # limitations under the License.
  
  import imp
  import sys
  import time
  from os import listdir
  from os.path import abspath, dirname, basename, isdir, join
  from threading import Lock
  
  from mycroft.configuration import Configuration
  from mycroft.messagebus.message import Message
  from mycroft.util.log import LOG
  
  try:
      import pulsectl
  except ImportError:
      pulsectl = None
  
  MAINMODULE = '__init__'
  sys.path.append(abspath(dirname(__file__)))
  
  
  def create_service_descriptor(service_folder):
      """Prepares a descriptor that can be used together with imp.
  
          Args:
              service_folder: folder that shall be imported.
  
          Returns:
              Dict with import information
      """
      info = imp.find_module(MAINMODULE, [service_folder])
      return {"name": basename(service_folder), "info": info}
  
  
  def get_services(services_folder):
      """
          Load and initialize services from all subfolders.
  
          Args:
              services_folder: base folder to look for services in.
  
          Returns:
              Sorted list of audio services.
      """
      LOG.info("Loading services from " + services_folder)
      services = []
      possible_services = listdir(services_folder)
      for i in possible_services:
          location = join(services_folder, i)
          if (isdir(location) and
                  not MAINMODULE + ".py" in listdir(location)):
              for j in listdir(location):
                  name = join(location, j)
                  if (not isdir(name) or
                          not MAINMODULE + ".py" in listdir(name)):
                      continue
                  try:
                      services.append(create_service_descriptor(name))
                  except Exception:
                      LOG.error
  
  [... the rest is omitted ...]
files.old_path: mycroft/audio/audioservice.py
files.new_contents: # Copyright 2017 Mycroft AI Inc.
  #
  # Licensed under the Apache License, Version 2.0 (the "License");
  # you may not use this file except in compliance with the License.
  # You may obtain a copy of the License at
  #
  #    http://www.apache.org/licenses/LICENSE-2.0
  #
  # Unless required by applicable law or agreed to in writing, software
  # distributed under the License is distributed on an "AS IS" BASIS,
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  # See the License for the specific language governing permissions and
  # limitations under the License.
  #
  from abc import ABCMeta, abstractmethod
  
  
  class AudioBackend:
      """
          Base class for all audio backend implementations.
  
          Args:
              config: configuration dict for the instance
              bus:    mycroft messagebus emitter
      """
      __metaclass__ = ABCMeta
  
      def __init__(self, config, bus):
          self._track_start_callback = None
          self.supports_mime_hints = False
  
      @abstractmethod
      def supported_uris(self):
          """
              Returns: list of supported uri types.
          """
          pass
  
      @abstractmethod
      def clear_list(self):
          """
              Clear playlist
          """
          pass
  
      @abstractmethod
      def add_list(self, tracks):
          """
              Add tracks to backend's playlist.
  
              Args:
                  tracks: list of tracks.
          """
          pass
  
      @abstractmethod
      def play(self, repeat=False):
          """
              Start playback.
  
              Args:
                  repeat: Repeat playlist, defaults to False
          """
          pass
  
      @abstractmethod
      def stop(self):
          """
              Stop playback.
  
              Returns: (bool) True if playback was stopped, otherwise False
          """
          pass
  
      def set_track_start_callback(self, callback_func):
          """
              Register callback on track start, should be called as each track
              in a playlist is started.
          """
          self._track_start_callback = callback_func
  
      def pause(self):
          """
              Pause playback.
          """
          pass
  
      def resume(self):
          """
              Resume paused playback.
          """
          pass
  
      def next(self):
          """
              Skip to next track in playlist.
          """
          pass
  
      def previous(self):
          """
              Skip to previous
  
  [... the rest is omitted ...]
files.new_path: mycroft/audio/services/__init__.py
files.old_contents: # Copyright 2017 Mycroft AI Inc.
  #
  # Licensed under the Apache License, Version 2.0 (the "License");
  # you may not use this file except in compliance with the License.
  # You may obtain a copy of the License at
  #
  #    http://www.apache.org/licenses/LICENSE-2.0
  #
  # Unless required by applicable law or agreed to in writing, software
  # distributed under the License is distributed on an "AS IS" BASIS,
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  # See the License for the specific language governing permissions and
  # limitations under the License.
  #
  from abc import ABCMeta, abstractmethod
  
  
  class AudioBackend:
      """
          Base class for all audio backend implementations.
  
          Args:
              config: configuration dict for the instance
              bus:    mycroft messagebus emitter
      """
      __metaclass__ = ABCMeta
  
      def __init__(self, config, bus):
          self._track_start_callback = None
          self.supports_mime_hints = False
  
      @abstractmethod
      def supported_uris(self):
          """
              Returns: list of supported uri types.
          """
          pass
  
      @abstractmethod
      def clear_list(self):
          """
              Clear playlist
          """
          pass
  
      @abstractmethod
      def add_list(self, tracks):
          """
              Add tracks to backend's playlist.
  
              Args:
                  tracks: list of tracks.
          """
          pass
  
      @abstractmethod
      def play(self, repeat=False):
          """
              Start playback.
  
              Args:
                  repeat: Repeat playlist, defaults to False
          """
          pass
  
      @abstractmethod
      def stop(self):
          """
              Stop playback.
  
              Returns: (bool) True if playback was stopped, otherwise False
          """
          pass
  
      def set_track_start_callback(self, callback_func):
          """
              Register callback on track start, should be called as each track
              in a playlist is started.
          """
          self._track_start_callback = callback_func
  
      def pause(self):
          """
              Pause playback.
          """
          pass
  
      def resume(self):
          """
              Resume paused playback.
          """
          pass
  
      def next(self):
          """
              Skip to next track in playlist.
          """
          pass
  
      def previous(self):
          """
              Skip to previous
  
  [... the rest is omitted ...]
files.old_path: mycroft/audio/services/__init__.py
files.new_contents: # Copyright 2017 Mycroft AI Inc.
  #
  # Licensed under the Apache License, Version 2.0 (the "License");
  # you may not use this file except in compliance with the License.
  # You may obtain a copy of the License at
  #
  #    http://www.apache.org/licenses/LICENSE-2.0
  #
  # Unless required by applicable law or agreed to in writing, software
  # distributed under the License is distributed on an "AS IS" BASIS,
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  # See the License for the specific language governing permissions and
  # limitations under the License.
  #
  import vlc
  
  from mycroft.audio.services import AudioBackend
  from mycroft.util.log import LOG
  
  
  class VlcService(AudioBackend):
      def __init__(self, config, bus=None, name='vlc'):
          super(VlcService, self).__init__(config, bus)
          self.instance = vlc.Instance()
          self.list_player = self.instance.media_list_player_new()
          self.player = self.instance.media_player_new()
          self.list_player.set_media_player(self.player)
          self.track_list = self.instance.media_list_new()
          self.list_player.set_media_list(self.track_list)
          self.vlc_events = self.player.event_manager()
          self.vlc_events.event_attach(vlc.EventType.MediaPlayerPlaying,
                                       self.track_start, 1)
          self.config = config
          self.bus = bus
          self.name = name
          self.normal_volume = None
          self.low_volume = self.config.get('low_volume', 30)
  
      def track_start(self, data, other):
          if self._track_start_callback:
              self._track_start_callback(self.track_info()['name'])
  
      def supported_uris(self):
          return ['file', 'http', 'https']
  
      def clear_list(self):
          # Create a new media list
          self.track_list = self.instance.media_list_new()
          # Set list as current track list
          self.list_player.set_media_list(self.track_list)
  
      def add_list(self, tracks):
          LOG.debug("Track list is " + str(tracks))
          for t in tracks:
              self.track_list.add_media(self.instance.media_new(t))
  
      def play(self,
  
  [... the rest is omitted ...]
files.new_path: mycroft/audio/services/vlc/__init__.py
files.old_contents: # Copyright 2017 Mycroft AI Inc.
  #
  # Licensed under the Apache License, Version 2.0 (the "License");
  # you may not use this file except in compliance with the License.
  # You may obtain a copy of the License at
  #
  #    http://www.apache.org/licenses/LICENSE-2.0
  #
  # Unless required by applicable law or agreed to in writing, software
  # distributed under the License is distributed on an "AS IS" BASIS,
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  # See the License for the specific language governing permissions and
  # limitations under the License.
  #
  import vlc
  
  from mycroft.audio.services import AudioBackend
  from mycroft.util.log import LOG
  
  
  class VlcService(AudioBackend):
      def __init__(self, config, bus=None, name='vlc'):
          super(VlcService, self).__init__(config, bus)
          self.instance = vlc.Instance()
          self.list_player = self.instance.media_list_player_new()
          self.player = self.instance.media_player_new()
          self.list_player.set_media_player(self.player)
          self.track_list = self.instance.media_list_new()
          self.list_player.set_media_list(self.track_list)
          self.vlc_events = self.player.event_manager()
          self.vlc_events.event_attach(vlc.EventType.MediaPlayerPlaying,
                                       self.track_start, 1)
          self.config = config
          self.bus = bus
          self.name = name
          self.normal_volume = None
          self.low_volume = self.config.get('low_volume', 30)
  
      def track_start(self, data, other):
          if self._track_start_callback:
              self._track_start_callback(self.track_info()['name'])
  
      def supported_uris(self):
          return ['file', 'http', 'https']
  
      def clear_list(self):
          # Create a new media list
          self.track_list = self.instance.media_list_new()
          # Set list as current track list
          self.list_player.set_media_list(self.track_list)
  
      def add_list(self, tracks):
          LOG.debug("Track list is " + str(tracks))
          for t in tracks:
              self.track_list.add_media(self.instance.media_new(t))
  
      def play(self,
  
  [... the rest is omitted ...]
files.old_path: mycroft/audio/services/vlc/__init__.py
files.new_contents: # Copyright 2017 Mycroft AI Inc.
  #
  # Licensed under the Apache License, Version 2.0 (the "License");
  # you may not use this file except in compliance with the License.
  # You may obtain a copy of the License at
  #
  #    http://www.apache.org/licenses/LICENSE-2.0
  #
  # Unless required by applicable law or agreed to in writing, software
  # distributed under the License is distributed on an "AS IS" BASIS,
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  # See the License for the specific language governing permissions and
  # limitations under the License.
  #
  import time
  from os.path import abspath
  
  from mycroft.messagebus.message import Message
  
  
  def ensure_uri(s):
      """
          Interprete paths as file:// uri's
  
          Args:
              s: string to be checked
  
          Returns:
              if s is uri, s is returned otherwise file:// is prepended
      """
      if isinstance(s, str):
          if '://' not in s:
              return 'file://' + abspath(s)
          else:
              return s
      elif isinstance(s, (tuple, list)):
          if '://' not in s[0]:
              return 'file://' + abspath(s[0]), s[1]
          else:
              return s
      else:
          raise ValueError('Invalid track')
  
  
  class AudioService:
      """
          AudioService class for interacting with the audio subsystem
  
          Arguments:
              bus: Mycroft messagebus connection
      """
  
      def __init__(self, bus):
          self.bus = bus
          self.bus.on('mycroft.audio.service.track_info_reply',
                      self._track_info)
          self.info = None
  
      def _track_info(self, message=None):
          """
              Handler for catching returning track info
          """
          self.info = message.data
  
      def queue(self, tracks=None):
          """ Queue up a track to playing playlist.
  
              Args:
                  tracks: track uri or list of track uri's
          """
          tracks = tracks or []
          if isinstance(tracks, str):
              tracks = [tracks]
          elif not isinstance(tracks, list):
              raise ValueError
          tracks = [ensure_uri(t) for t in tracks]
          self.bus.emit(Message('mycroft.audio.service.queue',
                                data
  
  [... the rest is omitted ...]
files.new_path: mycroft/skills/audioservice.py
files.old_contents: # Copyright 2017 Mycroft AI Inc.
  #
  # Licensed under the Apache License, Version 2.0 (the "License");
  # you may not use this file except in compliance with the License.
  # You may obtain a copy of the License at
  #
  #    http://www.apache.org/licenses/LICENSE-2.0
  #
  # Unless required by applicable law or agreed to in writing, software
  # distributed under the License is distributed on an "AS IS" BASIS,
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  # See the License for the specific language governing permissions and
  # limitations under the License.
  #
  import time
  from os.path import abspath
  
  from mycroft.messagebus.message import Message
  
  
  def ensure_uri(s):
      """
          Interprete paths as file:// uri's
  
          Args:
              s: string to be checked
  
          Returns:
              if s is uri, s is returned otherwise file:// is prepended
      """
      if isinstance(s, str):
          if '://' not in s:
              return 'file://' + abspath(s)
          else:
              return s
      elif isinstance(s, (tuple, list)):
          if '://' not in s[0]:
              return 'file://' + abspath(s[0]), s[1]
          else:
              return s
      else:
          raise ValueError('Invalid track')
  
  
  class AudioService:
      """
          AudioService class for interacting with the audio subsystem
  
          Arguments:
              bus: Mycroft messagebus connection
      """
  
      def __init__(self, bus):
          self.bus = bus
          self.bus.on('mycroft.audio.service.track_info_reply',
                      self._track_info)
          self.info = None
  
      def _track_info(self, message=None):
          """
              Handler for catching returning track info
          """
          self.info = message.data
  
      def queue(self, tracks=None):
          """ Queue up a track to playing playlist.
  
              Args:
                  tracks: track uri or list of track uri's
          """
          tracks = tracks or []
          if isinstance(tracks, str):
              tracks = [tracks]
          elif not isinstance(tracks, list):
              raise ValueError
          tracks = [ensure_uri(t) for t in tracks]
          self.bus.emit(Message('mycroft.audio.service.queue',
                                data
  
  [... the rest is omitted ...]
files.old_path: mycroft/skills/audioservice.py