Пример #1
0
 public void RemoveIndex(int indexIndex)
 {
     for (int i = indexIndex; i < m_Indices.Length - 1; i++)
     {
         m_Indices[i] = m_Indices[i + 1];
     }
     m_Indices = (Index[])CueSheet.ResizeArray(m_Indices, m_Indices.Length - 1);
 }
Пример #2
0
 public void AddComment(string comment)
 {
     if (comment.Trim() != "")
     {
         m_Comments = (string[])CueSheet.ResizeArray(m_Comments, m_Comments.Length + 1);
         m_Comments[m_Comments.Length - 1] = comment;
     }
 }
Пример #3
0
 public void AddGarbage(string garbage)
 {
     if (garbage.Trim() != "")
     {
         m_Garbage = (string[])CueSheet.ResizeArray(m_Garbage, m_Garbage.Length + 1);
         m_Garbage[m_Garbage.Length - 1] = garbage;
     }
 }
Пример #4
0
 public void AddFlag(Flags flag)
 {
     //if it's not a none tag
     //and if the tags hasn't already been added
     if (flag != Flags.NONE && NewFlag(flag) == true)
     {
         m_TrackFlags = (Flags[])CueSheet.ResizeArray(m_TrackFlags, m_TrackFlags.Length + 1);
         m_TrackFlags[m_TrackFlags.Length - 1] = flag;
     }
 }
Пример #5
0
        /// <summary>
        /// Cue file filter. Parse Cue sheet file,
        /// add cue fake track files for each one cue track,
        /// removes original single file ape flac wav and etc, from list
        /// </summary>
        /// <typeparam name="T">Type of obgects in fileList</typeparam>
        /// <param name="fileList">File list to be filtered</param>
        /// <param name="adaptor"></param>
        /// <returns></returns>
        public static IList <T> CUEFileListFilter <T>(IList <T> fileList, ICueTrackFileBuilder <T> builder)
        {
            if (fileList == null || fileList.Count == 0)
            {
                return(fileList);
            }

            List <string> exclusionList = new List <string>(2);
            List <T>      resultList    = new List <T>(fileList.Count);

            foreach (T fobj in fileList)
            {
                string fileName = builder.getFileName(fobj);
                if (CueUtil.isCueFile(fileName))
                {
                    exclusionList.Add(fileName);

                    CueSheet cueSheet = new CueSheet(fileName);
                    string   cuePath  = System.IO.Path.GetDirectoryName(fileName);

                    foreach (Track track in cueSheet.Tracks)
                    {
                        if (!exclusionList.Contains(cuePath + "\\" + track.DataFile.Filename))
                        {
                            exclusionList.Add(cuePath + "\\" + track.DataFile.Filename);
                        }
                        resultList.Add(builder.build(fileName, cueSheet, track));
                    }
                }
                else
                {
                    if (!isWavCueFile(fileName))
                    {
                        resultList.Add(fobj);
                    }
                }
            }

            if (exclusionList.Count > 0)
            {
                List <T> tmpList = new List <T>(resultList.Count);

                foreach (T fobj in resultList)
                {
                    if (!exclusionList.Contains(builder.getFileName(fobj)))
                    {
                        tmpList.Add(fobj);
                    }
                }

                resultList = tmpList;
            }

            return(resultList);
        }
        public GUIListItem build(string cueFileName, CueSheet cueSheet, Track track)
        {
            GUIListItem res = new GUIListItem();

            res.IsFolder = false;
            res.Path     = CueUtil.buildCueFakeTrackFileName(cueFileName, track);
            MediaPortal.Util.Utils.SetDefaultIcons(res);
            if (track.Performer != null && track.Performer != cueSheet.Performer)
            {
                res.Label = track.Performer + " - " + track.Title;
            }
            else
            {
                res.Label = track.Title;
            }

            res.Label = track.TrackNumber.ToString("00") + " " + res.Label;

            return(res);
        }
Пример #7
0
    /// <summary>
    /// Parse the Cue file. Return a Fake Cue track and adjest the playback position within the file.
    /// </summary>
    /// <param name="filePath"></param>
    /// <returns></returns>
    private bool HandleCueFile(ref string filePath, bool endOnly)
    {
      try
      {
        _cueTrackStartPos = 0;
        _cueTrackEndPos = 0;
        if (CueUtil.isCueFakeTrackFile(filePath))
        {
          Log.Debug("BASS: Playing CUE Track: {0}", filePath);
          _currentCueFakeTrackFileName = filePath;
          CueFakeTrack cueFakeTrack = CueUtil.parseCueFakeTrackFileName(filePath);
          if (!cueFakeTrack.CueFileName.Equals(_currentCueFileName))
          {
            // New CUE. Update chached cue.
            _currentCueSheet = new CueSheet(cueFakeTrack.CueFileName);
            _currentCueFileName = cueFakeTrack.CueFileName;
          }

          // Get track start position
          Track track = _currentCueSheet.Tracks[cueFakeTrack.TrackNumber - _currentCueSheet.Tracks[0].TrackNumber];
          Index index = track.Indices[0];
          _cueTrackStartPos = CueUtil.cueIndexToFloatTime(index);

          // If single audio file and is not last track, set track end position.
          if (_currentCueSheet.Tracks[_currentCueSheet.Tracks.Length - 1].TrackNumber > track.TrackNumber)
          {
            Track nextTrack =
              _currentCueSheet.Tracks[cueFakeTrack.TrackNumber - _currentCueSheet.Tracks[0].TrackNumber + 1];
            if (nextTrack.DataFile.Filename.Equals(track.DataFile.Filename))
            {
              Index nindex = nextTrack.Indices[0];
              _cueTrackEndPos = CueUtil.cueIndexToFloatTime(nindex);
            }
          }

          // If audio file is not changed, just set new start/end position and reset pause
          string audioFilePath = System.IO.Path.GetDirectoryName(cueFakeTrack.CueFileName) +
                                 System.IO.Path.DirectorySeparatorChar + track.DataFile.Filename;
          if (audioFilePath.CompareTo(_filePath) == 0 /* && StreamIsPlaying(stream)*/)
          {
            SetCueTrackEndPosition(GetCurrentStream(), endOnly);
            return true;
          }
          filePath = audioFilePath;
        }
        else
        {
          _currentCueFileName = null;
          _currentCueSheet = null;
        }
      }
      catch (System.IO.FileNotFoundException)
      {
        // The CUE File may have been moved
        Log.Error("BASS: Cue File cannot be found at the expected location. aborting playback.");
      }
      return false;
    }
Пример #8
0
    /// <summary>
    /// Scan the folders in the selected shares for music files to be added to the database
    /// </summary>
    private void AddUpdateFiles()
    {
      DatabaseReorgEventArgs MyArgs = new DatabaseReorgEventArgs();
      string strSQL;

      _processCount = 0;
      _songsAdded = 0;
      _songsUpdated = 0;
      _songsSkipped = 0;

      int allFilesCount = 0;

      foreach (string Share in _shares)
      {
        //dummy call to stop lots of watchers being created unnecessarily
        Util.Utils.FileExistsInCache(Path.Combine(Share, "folder.jpg"));
        // Get all the files for the given Share / Path
        try
        {
          foreach (FileInformation file in GetFilesRecursive(new DirectoryInfo(Share)))
          {
            allFilesCount++;

            if (allFilesCount % 1000 == 0)
            {
              Log.Info("MusicDBReorg: Procesing file {0}", allFilesCount);
            }

            MyArgs.progress = 4;
            MyArgs.phase = String.Format("Processing file {0}", allFilesCount);
            OnDatabaseReorgChanged(MyArgs);

            if (!CheckFileForInclusion(file))
            {
              continue;
            }

            _processCount++;

            AddUpdateSong(file.Name);
          }
        }
        catch (Exception ex)
        {
          Log.Error("MusicDBReorg: Exception accessing file or folder: {0}", ex.Message);
        }
      }

      // Now we will remove the CUE data file from the database, since we will add Fake Tracks in the next step
      foreach (string cueFile in cueFiles)
      {
        try
        {
          CueSheet cueSheet = new CueSheet(cueFile);
          string cuePath = Path.GetDirectoryName(cueFile);
          string cueDataFile = cuePath + "\\" + cueSheet.Tracks[0].DataFile.Filename;
          DatabaseUtility.RemoveInvalidChars(ref cueDataFile);
          strSQL = String.Format("delete from tracks where strPath='{0}'", cueDataFile);
          try
          {
            DirectExecute(strSQL);
          }
          catch (Exception ex)
          {
            Log.Error("Error deleting song from Database: {0}", ex.Message);
          }
        }
        catch (Exception ex)
        {
          Log.Error("Exception Processing CUE File: {0}: {1}", cueFile, ex.Message);
        }
      }

      try
      {
        // Apply CUE Filter
        List<string> cueFileFakeTracks = new List<string>();
        cueFileFakeTracks =
          (List<string>)CueUtil.CUEFileListFilterList<string>(cueFiles, CueUtil.CUE_TRACK_FILE_STRING_BUILDER);

        // and add them also to the Hashtable, so that they don't get deleted in the next step
        foreach (string song in cueFileFakeTracks)
        {
          _processCount++;
          AddUpdateSong(song);
          allFiles.Add(song, false);
        }
      }
      catch (Exception ex)
      {
        Log.Error("Error processing CUE files: {0}", ex.Message);
      }

      _resetEvent.Set();
    }
Пример #9
0
    /// <summary>
    /// Starts Playback of the given file
    /// </summary>
    /// <param name="filePath"></param>
    /// <returns></returns>
    public override bool Play(string filePath)
    {
      if (!_Initialized)
      {
        return false;
      }

      int stream = GetCurrentStream();

      bool doFade = false;
      bool result = true;
      Speed = 1; // Set playback Speed to normal speed

      try
      {
        if (filePath.ToLower().CompareTo(FilePath.ToLower()) == 0 && stream != 0)
        {
          // Selected file is equal to current stream
          if (_State == PlayState.Paused)
          {
            // Resume paused stream
            if (_SoftStop)
            {
              Bass.BASS_ChannelSlideAttribute(stream, BASSAttribute.BASS_ATTRIB_VOL, 1, 500);
            }
            else
            {
              Bass.BASS_ChannelSetAttribute(stream, BASSAttribute.BASS_ATTRIB_VOL, 1);
            }

            result = Bass.BASS_Start();

            if (_useASIO)
            {
              result = BassAsio.BASS_ASIO_Start(0);
            }

            if (result)
            {
              _State = PlayState.Playing;

              if (PlaybackStateChanged != null)
              {
                PlaybackStateChanged(this, PlayState.Paused, _State);
              }
            }

            return result;
          }
        }
        else
        {
          // Cue support
          cueTrackStartPos = 0;
          cueTrackEndPos = 0;
          if (CueUtil.isCueFakeTrackFile(filePath))
          {
            Log.Debug("BASS: Playing CUE Track: {0}", filePath);
            currentCueFakeTrackFileName = filePath;
            CueFakeTrack cueFakeTrack = CueUtil.parseCueFakeTrackFileName(filePath);
            if (!cueFakeTrack.CueFileName.Equals(currentCueFileName))
            {
              // New CUE. Update chached cue.
              currentCueSheet = new CueSheet(cueFakeTrack.CueFileName);
              currentCueFileName = cueFakeTrack.CueFileName;
            }

            // Get track start position
            Track track = currentCueSheet.Tracks[cueFakeTrack.TrackNumber - currentCueSheet.Tracks[0].TrackNumber];
            Index index = track.Indices[0];
            cueTrackStartPos = CueUtil.cueIndexToFloatTime(index);

            // If single audio file and is not last track, set track end position.
            if (currentCueSheet.Tracks[currentCueSheet.Tracks.Length - 1].TrackNumber > track.TrackNumber)
            {
              Track nextTrack =
                currentCueSheet.Tracks[cueFakeTrack.TrackNumber - currentCueSheet.Tracks[0].TrackNumber + 1];
              if (nextTrack.DataFile.Filename.Equals(track.DataFile.Filename))
              {
                Index nindex = nextTrack.Indices[0];
                cueTrackEndPos = CueUtil.cueIndexToFloatTime(nindex);
              }
            }

            // If audio file is not changed, just set new start/end position and reset pause
            string audioFilePath = System.IO.Path.GetDirectoryName(cueFakeTrack.CueFileName) +
                                   System.IO.Path.DirectorySeparatorChar + track.DataFile.Filename;
            if (audioFilePath.CompareTo(FilePath) == 0 /* && StreamIsPlaying(stream)*/)
            {
              setCueTrackEndPosition(stream);
              return true;
            }
            filePath = audioFilePath;
          }
          else
          {
            currentCueFileName = null;
            currentCueSheet = null;
          }
        }

        if (stream != 0 && StreamIsPlaying(stream))
        {
          int oldStream = stream;
          double oldStreamDuration = GetTotalStreamSeconds(oldStream);
          double oldStreamElapsedSeconds = GetStreamElapsedTime(oldStream);
          double crossFadeSeconds = (double)_CrossFadeIntervalMS;

          if (crossFadeSeconds > 0)
            crossFadeSeconds = crossFadeSeconds / 1000.0;

          if ((oldStreamDuration - (oldStreamElapsedSeconds + crossFadeSeconds) > -1))
          {
            FadeOutStop(oldStream);
          }
          else
          {
            Bass.BASS_ChannelStop(oldStream);
          }

          doFade = true;
          stream = GetNextStream();

          if (stream != 0 || StreamIsPlaying(stream))
          {
            FreeStream(stream);
          }
        }

        if (stream != 0)
        {
          if (!Stopped) // Check if stopped already to avoid that Stop() is called two or three times
          {
            Stop();
          }
          FreeStream(stream);
        }

        _State = PlayState.Init;

        // Make sure Bass is ready to begin playing again
        Bass.BASS_Start();

        float crossOverSeconds = 0;

        if (_CrossFadeIntervalMS > 0)
        {
          crossOverSeconds = (float)_CrossFadeIntervalMS / 1000f;
        }

        if (filePath != string.Empty)
        {
          // Turn on parsing of ASX files
          Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_NET_PLAYLIST, 2);

          // We need different flags for standard BASS and ASIO / Mixing
          BASSFlag streamFlags;
          if (_useASIO || _Mixing)
          {
            streamFlags = BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT;
            // Don't use the BASS_STREAM_AUTOFREE flag on a decoding channel. will produce a BASS_ERROR_NOTAVAIL
          }
          else
          {
            streamFlags = BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_STREAM_AUTOFREE;
          }

          FilePath = filePath;

          // create the stream
          _isCDDAFile = false;
          _isRadio = false;
          _isLastFMRadio = false;
          if (Util.Utils.IsCDDA(filePath))
          {
            _isCDDAFile = true;

            // StreamCreateFile causes problems with Multisession disks, so use StreamCreate with driveindex and track index
            int driveindex = _cdDriveLetters.IndexOf(filePath.Substring(0, 1));
            int tracknum = Convert.ToInt16(filePath.Substring(filePath.IndexOf(".cda") - 2, 2));
            stream = BassCd.BASS_CD_StreamCreate(driveindex, tracknum - 1, streamFlags);
            if (stream == 0)
              Log.Error("BASS: CD: {0}.", Enum.GetName(typeof (BASSError), Bass.BASS_ErrorGetCode()));
          }
          else if (filePath.ToLower().Contains(@"http://") || filePath.ToLower().Contains(@"https://") ||
                   filePath.ToLower().StartsWith("mms") || filePath.ToLower().StartsWith("rtsp"))
          {
            // We're playing Internet Radio Stream
            _isLastFMRadio = Util.Utils.IsLastFMStream(filePath);
            if (!_isLastFMRadio)
            {
              // We're playing Internet Radio Stream, but not LastFM
              _isRadio = true;
            }

            stream = Bass.BASS_StreamCreateURL(filePath, 0, streamFlags, null, IntPtr.Zero);

            if (stream != 0)
            {
              // Get the Tags and set the Meta Tag SyncProc
              _tagInfo = new TAG_INFO(filePath);
              SetStreamTags(stream);

              if (BassTags.BASS_TAG_GetFromURL(stream, _tagInfo))
              {
                GetMetaTags();
              }

              Bass.BASS_ChannelSetSync(stream, BASSSync.BASS_SYNC_META, 0, MetaTagSyncProcDelegate, IntPtr.Zero);
            }
            Log.Debug("BASSAudio: Webstream found - trying to fetch stream {0}", Convert.ToString(stream));
          }
          else if (IsMODFile(filePath))
          {
            // Load a Mod file
            stream = Bass.BASS_MusicLoad(filePath, 0, 0,
                                         BASSFlag.BASS_SAMPLE_SOFTWARE | BASSFlag.BASS_SAMPLE_FLOAT |
                                         BASSFlag.BASS_MUSIC_AUTOFREE | BASSFlag.BASS_MUSIC_PRESCAN |
                                         BASSFlag.BASS_MUSIC_RAMP, 0);
          }
          else
          {
            // Create a Standard Stream
            stream = Bass.BASS_StreamCreateFile(filePath, 0, 0, streamFlags);
          }

          // Is Mixing / ASIO enabled, then we create a mixer channel and assign the stream to the mixer
          if ((_Mixing || _useASIO) && stream != 0)
          {
            // Do an upmix of the stereo according to the matrix.
            // Now Plugin the stream to the mixer and set the mixing matrix
            BassMix.BASS_Mixer_StreamAddChannel(_mixer, stream,
                                                BASSFlag.BASS_MIXER_MATRIX | BASSFlag.BASS_STREAM_AUTOFREE |
                                                BASSFlag.BASS_MIXER_NORAMPIN | BASSFlag.BASS_MIXER_BUFFER);
            BassMix.BASS_Mixer_ChannelSetMatrix(stream, _MixingMatrix);
          }

          Streams[CurrentStreamIndex] = stream;

          if (stream != 0)
          {
            // When we have a MIDI file, we need to assign the sound banks to the stream
            if (IsMidiFile(filePath) && soundFonts != null)
            {
              BassMidi.BASS_MIDI_StreamSetFonts(stream, soundFonts, soundFonts.Length);
            }

            StreamEventSyncHandles[CurrentStreamIndex] = RegisterPlaybackEvents(stream, CurrentStreamIndex);

            if (doFade && CrossFadeIntervalMS > 0)
            {
              _CrossFading = true;
              // Reduce the stream volume to zero so we can fade it in...
              Bass.BASS_ChannelSetAttribute(stream, BASSAttribute.BASS_ATTRIB_VOL, 0);

              // Fade in from 0 to 1 over the _CrossFadeIntervalMS duration
              Bass.BASS_ChannelSlideAttribute(stream, BASSAttribute.BASS_ATTRIB_VOL, 1, _CrossFadeIntervalMS);
            }

            // Attach active DSP effects to the Stream
            if (_dspActive)
            {
              // BASS effects
              if (_gain != null)
              {
                _gain.ChannelHandle = stream;
                _gain.Start();
              }
              if (_damp != null)
              {
                int dampHandle = Bass.BASS_ChannelSetFX(stream, BASSFXType.BASS_FX_BFX_DAMP, _dampPrio);
                Bass.BASS_FXSetParameters(dampHandle, _damp);
              }
              if (_comp != null)
              {
                int compHandle = Bass.BASS_ChannelSetFX(stream, BASSFXType.BASS_FX_BFX_COMPRESSOR, _compPrio);
                Bass.BASS_FXSetParameters(compHandle, _comp);
              }

              // VST Plugins
              foreach (string plugin in _VSTPlugins)
              {
                int vstHandle = BassVst.BASS_VST_ChannelSetDSP(stream, plugin, BASSVSTDsp.BASS_VST_DEFAULT, 1);
                // Copy the parameters of the plugin as loaded on from the settings
                int vstParm = _vstHandles[plugin];
                BassVst.BASS_VST_SetParamCopyParams(vstParm, vstHandle);
              }

              // Init Winamp DSP only if we got a winamp plugin actiavtes
              int waDspPlugin = 0;
              if (DSP.Settings.Instance.WinAmpPlugins.Count > 0 && !_waDspInitialised)
              {
                BassWaDsp.BASS_WADSP_Init(GUIGraphicsContext.ActiveForm);
                _waDspInitialised = true;
                foreach (WinAmpPlugin plugins in DSP.Settings.Instance.WinAmpPlugins)
                {
                  waDspPlugin = BassWaDsp.BASS_WADSP_Load(plugins.PluginDll, 5, 5, 100, 100, null);
                  if (waDspPlugin > 0)
                  {
                    _waDspPlugins[plugins.PluginDll] = waDspPlugin;
                    BassWaDsp.BASS_WADSP_Start(waDspPlugin, 0, 0);
                  }
                  else
                  {
                    Log.Debug("Couldn't load WinAmp Plugin {0}. Error code: {1}", plugins.PluginDll,
                              Enum.GetName(typeof (BASSError), Bass.BASS_ErrorGetCode()));
                  }
                }
              }

              foreach (int waPluginHandle in _waDspPlugins.Values)
              {
                BassWaDsp.BASS_WADSP_ChannelSetDSP(waPluginHandle, stream, 1);
              }
            }
          }
          else
          {
            Log.Error("BASS: Unable to create Stream for {0}.  Reason: {1}.", filePath,
                      Enum.GetName(typeof (BASSError), Bass.BASS_ErrorGetCode()));
          }

          bool playbackStarted = false;
          if (_Mixing)
          {
            if (Bass.BASS_ChannelIsActive(_mixer) == BASSActive.BASS_ACTIVE_PLAYING)
            {
              setCueTrackEndPosition(stream);
              playbackStarted = true;
            }
            else
            {
              playbackStarted = Bass.BASS_ChannelPlay(_mixer, false);
              setCueTrackEndPosition(stream);
            }
          }
          else if (_useASIO)
          {
            // Get some information about the stream
            BASS_CHANNELINFO info = new BASS_CHANNELINFO();
            Bass.BASS_ChannelGetInfo(stream, info);

            // In order to provide data for visualisation we need to clone the stream
            _streamcopy = new StreamCopy();
            _streamcopy.ChannelHandle = stream;
            _streamcopy.StreamFlags = BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT;
            // decode the channel, so that we have a Streamcopy

            _asioHandler.Pan = _asioBalance;
            _asioHandler.Volume = (float)_StreamVolume / 100f;

            // Set the Sample Rate from the stream
            _asioHandler.SampleRate = (double)info.freq;
            // try to set the device rate too (saves resampling)
            BassAsio.BASS_ASIO_SetRate((double)info.freq);

            try
            {
              _streamcopy.Start(); // start the cloned stream
            }
            catch (Exception)
            {
              Log.Error("Captured an error on StreamCopy start");
            }

            if (BassAsio.BASS_ASIO_IsStarted())
            {
              setCueTrackEndPosition(stream);
              playbackStarted = true;
            }
            else
            {
              BassAsio.BASS_ASIO_Stop();
              playbackStarted = BassAsio.BASS_ASIO_Start(0);
              setCueTrackEndPosition(stream);
            }
          }
          else
          {
            setCueTrackEndPosition(stream);
            playbackStarted = Bass.BASS_ChannelPlay(stream, false);
          }

          if (stream != 0 && playbackStarted)
          {
            Log.Info("BASS: playback started");

            GUIMessage msg = new GUIMessage(GUIMessage.MessageType.GUI_MSG_PLAYBACK_STARTED, 0, 0, 0, 0, 0, null);
            msg.Label = FilePath;
            GUIWindowManager.SendThreadMessage(msg);
            NotifyPlaying = true;

            NeedUpdate = true;
            _IsFullScreen = GUIGraphicsContext.IsFullScreenVideo;
            _VideoPositionX = GUIGraphicsContext.VideoWindow.Left;
            _VideoPositionY = GUIGraphicsContext.VideoWindow.Top;
            _VideoWidth = GUIGraphicsContext.VideoWindow.Width;
            _VideoHeight = GUIGraphicsContext.VideoWindow.Height;

            // Re-Add the Viswindow to the Mainform Control (It got removed on a manual Stop)
            SetVisualizationWindow();
            SetVideoWindow();

            PlayState oldState = _State;
            _State = PlayState.Playing;

            if (oldState != _State && PlaybackStateChanged != null)
            {
              PlaybackStateChanged(this, oldState, _State);
            }

            if (PlaybackStart != null)
            {
              PlaybackStart(this, GetTotalStreamSeconds(stream));
            }
          }

          else
          {
            Log.Error("BASS: Unable to play {0}.  Reason: {1}.", filePath,
                      Enum.GetName(typeof (BASSError), Bass.BASS_ErrorGetCode()));

            // Release all of the sync proc handles
            if (StreamEventSyncHandles[CurrentStreamIndex] != null)
            {
              UnregisterPlaybackEvents(stream, StreamEventSyncHandles[CurrentStreamIndex]);
            }

            result = false;
          }
        }
      }
      catch (Exception ex)
      {
        result = false;
        Log.Error("BASS: Play caused an exception:  {0}.", ex);
      }

      return result;
    }
Пример #10
0
        /// <summary>
        /// Read MusicTag information from cueFakeTrack
        /// Not thread safe!
        /// </summary>
        /// <param name="cueFakeTrackFileName">Cue fake track file name</param>
        /// <returns>MusicTag filled with cue track information</returns>
        public static MusicTag CueFakeTrackFile2MusicTag(string cueFakeTrackFileName)
        {
            lock (cacheLock)
            {
                // This metod called twice for each one file. So, cache data!
                if (cueFakeTrackFileName == cueFakeTrackFileNameCache)
                {
                    return(musicTagCache);
                }
                cueFakeTrackFileNameCache = cueFakeTrackFileName;

                // Cache CueSheet to pervent parsing it for each track in the album
                CueFakeTrack cueFakeTrack = parseCueFakeTrackFileName(cueFakeTrackFileName);
                if (cueSheetCacheFileNameCache != cueFakeTrack.CueFileName)
                {
                    cueSheetCache = new CueSheet(cueFakeTrack.CueFileName);
                    cueSheetCacheFileNameCache = cueFakeTrack.CueFileName;
                }

                int   trackPosition = cueFakeTrack.TrackNumber - cueSheetCache.Tracks[0].TrackNumber;
                Track track         = cueSheetCache.Tracks[trackPosition];

                musicTagCache = new MusicTag();
                if (track.TrackNumber < cueSheetCache.Tracks[cueSheetCache.Tracks.Length - 1].TrackNumber)
                {
                    Track nextTrack = cueSheetCache.Tracks[trackPosition + 1];
                    musicTagCache.Duration = cueIndexToIntTime(nextTrack.Indices[0]) - cueIndexToIntTime(track.Indices[0]);
                }

                string fname = Path.Combine(Path.GetDirectoryName(cueFakeTrack.CueFileName), track.DataFile.Filename);

                try
                {
                    if (fname != cacheFName)
                    {
                        tagCache = TagLib.File.Create(fname);
                    }
                    cacheFName = fname;

                    musicTagCache.FileType  = tagCache.MimeType;
                    musicTagCache.Year      = (int)tagCache.Tag.Year;
                    musicTagCache.BitRate   = tagCache.Properties.AudioBitrate;
                    musicTagCache.DiscID    = (int)tagCache.Tag.Disc;
                    musicTagCache.DiscTotal = (int)tagCache.Tag.DiscCount;
                    ;

                    if (musicTagCache.Duration == 0)
                    {
                        musicTagCache.Duration = (int)tagCache.Properties.Duration.TotalSeconds -
                                                 cueIndexToIntTime(track.Indices[0]);
                    }
                }
                catch (Exception ex)
                {
                    Log.Warn("CueFakeTrackFile2MusicTag: Exception reading file {0}. {1}", fname, ex.Message);
                }

                // In case of having a multi file Cue sheet, we're not able to get the duration
                // from the index entries. use MediaInfo then
                if (musicTagCache.Duration == 0)
                {
                    try
                    {
                        MediaInfo mi = new MediaInfo();
                        mi.Open(fname);
                        int durationms = 0;
                        int.TryParse(mi.Get(StreamKind.General, 0, "Duration"), out durationms);
                        musicTagCache.Duration = durationms / 1000;
                        mi.Close();
                    }
                    catch (Exception ex1)
                    {
                        Log.Warn("CueFakeTrackFile2MusicTag: Exception retrieving duration for file {0}. {1}", fname, ex1.Message);
                    }
                }

                if (string.IsNullOrEmpty(musicTagCache.Artist))
                {
                    // if track has a performer set use this value for artist tag
                    // else use global performer defined for cue sheet
                    if (!string.IsNullOrEmpty(track.Performer))
                    {
                        musicTagCache.Artist = track.Performer;
                    }
                    else
                    {
                        musicTagCache.Artist = cueSheetCache.Performer;
                    }
                }

                if (string.IsNullOrEmpty(musicTagCache.Album))
                {
                    musicTagCache.Album = cueSheetCache.Title;
                }

                if (string.IsNullOrEmpty(musicTagCache.AlbumArtist))
                {
                    if (!string.IsNullOrEmpty(cueSheetCache.Performer))
                    {
                        musicTagCache.AlbumArtist    = cueSheetCache.Performer;
                        musicTagCache.HasAlbumArtist = true;
                    }
                    else
                    {
                        musicTagCache.HasAlbumArtist = false;
                    }
                }

                // let tagged genre override cuesheet genre
                if (string.IsNullOrEmpty(musicTagCache.Genre) &&
                    !string.IsNullOrEmpty(cueSheetCache.Genre))
                {
                    musicTagCache.Genre = cueSheetCache.Genre;
                }

                // let tagged year override cuesheet year
                if (musicTagCache.Year == 0 && cueSheetCache.Year != 0)
                {
                    musicTagCache.Year = cueSheetCache.Year;
                }

                // let tagged composer override cuesheet songwriter
                if (string.IsNullOrEmpty(musicTagCache.Composer) &&
                    !string.IsNullOrEmpty(cueSheetCache.Songwriter))
                {
                    musicTagCache.Composer = cueSheetCache.Songwriter;
                }


                //musicTagCache.CoverArtImageBytes = pics[0].Data.Data;
                musicTagCache.FileName   = cueFakeTrackFileName;
                musicTagCache.Title      = track.Title;
                musicTagCache.Track      = track.TrackNumber;
                musicTagCache.TrackTotal = cueSheetCache.Tracks.Length;

                return(musicTagCache);
            }
        }
Пример #11
0
        public void AddIndex(int number, int minutes, int seconds, int frames)
        {
            m_Indices = (Index[])CueSheet.ResizeArray(m_Indices, m_Indices.Length + 1);

            m_Indices[m_Indices.Length - 1] = new Index(number, minutes, seconds, frames);
        }
Пример #12
0
        /// <summary>
        /// Read MusicTag information from cueFakeTrack
        /// Not thread safe!
        /// </summary>
        /// <param name="cueFakeTrackFileName">Cue fake track file name</param>
        /// <returns>MusicTag filled with cue track information</returns>
        public static MusicTag CueFakeTrackFile2MusicTag(string cueFakeTrackFileName)
        {
            lock (cacheLock)
            {
                // This metod called twice for each single file. So, cache data!
                if (cueFakeTrackFileName == cueFakeTrackFileNameCache)
                {
                    return(musicTagCache);
                }
                cueFakeTrackFileNameCache = cueFakeTrackFileName;

                // Cache CueSheet to pervent parsing it for each track in the album
                CueFakeTrack cueFakeTrack = parseCueFakeTrackFileName(cueFakeTrackFileName);
                if (cueSheetCacheFileNameCache != cueFakeTrack.CueFileName)
                {
                    cueSheetCache = new CueSheet(cueFakeTrack.CueFileName);
                    cueSheetCacheFileNameCache = cueFakeTrack.CueFileName;
                }

                int   trackPosition = cueFakeTrack.TrackNumber - cueSheetCache.Tracks[0].TrackNumber;
                Track track         = cueSheetCache.Tracks[trackPosition];

                musicTagCache = new MusicTag();
                if (track.TrackNumber < cueSheetCache.Tracks[cueSheetCache.Tracks.Length - 1].TrackNumber)
                {
                    Track nextTrack = cueSheetCache.Tracks[trackPosition + 1];
                    musicTagCache.Duration = cueIndexToIntTime(nextTrack.Indices[0]) - cueIndexToIntTime(track.Indices[0]);
                }

                string fname = Path.Combine(Path.GetDirectoryName(cueFakeTrack.CueFileName), track.DataFile.Filename);

                try
                {
                    if (fname != cacheFName)
                    {
                        TagLib.File file = TagLib.File.Create(fname);
                        tagCache = new TagCache();
                        tagCache.CopyTags(file);
                    }
                    cacheFName = fname;

                    musicTagCache.FileType    = tagCache.FileType;
                    musicTagCache.Codec       = tagCache.Codec;
                    musicTagCache.Year        = tagCache.Year;
                    musicTagCache.BitRate     = tagCache.BitRate;
                    musicTagCache.DiscID      = tagCache.DiscId;
                    musicTagCache.DiscTotal   = tagCache.DiscTotal;
                    musicTagCache.Channels    = tagCache.Channels;
                    musicTagCache.SampleRate  = tagCache.SampleRate;
                    musicTagCache.BitRateMode = tagCache.BitRateMode;

                    if (musicTagCache.Duration == 0)
                    {
                        musicTagCache.Duration = tagCache.Duration - cueIndexToIntTime(track.Indices[0]);
                    }
                }
                catch (Exception)
                {
                    // If we end up here this means that we were not able to read the file
                    // Most probably because of taglib-sharp not supporting the audio file
                    // For example DTS file format has no Tags, but can be replayed by BASS
                    // Use MediaInfo to read the properties
                    if (fname != cacheFName)
                    {
                        tagCache = new TagCache();
                        if (tagCache.CopyMediaInfo(fname))
                        {
                            musicTagCache.FileType    = tagCache.FileType;
                            musicTagCache.Codec       = tagCache.Codec;
                            musicTagCache.BitRate     = tagCache.BitRate;
                            musicTagCache.Channels    = tagCache.Channels;
                            musicTagCache.SampleRate  = tagCache.SampleRate;
                            musicTagCache.BitRateMode = tagCache.BitRateMode;

                            if (musicTagCache.Duration == 0)
                            {
                                musicTagCache.Duration = tagCache.Duration - cueIndexToIntTime(track.Indices[0]);
                            }
                        }
                    }
                    cacheFName = fname;
                }

                // In case of having a multi file Cue sheet, we're not able to get the duration
                // from the index entries. use MediaInfo then
                if (musicTagCache.Duration == 0)
                {
                    try
                    {
                        var logger = GlobalServiceProvider.Get <MediaInfo.ILogger>();
                        var mi     = new MediaInfoWrapper(fname, logger);
                        if (!mi.MediaInfoNotloaded)
                        {
                            mi.WriteInfo();
                            musicTagCache.Duration = (int?)mi.BestAudioStream?.Duration.TotalSeconds ?? 0;
                        }
                    }
                    catch (Exception ex1)
                    {
                        Log.Warn("CueFakeTrackFile2MusicTag: Exception retrieving duration for file {0}. {1}", fname, ex1.Message);
                    }
                }

                if (string.IsNullOrEmpty(musicTagCache.Artist))
                {
                    // if track has a performer set use this value for artist tag
                    // else use global performer defined for cue sheet
                    if (!string.IsNullOrEmpty(track.Performer))
                    {
                        musicTagCache.Artist = track.Performer;
                    }
                    else
                    {
                        musicTagCache.Artist = cueSheetCache.Performer;
                    }
                }

                if (string.IsNullOrEmpty(musicTagCache.Album))
                {
                    musicTagCache.Album = cueSheetCache.Title;
                }

                if (string.IsNullOrEmpty(musicTagCache.AlbumArtist))
                {
                    if (!string.IsNullOrEmpty(cueSheetCache.Performer))
                    {
                        musicTagCache.AlbumArtist    = cueSheetCache.Performer;
                        musicTagCache.HasAlbumArtist = true;
                    }
                    else
                    {
                        musicTagCache.HasAlbumArtist = false;
                    }
                }

                // let tagged genre override cuesheet genre
                if (string.IsNullOrEmpty(musicTagCache.Genre) &&
                    !string.IsNullOrEmpty(cueSheetCache.Genre))
                {
                    musicTagCache.Genre = cueSheetCache.Genre;
                }

                // let tagged year override cuesheet year
                if (musicTagCache.Year == 0 && cueSheetCache.Year != 0)
                {
                    musicTagCache.Year = cueSheetCache.Year;
                }

                // let tagged composer override cuesheet songwriter
                if (string.IsNullOrEmpty(musicTagCache.Composer) &&
                    !string.IsNullOrEmpty(cueSheetCache.Songwriter))
                {
                    musicTagCache.Composer = cueSheetCache.Songwriter;
                }

                // in case we were not able to read the file type via taglib, we will get it vai extension
                if (string.IsNullOrEmpty(musicTagCache.FileType))
                {
                    var extension = Path.GetExtension(fname);
                    if (extension != null)
                    {
                        musicTagCache.FileType = extension.Substring(1).ToLowerInvariant();
                    }
                }

                musicTagCache.FileName   = cueFakeTrackFileName;
                musicTagCache.Title      = track.Title;
                musicTagCache.Track      = track.TrackNumber;
                musicTagCache.TrackTotal = cueSheetCache.Tracks.Length;

                return(musicTagCache);
            }
        }
 public string build(string cueFileName, CueSheet cueSheet, Track track)
 {
     return(CueUtil.buildCueFakeTrackFileName(cueFileName, track));
 }