2 * Copyright (C) 2012-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
21 #include "CDDARipJob.h"
22 #ifdef HAVE_LIBMP3LAME
23 #include "EncoderLame.h"
25 #ifdef HAVE_LIBVORBISENC
26 #include "EncoderVorbis.h"
28 #include "EncoderWav.h"
29 #include "EncoderFFmpeg.h"
30 #include "EncoderFlac.h"
32 #include "utils/log.h"
34 #include "dialogs/GUIDialogExtendedProgressBar.h"
35 #include "filesystem/File.h"
36 #include "filesystem/SpecialProtocol.h"
37 #include "guilib/GUIWindowManager.h"
38 #include "guilib/LocalizeStrings.h"
39 #include "settings/AdvancedSettings.h"
40 #include "utils/StringUtils.h"
41 #include "storage/MediaManager.h"
43 using namespace MUSIC_INFO;
44 using namespace XFILE;
46 CCDDARipJob::CCDDARipJob(const CStdString& input,
47 const CStdString& output,
48 const CMusicInfoTag& tag,
52 unsigned int channels, unsigned int bps) :
53 m_rate(rate), m_channels(channels), m_bps(bps), m_tag(tag),
54 m_input(input), m_output(CUtil::MakeLegalPath(output)), m_eject(eject),
59 CCDDARipJob::~CCDDARipJob()
63 bool CCDDARipJob::DoWork()
65 CLog::Log(LOGINFO, "Start ripping track %s to %s", m_input.c_str(),
68 // if we are ripping to a samba share, rip it to hd first and then copy it it the share
69 CFileItem file(m_output, false);
71 m_output = SetupTempFile();
73 if (m_output.IsEmpty())
75 CLog::Log(LOGERROR, "CCDDARipper: Error opening file");
82 if (!reader.Open(m_input,READ_CACHED) || !(encoder=SetupEncoder(reader)))
84 CLog::Log(LOGERROR, "Error: CCDDARipper::Init failed");
88 // setup the progress dialog
89 CGUIDialogExtendedProgressBar* pDlgProgress =
90 (CGUIDialogExtendedProgressBar*)g_windowManager.GetWindow(WINDOW_DIALOG_EXT_PROGRESS);
91 CGUIDialogProgressBarHandle* handle = pDlgProgress->GetHandle(g_localizeStrings.Get(605));
93 int iTrack = atoi(m_input.substr(13, m_input.size() - 13 - 5).c_str());
94 strLine0.Format("%02i. %s - %s", iTrack,
95 StringUtils::Join(m_tag.GetArtist(),
96 g_advancedSettings.m_musicItemSeparator).c_str(),
97 m_tag.GetTitle().c_str());
98 handle->SetText(strLine0);
103 bool cancelled(false);
105 while (!cancelled && (result=RipChunk(reader, encoder, percent)) == 0)
107 cancelled = ShouldCancel(percent,100);
108 if (percent > oldpercent)
110 oldpercent = percent;
111 handle->SetPercentage(percent);
115 // close encoder ripper
120 if (file.IsRemote() && !cancelled && result == 2)
122 // copy the ripped track to the share
123 if (!CFile::Cache(m_output, file.GetPath()))
125 CLog::Log(LOGERROR, "CDDARipper: Error copying file from %s to %s",
126 m_output.c_str(), file.GetPath().c_str());
127 CFile::Delete(m_output);
130 // delete cached file
131 CFile::Delete(m_output);
136 CLog::Log(LOGWARNING, "User Cancelled CDDA Rip");
137 CFile::Delete(m_output);
139 else if (result == 1)
140 CLog::Log(LOGERROR, "CDDARipper: Error ripping %s", m_input.c_str());
142 CLog::Log(LOGERROR, "CDDARipper: Error encoding %s", m_input.c_str());
145 CLog::Log(LOGINFO, "Finished ripping %s", m_input.c_str());
148 CLog::Log(LOGINFO, "Ejecting CD");
149 g_mediaManager.EjectTray();
153 handle->MarkFinished();
155 return !cancelled && result == 2;
158 int CCDDARipJob::RipChunk(CFile& reader, CEncoder* encoder, int& percent)
162 uint8_t stream[1024];
165 int result = reader.Read(stream, 1024);
167 // return if rip is done or on some kind of error
172 int encres=encoder->Encode(result, stream);
174 // Get progress indication
175 percent = reader.GetPosition()*100/reader.GetLength();
177 if (reader.GetPosition() == reader.GetLength())
183 CEncoder* CCDDARipJob::SetupEncoder(CFile& reader)
188 #ifdef HAVE_LIBVORBISENC
189 case CDDARIP_ENCODER_VORBIS:
190 encoder = new CEncoderVorbis();
193 #ifdef HAVE_LIBMP3LAME
194 case CDDARIP_ENCODER_LAME:
195 encoder = new CEncoderLame();
198 case CDDARIP_ENCODER_FLAC:
199 encoder = new CEncoderFlac();
201 case CDDARIP_ENCODER_FFMPEG_M4A:
202 case CDDARIP_ENCODER_FFMPEG_WMA:
203 encoder = new CEncoderFFmpeg();
205 case CDDARIP_ENCODER_WAV:
207 encoder = new CEncoderWav();
214 // we have to set the tags before we init the Encoder
216 strTrack.Format("%i", strtol(m_input.substr(13, m_input.size() - 13 - 5).c_str(),NULL,10));
218 encoder->SetComment("Ripped with XBMC");
219 encoder->SetArtist(StringUtils::Join(m_tag.GetArtist(),
220 g_advancedSettings.m_musicItemSeparator));
221 encoder->SetTitle(m_tag.GetTitle());
222 encoder->SetAlbum(m_tag.GetAlbum());
223 encoder->SetAlbumArtist(StringUtils::Join(m_tag.GetAlbumArtist(),
224 g_advancedSettings.m_musicItemSeparator));
225 encoder->SetGenre(StringUtils::Join(m_tag.GetGenre(),
226 g_advancedSettings.m_musicItemSeparator));
227 encoder->SetTrack(strTrack);
228 encoder->SetTrackLength(reader.GetLength());
229 encoder->SetYear(m_tag.GetYearString());
232 if (!encoder->Init(m_output.c_str(), m_channels, m_rate, m_bps))
233 delete encoder, encoder = NULL;
238 CStdString CCDDARipJob::SetupTempFile()
242 GetTempFileName(CSpecialProtocol::TranslatePath("special://temp/"), "riptrack", 0, tmp);
245 strncpy(tmp, CSpecialProtocol::TranslatePath("special://temp/riptrackXXXXXX").c_str(), MAX_PATH);
246 if ((fd = mkstemp(tmp)) == -1)
254 bool CCDDARipJob::operator==(const CJob* job) const
256 if (strcmp(job->GetType(),GetType()) == 0)
258 const CCDDARipJob* rjob = dynamic_cast<const CCDDARipJob*>(job);
261 return m_input == rjob->m_input &&
262 m_output == rjob->m_output;