Make chromaprint optional

This commit is contained in:
Jonas Kvinge 2018-07-16 07:23:37 +02:00
parent e181b47e3f
commit b2c26eb4ed
10 changed files with 86 additions and 46 deletions

View File

@ -109,8 +109,11 @@ pkg_check_modules(LIBXINE libxine)
pkg_check_modules(LIBVLC libvlc) pkg_check_modules(LIBVLC libvlc)
pkg_check_modules(PHONON phonon4qt5) pkg_check_modules(PHONON phonon4qt5)
pkg_check_modules(SQLITE REQUIRED sqlite3>=3.7) pkg_check_modules(SQLITE REQUIRED sqlite3>=3.7)
pkg_check_modules(CHROMAPRINT REQUIRED libchromaprint)
pkg_check_modules(LIBPULSE libpulse) pkg_check_modules(LIBPULSE libpulse)
pkg_check_modules(CHROMAPRINT libchromaprint)
#if(CHROMAPRINT_FOUND)
# set(HAVE_CHROMAPRINT ON)
#endif()
pkg_check_modules(LIBGPOD libgpod-1.0>=0.7.92) pkg_check_modules(LIBGPOD libgpod-1.0>=0.7.92)
pkg_check_modules(LIBMTP libmtp>=1.0) pkg_check_modules(LIBMTP libmtp>=1.0)
pkg_check_modules(IMOBILEDEVICE libimobiledevice-1.0) pkg_check_modules(IMOBILEDEVICE libimobiledevice-1.0)
@ -184,9 +187,6 @@ if(LASTFM5_INCLUDE_DIRS AND LASTFM51_INCLUDE_DIRS)
set(HAVE_LIBLASTFM1 ON) set(HAVE_LIBLASTFM1 ON)
endif() endif()
# CHECK INCLUDES
CHECK_INCLUDE_FILES(chromaprint.h CHROMAPRINT_H)
# Use system sha2 if it's available # Use system sha2 if it's available
find_path(SHA2_INCLUDE_DIRS sha2.h) find_path(SHA2_INCLUDE_DIRS sha2.h)
find_library(SHA2_LIBRARIES sha2) find_library(SHA2_LIBRARIES sha2)
@ -286,34 +286,22 @@ optional_component(PHONON OFF "Engine: Phonon backend"
DEPENDS "phonon4qt5" PHONON_FOUND DEPENDS "phonon4qt5" PHONON_FOUND
) )
optional_component(AUDIOCD ON "Devices: Audio CD support" optional_component(LIBPULSE ON "Pulse audio integration"
DEPENDS "libcdio" CDIO_FOUND DEPENDS "libpulse" LIBPULSE_FOUND
)
optional_component(LIBGPOD ON "Devices: iPod classic support"
DEPENDS "libgpod" LIBGPOD_FOUND
)
optional_component(GIO ON "Devices: GIO device backend"
DEPENDS "libgio" GIO_FOUND
DEPENDS "Unix or Windows" "NOT APPLE"
)
optional_component(IMOBILEDEVICE ON "Devices: iPod Touch, iPhone, iPad support"
DEPENDS "libimobiledevice" IMOBILEDEVICE_FOUND
DEPENDS "libplist" PLIST_FOUND
DEPENDS "libusbmuxd" USBMUXD_FOUND
DEPENDS "iPod classic support" HAVE_LIBGPOD
)
optional_component(LIBMTP ON "Devices: MTP support"
DEPENDS "libmtp" LIBMTP_FOUND
) )
optional_component(LIBLASTFM ON "Last.fm album cover provider" optional_component(LIBLASTFM ON "Last.fm album cover provider"
DEPENDS "liblastfm" LASTFM5_LIBRARIES LASTFM5_INCLUDE_DIRS DEPENDS "liblastfm" LASTFM5_LIBRARIES LASTFM5_INCLUDE_DIRS
) )
optional_component(CHROMAPRINT ON "Chromaprint support / Tag fetching from Musicbrainz"
DEPENDS "chromaprint" CHROMAPRINT_FOUND
)
optional_component(AUDIOCD ON "Devices: Audio CD support"
DEPENDS "libcdio" CDIO_FOUND
)
optional_component(DEVICEKIT ON "Devices: DeviceKit backend" optional_component(DEVICEKIT ON "Devices: DeviceKit backend"
DEPENDS "D-Bus support" DBUS_FOUND DEPENDS "D-Bus support" DBUS_FOUND
) )
@ -322,8 +310,24 @@ optional_component(UDISKS2 ON "Devices: UDisks2 backend"
DEPENDS "D-Bus support" DBUS_FOUND DEPENDS "D-Bus support" DBUS_FOUND
) )
optional_component(LIBPULSE ON "Pulse audio integration" optional_component(GIO ON "Devices: GIO device backend"
DEPENDS "libpulse" LIBPULSE_FOUND DEPENDS "libgio" GIO_FOUND
DEPENDS "Unix or Windows" "NOT APPLE"
)
optional_component(LIBGPOD ON "Devices: iPod classic support"
DEPENDS "libgpod" LIBGPOD_FOUND
)
optional_component(LIBMTP ON "Devices: MTP support"
DEPENDS "libmtp" LIBMTP_FOUND
)
optional_component(IMOBILEDEVICE ON "Devices: iPod Touch, iPhone, iPad support"
DEPENDS "libimobiledevice" IMOBILEDEVICE_FOUND
DEPENDS "libplist" PLIST_FOUND
DEPENDS "libusbmuxd" USBMUXD_FOUND
DEPENDS "iPod classic support" LIBGPOD_FOUND
) )
optional_component(SPARKLE ON "Sparkle integration" optional_component(SPARKLE ON "Sparkle integration"

View File

@ -26,7 +26,7 @@ endif(STRAWBERRY_VERSION_PRERELEASE)
if(INCLUDE_GIT_REVISION AND EXISTS "${CMAKE_SOURCE_DIR}/.git") if(INCLUDE_GIT_REVISION AND EXISTS "${CMAKE_SOURCE_DIR}/.git")
find_program(GIT_EXECUTABLE git) find_program(GIT_EXECUTABLE git)
if(GIT_EXECUTABLE-NOTFOUND) if(NOT GIT_EXECUTABLE OR GIT_EXECUTABLE-NOTFOUND)
message(FATAL_ERROR "Missing GIT executable." ) message(FATAL_ERROR "Missing GIT executable." )
endif() endif()

View File

@ -724,8 +724,6 @@ SOURCES
settings/transcodersettingspage.cpp settings/transcodersettingspage.cpp
dialogs/organisedialog.cpp dialogs/organisedialog.cpp
dialogs/organiseerrordialog.cpp dialogs/organiseerrordialog.cpp
musicbrainz/chromaprinter.cpp
musicbrainz/tagfetcher.cpp
transcoder/transcoder.cpp transcoder/transcoder.cpp
transcoder/transcodedialog.cpp transcoder/transcodedialog.cpp
transcoder/transcoderoptionsaac.cpp transcoder/transcoderoptionsaac.cpp
@ -741,7 +739,6 @@ HEADERS
settings/transcodersettingspage.h settings/transcodersettingspage.h
dialogs/organisedialog.h dialogs/organisedialog.h
dialogs/organiseerrordialog.h dialogs/organiseerrordialog.h
musicbrainz/tagfetcher.h
transcoder/transcoder.h transcoder/transcoder.h
transcoder/transcodedialog.h transcoder/transcodedialog.h
transcoder/transcoderoptionsdialog.h transcoder/transcoderoptionsdialog.h
@ -764,6 +761,13 @@ UI
# CDIO backend and device # CDIO backend and device
if(HAVE_GSTREAMER) if(HAVE_GSTREAMER)
optional_source(HAVE_CHROMAPRINT
SOURCES
musicbrainz/chromaprinter.cpp
musicbrainz/tagfetcher.cpp
HEADERS
musicbrainz/tagfetcher.h
)
optional_source(HAVE_AUDIOCD optional_source(HAVE_AUDIOCD
SOURCES SOURCES
device/cddadevice.cpp device/cddadevice.cpp

View File

@ -36,6 +36,7 @@
#cmakedefine HAVE_LIBPULSE #cmakedefine HAVE_LIBPULSE
#cmakedefine HAVE_QCA #cmakedefine HAVE_QCA
#cmakedefine HAVE_SPARKLE #cmakedefine HAVE_SPARKLE
#cmakedefine HAVE_CHROMAPRINT
#cmakedefine IMOBILEDEVICE_USES_UDIDS #cmakedefine IMOBILEDEVICE_USES_UDIDS
#cmakedefine USE_INSTALL_PREFIX #cmakedefine USE_INSTALL_PREFIX
#cmakedefine USE_SYSTEM_SHA2 #cmakedefine USE_SYSTEM_SHA2

View File

@ -116,7 +116,6 @@
#include "analyzer/analyzercontainer.h" #include "analyzer/analyzercontainer.h"
#include "equalizer/equalizer.h" #include "equalizer/equalizer.h"
#include "globalshortcuts/globalshortcuts.h" #include "globalshortcuts/globalshortcuts.h"
#include "musicbrainz/tagfetcher.h"
#include "covermanager/albumcovermanager.h" #include "covermanager/albumcovermanager.h"
#include "device/devicemanager.h" #include "device/devicemanager.h"
#include "device/devicestatefiltermodel.h" #include "device/devicestatefiltermodel.h"
@ -127,6 +126,10 @@
#include "settings/playlistsettingspage.h" #include "settings/playlistsettingspage.h"
#include "settings/settingsdialog.h" #include "settings/settingsdialog.h"
#if defined(HAVE_GSTREAMER) && defined(HAVE_CHROMAPRINT)
# include "musicbrainz/tagfetcher.h"
#endif
#ifdef Q_OS_MACOS #ifdef Q_OS_MACOS
# include "core/macsystemtrayicon.h" # include "core/macsystemtrayicon.h"
#endif #endif
@ -341,7 +344,7 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
connect(ui_->action_renumber_tracks, SIGNAL(triggered()), SLOT(RenumberTracks())); connect(ui_->action_renumber_tracks, SIGNAL(triggered()), SLOT(RenumberTracks()));
connect(ui_->action_selection_set_value, SIGNAL(triggered()), SLOT(SelectionSetValue())); connect(ui_->action_selection_set_value, SIGNAL(triggered()), SLOT(SelectionSetValue()));
connect(ui_->action_edit_value, SIGNAL(triggered()), SLOT(EditValue())); connect(ui_->action_edit_value, SIGNAL(triggered()), SLOT(EditValue()));
#ifdef HAVE_GSTREAMER #if defined(HAVE_GSTREAMER) && defined(HAVE_CHROMAPRINT)
connect(ui_->action_auto_complete_tags, SIGNAL(triggered()), SLOT(AutoCompleteTags())); connect(ui_->action_auto_complete_tags, SIGNAL(triggered()), SLOT(AutoCompleteTags()));
#endif #endif
connect(ui_->action_settings, SIGNAL(triggered()), SLOT(OpenSettingsDialog())); connect(ui_->action_settings, SIGNAL(triggered()), SLOT(OpenSettingsDialog()));
@ -1239,8 +1242,13 @@ void MainWindow::PlaylistRightClick(const QPoint &global_pos, const QModelIndex
// this is available when we have one or many files and at least one of those is not CUE related // this is available when we have one or many files and at least one of those is not CUE related
ui_->action_edit_track->setEnabled(editable); ui_->action_edit_track->setEnabled(editable);
ui_->action_edit_track->setVisible(editable); ui_->action_edit_track->setVisible(editable);
#if defined(HAVE_GSTREAMER) && defined(HAVE_CHROMAPRINT)
ui_->action_auto_complete_tags->setEnabled(editable); ui_->action_auto_complete_tags->setEnabled(editable);
ui_->action_auto_complete_tags->setVisible(editable); ui_->action_auto_complete_tags->setVisible(editable);
#else
ui_->action_auto_complete_tags->setEnabled(false);
ui_->action_auto_complete_tags->setVisible(false);
#endif
// the rest of the read / write actions work only when there are no CUEs involved // the rest of the read / write actions work only when there are no CUEs involved
if (cue_selected) editable = 0; if (cue_selected) editable = 0;
@ -2155,7 +2163,7 @@ void MainWindow::Exit() {
} }
#ifdef HAVE_GSTREAMER #if defined(HAVE_GSTREAMER) && defined(HAVE_CHROMAPRINT)
void MainWindow::AutoCompleteTags() { void MainWindow::AutoCompleteTags() {
// Create the tag fetching stuff if it hasn't been already // Create the tag fetching stuff if it hasn't been already

View File

@ -75,7 +75,9 @@ class QueueManager;
class Song; class Song;
class StatusView; class StatusView;
class SystemTrayIcon; class SystemTrayIcon;
#if defined(HAVE_GSTREAMER) && defined(HAVE_CHROMAPRINT)
class TagFetcher; class TagFetcher;
#endif
class TrackSelectionDialog; class TrackSelectionDialog;
#ifdef HAVE_GSTREAMER #ifdef HAVE_GSTREAMER
class TranscodeDialog; class TranscodeDialog;
@ -166,7 +168,7 @@ signals:
void RenumberTracks(); void RenumberTracks();
void SelectionSetValue(); void SelectionSetValue();
void EditValue(); void EditValue();
#ifdef HAVE_GSTREAMER #if defined(HAVE_GSTREAMER) && defined(HAVE_CHROMAPRINT)
void AutoCompleteTags(); void AutoCompleteTags();
void AutoCompleteTagsAccepted(); void AutoCompleteTagsAccepted();
#endif #endif
@ -303,11 +305,11 @@ signals:
#endif #endif
Lazy<QueueManager> queue_manager_; Lazy<QueueManager> queue_manager_;
#ifdef HAVE_GSTREAMER #if defined(HAVE_GSTREAMER) && defined(HAVE_CHROMAPRINT)
std::unique_ptr<TagFetcher> tag_fetcher_; std::unique_ptr<TagFetcher> tag_fetcher_;
#endif #endif
std::unique_ptr<TrackSelectionDialog> track_selection_dialog_; std::unique_ptr<TrackSelectionDialog> track_selection_dialog_;
#ifdef HAVE_GSTREAMER #if defined(HAVE_GSTREAMER) && defined(HAVE_CHROMAPRINT)
PlaylistItemList autocomplete_tag_items_; PlaylistItemList autocomplete_tag_items_;
#endif #endif

View File

@ -164,6 +164,7 @@ void CddaSongLoader::LoadSongs() {
} }
emit SongsDurationLoaded(songs); emit SongsDurationLoaded(songs);
#ifdef HAVE_CHROMAPRINT
// Handle TAG message: generate MusicBrainz DiscId // Handle TAG message: generate MusicBrainz DiscId
if (msg_tag) { if (msg_tag) {
GstTagList *tags = nullptr; GstTagList *tags = nullptr;
@ -181,6 +182,7 @@ void CddaSongLoader::LoadSongs() {
gst_tag_list_free(tags); gst_tag_list_free(tags);
} }
} }
#endif
gst_element_set_state(pipeline, GST_STATE_NULL); gst_element_set_state(pipeline, GST_STATE_NULL);
// This will also cause cdda_ to be unref'd. // This will also cause cdda_ to be unref'd.
@ -188,6 +190,7 @@ void CddaSongLoader::LoadSongs() {
} }
#ifdef HAVE_CHROMAPRINT
void CddaSongLoader::AudioCDTagsLoaded(const QString &artist, const QString &album, const MusicBrainzClient::ResultList &results) { void CddaSongLoader::AudioCDTagsLoaded(const QString &artist, const QString &album, const MusicBrainzClient::ResultList &results) {
MusicBrainzClient *musicbrainz_client = qobject_cast<MusicBrainzClient*>(sender()); MusicBrainzClient *musicbrainz_client = qobject_cast<MusicBrainzClient*>(sender());
@ -213,6 +216,7 @@ void CddaSongLoader::AudioCDTagsLoaded(const QString &artist, const QString &alb
emit SongsMetadataLoaded(songs); emit SongsMetadataLoaded(songs);
} }
#endif
bool CddaSongLoader::HasChanged() { bool CddaSongLoader::HasChanged() {

View File

@ -37,7 +37,9 @@
#include <gst/audio/gstaudiocdsrc.h> #include <gst/audio/gstaudiocdsrc.h>
#include "core/song.h" #include "core/song.h"
#ifdef HAVE_CHROMAPRINT
# include "musicbrainz/musicbrainzclient.h" # include "musicbrainz/musicbrainzclient.h"
#endif
// This class provides a (hopefully) nice, high level interface to get CD information and load tracks // This class provides a (hopefully) nice, high level interface to get CD information and load tracks
class CddaSongLoader : public QObject { class CddaSongLoader : public QObject {
@ -60,7 +62,9 @@ class CddaSongLoader : public QObject {
void SongsMetadataLoaded(const SongList &songs); void SongsMetadataLoaded(const SongList &songs);
private slots: private slots:
#ifdef HAVE_CHROMAPRINT
void AudioCDTagsLoaded(const QString &artist, const QString &album, const MusicBrainzClient::ResultList &results); void AudioCDTagsLoaded(const QString &artist, const QString &album, const MusicBrainzClient::ResultList &results);
#endif
private: private:
QUrl GetUrlFromTrack(int track_number) const; QUrl GetUrlFromTrack(int track_number) const;

View File

@ -76,7 +76,9 @@
#include "collection/collectionbackend.h" #include "collection/collectionbackend.h"
#include "playlist/playlist.h" #include "playlist/playlist.h"
#include "playlist/playlistdelegates.h" #include "playlist/playlistdelegates.h"
#if defined(HAVE_GSTREAMER) && defined(HAVE_CHROMAPRINT)
# include "musicbrainz/tagfetcher.h" # include "musicbrainz/tagfetcher.h"
#endif
#include "covermanager/albumcoverchoicecontroller.h" #include "covermanager/albumcoverchoicecontroller.h"
#include "covermanager/albumcoverloader.h" #include "covermanager/albumcoverloader.h"
#include "covermanager/coverproviders.h" #include "covermanager/coverproviders.h"
@ -94,7 +96,7 @@ EditTagDialog::EditTagDialog(Application *app, QWidget *parent)
album_cover_choice_controller_(new AlbumCoverChoiceController(this)), album_cover_choice_controller_(new AlbumCoverChoiceController(this)),
loading_(false), loading_(false),
ignore_edits_(false), ignore_edits_(false),
#ifdef HAVE_GSTREAMER #if defined(HAVE_GSTREAMER) && defined(HAVE_CHROMAPRINT)
tag_fetcher_(new TagFetcher(this)), tag_fetcher_(new TagFetcher(this)),
#endif #endif
cover_art_id_(0), cover_art_id_(0),
@ -108,7 +110,7 @@ EditTagDialog::EditTagDialog(Application *app, QWidget *parent)
connect(app_->album_cover_loader(), SIGNAL(ImageLoaded(quint64,QImage,QImage)), SLOT(ArtLoaded(quint64,QImage,QImage))); connect(app_->album_cover_loader(), SIGNAL(ImageLoaded(quint64,QImage,QImage)), SLOT(ArtLoaded(quint64,QImage,QImage)));
#ifdef HAVE_GSTREAMER #if defined(HAVE_GSTREAMER) && defined(HAVE_CHROMAPRINT)
connect(tag_fetcher_, SIGNAL(ResultAvailable(Song, SongList)), results_dialog_, SLOT(FetchTagFinished(Song, SongList)), Qt::QueuedConnection); connect(tag_fetcher_, SIGNAL(ResultAvailable(Song, SongList)), results_dialog_, SLOT(FetchTagFinished(Song, SongList)), Qt::QueuedConnection);
connect(tag_fetcher_, SIGNAL(Progress(Song,QString)), results_dialog_, SLOT(FetchTagProgress(Song,QString))); connect(tag_fetcher_, SIGNAL(Progress(Song,QString)), results_dialog_, SLOT(FetchTagProgress(Song,QString)));
connect(results_dialog_, SIGNAL(SongChosen(Song, Song)), SLOT(FetchTagSongChosen(Song, Song))); connect(results_dialog_, SIGNAL(SongChosen(Song, Song)), SLOT(FetchTagSongChosen(Song, Song)));
@ -122,6 +124,11 @@ EditTagDialog::EditTagDialog(Application *app, QWidget *parent)
ui_->loading_label->hide(); ui_->loading_label->hide();
ui_->fetch_tag->setIcon(QPixmap::fromImage(QImage(":/pictures/musicbrainz.png"))); ui_->fetch_tag->setIcon(QPixmap::fromImage(QImage(":/pictures/musicbrainz.png")));
#if defined(HAVE_GSTREAMER) && defined(HAVE_CHROMAPRINT)
ui_->fetch_tag->setEnabled(true);
#else
ui_->fetch_tag->setEnabled(false);
#endif
// An editable field is one that has a label as a buddy. The label is // An editable field is one that has a label as a buddy. The label is
// important because it gets turned bold when the field is changed. // important because it gets turned bold when the field is changed.
@ -168,7 +175,9 @@ EditTagDialog::EditTagDialog(Application *app, QWidget *parent)
connect(ui_->button_box, SIGNAL(clicked(QAbstractButton*)), SLOT(ButtonClicked(QAbstractButton*))); connect(ui_->button_box, SIGNAL(clicked(QAbstractButton*)), SLOT(ButtonClicked(QAbstractButton*)));
//connect(ui_->rating, SIGNAL(RatingChanged(float)), SLOT(SongRated(float))); //connect(ui_->rating, SIGNAL(RatingChanged(float)), SLOT(SongRated(float)));
connect(ui_->playcount_reset, SIGNAL(clicked()), SLOT(ResetPlayCounts())); connect(ui_->playcount_reset, SIGNAL(clicked()), SLOT(ResetPlayCounts()));
#if defined(HAVE_GSTREAMER) && defined(HAVE_CHROMAPRINT)
connect(ui_->fetch_tag, SIGNAL(clicked()), SLOT(FetchTag())); connect(ui_->fetch_tag, SIGNAL(clicked()), SLOT(FetchTag()));
#endif
// Set up the album cover menu // Set up the album cover menu
cover_menu_ = new QMenu(this); cover_menu_ = new QMenu(this);
@ -237,7 +246,9 @@ bool EditTagDialog::SetLoading(const QString &message) {
ui_->button_box->setEnabled(!loading); ui_->button_box->setEnabled(!loading);
ui_->tab_widget->setEnabled(!loading); ui_->tab_widget->setEnabled(!loading);
ui_->song_list->setEnabled(!loading); ui_->song_list->setEnabled(!loading);
#if defined(HAVE_GSTREAMER) && defined(HAVE_CHROMAPRINT)
ui_->fetch_tag->setEnabled(!loading); ui_->fetch_tag->setEnabled(!loading);
#endif
ui_->loading_label->setVisible(loading); ui_->loading_label->setVisible(loading);
ui_->loading_label->set_text(message); ui_->loading_label->set_text(message);
return true; return true;
@ -826,7 +837,7 @@ void EditTagDialog::ResetPlayCounts() {
UpdateStatisticsTab(*song); UpdateStatisticsTab(*song);
} }
#ifdef HAVE_GSTREAMER #if defined(HAVE_GSTREAMER) && defined(HAVE_CHROMAPRINT)
void EditTagDialog::FetchTag() { void EditTagDialog::FetchTag() {
const QModelIndexList sel = ui_->song_list->selectionModel()->selectedIndexes(); const QModelIndexList sel = ui_->song_list->selectionModel()->selectedIndexes();

View File

@ -50,10 +50,12 @@ class QShowEvent;
class QHideEvent; class QHideEvent;
class Application; class Application;
class TagFetcher;
class AlbumCoverChoiceController; class AlbumCoverChoiceController;
class TrackSelectionDialog; class TrackSelectionDialog;
class Ui_EditTagDialog; class Ui_EditTagDialog;
#if defined(HAVE_GSTREAMER) && defined(HAVE_CHROMAPRINT)
class TagFetcher;
#endif
class EditTagDialog : public QDialog { class EditTagDialog : public QDialog {
Q_OBJECT Q_OBJECT
@ -106,7 +108,7 @@ protected:
void ResetField(); void ResetField();
void ButtonClicked(QAbstractButton *button); void ButtonClicked(QAbstractButton *button);
void ResetPlayCounts(); void ResetPlayCounts();
#ifdef HAVE_GSTREAMER #if defined(HAVE_GSTREAMER) && defined(HAVE_CHROMAPRINT)
void FetchTag(); void FetchTag();
void FetchTagSongChosen(const Song &original_song, const Song &new_metadata); void FetchTagSongChosen(const Song &original_song, const Song &new_metadata);
#endif #endif
@ -170,7 +172,7 @@ private:
bool ignore_edits_; bool ignore_edits_;
#ifdef HAVE_GSTREAMER #if defined(HAVE_GSTREAMER) && defined(HAVE_CHROMAPRINT)
TagFetcher *tag_fetcher_; TagFetcher *tag_fetcher_;
#endif #endif