1 /*
2  *  Copyright 2007-2016 Fabrice Colin
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17  */
18 
19 #include <stdio.h>
20 #include <unistd.h>
21 #include <fileref.h>
22 #include <tfile.h>
23 #include <tag.h>
24 #include <iostream>
25 
26 #include "TagLibMusicFilter.h"
27 
28 using std::string;
29 using std::clog;
30 using std::endl;
31 
32 using namespace Dijon;
33 
34 #ifdef _DYNAMIC_DIJON_FILTERS
get_filter_types(MIMETypes & mime_types)35 DIJON_FILTER_EXPORT bool get_filter_types(MIMETypes &mime_types)
36 {
37 	mime_types.m_mimeTypes.clear();
38 	mime_types.m_mimeTypes.insert("audio/mpeg");
39 	mime_types.m_mimeTypes.insert("audio/x-mp3");
40 	mime_types.m_mimeTypes.insert("application/ogg");
41 	mime_types.m_mimeTypes.insert("audio/x-flac+ogg");
42 	mime_types.m_mimeTypes.insert("audio/x-flac");
43 
44 	return true;
45 }
46 
check_filter_data_input(int data_input)47 DIJON_FILTER_EXPORT bool check_filter_data_input(int data_input)
48 {
49 	Filter::DataInput input = (Filter::DataInput)data_input;
50 
51 	if (input == Filter::DOCUMENT_FILE_NAME)
52 	{
53 		return true;
54 	}
55 
56 	return false;
57 }
58 
get_filter(void)59 DIJON_FILTER_EXPORT Filter *get_filter(void)
60 {
61 	return new TagLibMusicFilter();
62 }
63 #endif
64 
TagLibMusicFilter()65 TagLibMusicFilter::TagLibMusicFilter() :
66 	Filter(),
67 	m_parseDocument(false)
68 {
69 }
70 
~TagLibMusicFilter()71 TagLibMusicFilter::~TagLibMusicFilter()
72 {
73 	rewind();
74 }
75 
is_data_input_ok(DataInput input) const76 bool TagLibMusicFilter::is_data_input_ok(DataInput input) const
77 {
78 	if (input == DOCUMENT_FILE_NAME)
79 	{
80 		return true;
81 	}
82 
83 	return false;
84 }
85 
set_property(Properties prop_name,const string & prop_value)86 bool TagLibMusicFilter::set_property(Properties prop_name, const string &prop_value)
87 {
88 	return false;
89 }
90 
set_document_data(const char * data_ptr,off_t data_length)91 bool TagLibMusicFilter::set_document_data(const char *data_ptr, off_t data_length)
92 {
93 	return false;
94 }
95 
set_document_string(const string & data_str)96 bool TagLibMusicFilter::set_document_string(const string &data_str)
97 {
98 	return false;
99 }
100 
set_document_file(const string & file_path,bool unlink_when_done)101 bool TagLibMusicFilter::set_document_file(const string &file_path, bool unlink_when_done)
102 {
103 	if (Filter::set_document_file(file_path, unlink_when_done) == true)
104 	{
105 		m_parseDocument = true;
106 
107 		return true;
108 	}
109 
110 	return false;
111 }
112 
set_document_uri(const string & uri)113 bool TagLibMusicFilter::set_document_uri(const string &uri)
114 {
115 	return false;
116 }
117 
has_documents(void) const118 bool TagLibMusicFilter::has_documents(void) const
119 {
120 	return m_parseDocument;
121 }
122 
next_document(void)123 bool TagLibMusicFilter::next_document(void)
124 {
125 	if (m_parseDocument == true)
126 	{
127 		m_parseDocument = false;
128 
129 		m_content.clear();
130 		m_metaData.clear();
131 
132 		TagLib::FileRef fileRef(m_filePath.c_str(), false);
133 		if (fileRef.isNull() == false)
134 		{
135 			TagLib::Tag *pTag = fileRef.tag();
136 
137 			if ((pTag != NULL) &&
138 				(pTag->isEmpty() == false))
139 			{
140 				char yearStr[64];
141 
142 				string trackTitle(pTag->title().toCString(true));
143 				trackTitle += " ";
144 				trackTitle += pTag->artist().toCString(true);
145 
146 #ifdef DEBUG
147 				clog << "TagLibMusicFilter::next_document: " << trackTitle.length() << " bytes of text" << endl;
148 #endif
149 				m_content.append(trackTitle.c_str(), trackTitle.length());
150 				m_content += " ";
151 				m_content += pTag->album().toCString(true);
152 				m_content += " ";
153 				m_content += pTag->comment().toCString(true);
154 				m_content += " ";
155 				m_content += pTag->genre().toCString(true);
156 				snprintf(yearStr, 64, " %u", pTag->year());
157 				m_content += yearStr;
158 
159 				m_metaData["title"] = trackTitle;
160 				m_metaData["ipath"] = "";
161 				m_metaData["mimetype"] = "text/plain";
162 				m_metaData["charset"] = "utf-8";
163 				m_metaData["author"] = pTag->artist().toCString(true);
164 			}
165 			else
166 			{
167 				// This file doesn't have any tag
168 				string::size_type filePos = m_filePath.find_last_of("/");
169 				if ((filePos != string::npos) &&
170 					(m_filePath.length() - filePos > 1))
171 				{
172 					m_metaData["title"] = m_filePath.substr(filePos + 1);
173 				}
174 				else
175 				{
176 					m_metaData["title"] = m_filePath;
177 				}
178 				m_metaData["ipath"] = "";
179 				m_metaData["mimetype"] = "text/plain";
180 				m_metaData["charset"] = "utf-8";
181 			}
182 
183 			return true;
184 		}
185 	}
186 
187 	return false;
188 }
189 
skip_to_document(const string & ipath)190 bool TagLibMusicFilter::skip_to_document(const string &ipath)
191 {
192 	if (ipath.empty() == true)
193 	{
194 		return next_document();
195 	}
196 
197 	return false;
198 }
199 
get_error(void) const200 string TagLibMusicFilter::get_error(void) const
201 {
202 	return "";
203 }
204 
rewind(void)205 void TagLibMusicFilter::rewind(void)
206 {
207 	Filter::rewind();
208 
209 	m_parseDocument = false;
210 }
211