示例#1
0
void CTagLoaderTagLib::SetArtist(CMusicInfoTag &tag, const std::vector<std::string> &values)
{
  if (values.size() == 1)
    tag.SetArtist(values[0]);
  else
    tag.SetArtist(values);
}
示例#2
0
void CTagLoaderTagLib::SetArtist(CMusicInfoTag &tag, const std::vector<std::string> &values)
{
  if (values.size() == 1)
    tag.SetArtist(values[0]);
  else
    // Fill both artist vector and artist desc from tag value.
    // Note desc may not be empty as it could have been set by previous parsing of ID3v2 before APE
    tag.SetArtist(values, true); 
}
示例#3
0
bool CMusicInfoTagLoaderNSF::Load(const CStdString& strFileName, CMusicInfoTag& tag)
{
  tag.SetLoaded(false);

  if (!m_dll.Load())
    return false;

  m_nsf = m_dll.LoadNSF(strFileName.c_str());
  if (!m_nsf)
  {
    CLog::Log(LOGERROR,"MusicInfoTagLoaderNSF: failed to open NSF %s",strFileName.c_str());
    return false;
  }

  tag.SetURL(strFileName);

  tag.SetLoaded(false);
  char* szTitle = (char*)m_dll.GetTitle(m_nsf); // no alloc
  if( szTitle && strcmp(szTitle,"<?>") )
  {
    tag.SetTitle(szTitle);
    tag.SetLoaded(true);
  }

  char* szArtist = (char*)m_dll.GetArtist(m_nsf); // no alloc
  if( szArtist && strcmp(szArtist,"<?>") && tag.Loaded() )
    tag.SetArtist(szArtist);

  m_dll.FreeNSF(m_nsf);
  m_nsf = 0;

  return tag.Loaded();
}
示例#4
0
bool CMusicInfoTagLoaderSPC::Load(const CStdString& strFileName, CMusicInfoTag& tag)
{
  tag.SetLoaded(false);

  CFile file;
  if (!file.Open(strFileName))
  {
    CLog::Log(LOGERROR,"MusicInfoTagLoaderSPC: failed to open SPC %s",strFileName.c_str());
    return false;
  }

  tag.SetURL(strFileName);

  tag.SetLoaded(false);
  SPC_ID666* spc = SPC_get_id666FP(file);
  if (!spc)
    return false;
  if( strcmp(spc->songname,"") )
  {
    tag.SetTitle(spc->songname);
    tag.SetLoaded(true);
  }

  if( strcmp(spc->author,"") && tag.Loaded() )
    tag.SetArtist(spc->author);

  if (spc->playtime)
    tag.SetDuration(spc->playtime);
  else
    tag.SetDuration(4*60); // 4 mins

  free(spc);
  return tag.Loaded();
}
示例#5
0
bool CTagLoaderTagLib::ParseASF(ASF::Tag *asf, EmbeddedArt *art, CMusicInfoTag& tag)
{
  if (!asf)
    return false;

  tag.SetTitle(asf->title().to8Bit(true));
  const ASF::AttributeListMap& attributeListMap = asf->attributeListMap();
  for (ASF::AttributeListMap::ConstIterator it = attributeListMap.begin(); it != attributeListMap.end(); ++it)
  {
    if (it->first == "Author")                           SetArtist(tag, GetASFStringList(it->second));
    else if (it->first == "WM/AlbumArtist")              SetAlbumArtist(tag, GetASFStringList(it->second));
    else if (it->first == "WM/AlbumTitle")               tag.SetAlbum(it->second.front().toString().to8Bit(true));
    else if (it->first == "WM/TrackNumber" ||
             it->first == "WM/Track")
    {
      if (it->second.front().type() == ASF::Attribute::DWordType)
        tag.SetTrackNumber(it->second.front().toUInt());
      else
        tag.SetTrackNumber(atoi(it->second.front().toString().toCString(true)));
    }
    else if (it->first == "WM/PartOfSet")                tag.SetPartOfSet(atoi(it->second.front().toString().toCString(true)));
    else if (it->first == "WM/Genre")                    SetGenre(tag, GetASFStringList(it->second));
    else if (it->first == "WM/AlbumArtistSortOrder")     {} // Known unsupported, supress warnings
    else if (it->first == "WM/ArtistSortOrder")          {} // Known unsupported, supress warnings
    else if (it->first == "WM/Script")                   {} // Known unsupported, supress warnings
    else if (it->first == "WM/Year")                     tag.SetYear(atoi(it->second.front().toString().toCString(true)));
    else if (it->first == "MusicBrainz/Artist Id")       tag.SetMusicBrainzArtistID(GetASFStringList(it->second));
    else if (it->first == "MusicBrainz/Album Id")        tag.SetMusicBrainzAlbumID(it->second.front().toString().to8Bit(true));
    else if (it->first == "MusicBrainz/Album Artist")    SetAlbumArtist(tag, GetASFStringList(it->second));
    else if (it->first == "MusicBrainz/Album Artist Id") tag.SetMusicBrainzAlbumArtistID(GetASFStringList(it->second));
    else if (it->first == "MusicBrainz/Track Id")        tag.SetMusicBrainzTrackID(it->second.front().toString().to8Bit(true));
    else if (it->first == "MusicBrainz/Album Status")    {}
    else if (it->first == "MusicBrainz/Album Type")      {}
    else if (it->first == "MusicIP/PUID")                {}
    else if (it->first == "replaygain_track_gain")       tag.SetReplayGainTrackGain((int)(atof(it->second.front().toString().toCString(true)) * 100 + 0.5));
    else if (it->first == "replaygain_album_gain")       tag.SetReplayGainAlbumGain((int)(atof(it->second.front().toString().toCString(true)) * 100 + 0.5));
    else if (it->first == "replaygain_track_peak")       tag.SetReplayGainTrackPeak((float)atof(it->second.front().toString().toCString(true)));
    else if (it->first == "replaygain_album_peak")       tag.SetReplayGainAlbumPeak((float)atof(it->second.front().toString().toCString(true)));
    else if (it->first == "WM/Picture")
    { // picture
      ASF::Picture pic = it->second.front().toPicture();
      tag.SetCoverArtInfo(pic.picture().size(), pic.mimeType().toCString());
      if (art)
        art->set((const uint8_t *)pic.picture().data(), pic.picture().size(), pic.mimeType().toCString());
    }
    else if (g_advancedSettings.m_logLevel == LOG_LEVEL_MAX)
      CLog::Log(LOGDEBUG, "unrecognized ASF tag name: %s", it->first.toCString(true));
  }
  // artist may be specified in the ContentDescription block rather than using the 'Author' attribute.
  if (tag.GetArtist().empty())
    tag.SetArtist(asf->artist().toCString(true));
  tag.SetLoaded(true);
  return true;
}
示例#6
0
bool CTagLoaderTagLib::ParseTag(ID3v1::Tag *id3v1, EmbeddedArt *art, CMusicInfoTag& tag)
{
  if (!id3v1) return false;
  tag.SetTitle(id3v1->title().to8Bit(true));
  tag.SetArtist(id3v1->artist().to8Bit(true));
  tag.SetAlbum(id3v1->album().to8Bit(true));
  tag.SetComment(id3v1->comment().to8Bit(true));
  tag.SetGenre(id3v1->genre().to8Bit(true));
  tag.SetYear(id3v1->year());
  tag.SetTrackNumber(id3v1->track());
  return true;
}
bool CMusicInfoTagLoaderMod::Load(const CStdString& strFileName, CMusicInfoTag& tag, EmbeddedArt *art)
{
  tag.SetURL(strFileName);
  // first, does the module have a .mdz?
  CStdString strMDZ(URIUtils::ReplaceExtension(strFileName,".mdz"));
  if (CFile::Exists(strMDZ))
  {
    if (!getFile(strMDZ,strMDZ))
    {
      tag.SetLoaded(false);
      return( false );
    }
    ifstream inMDZ(CSpecialProtocol::TranslatePath(strMDZ.c_str()));
    char temp[8192];
    char temp2[8192];

    while (!inMDZ.eof())
    {
      inMDZ.getline(temp,8191);
      if (strstr(temp,"COMPOSER"))
      {
        strcpy(temp2,temp+strlen("COMPOSER "));
        tag.SetArtist(temp2);
      }
      else if (strstr(temp,"TITLE"))
      {
        strcpy(temp2,temp+strlen("TITLE "));
        tag.SetTitle(temp2);
        tag.SetLoaded(true);
      }
      else if (strstr(temp,"PLAYTIME"))
      {
        char* temp3 = strtok(temp+strlen("PLAYTIME "),":");
        int iSecs = atoi(temp3)*60;
        temp3 = strtok(NULL,":");
        iSecs += atoi(temp3);
        tag.SetDuration(iSecs);
      }
      else if (strstr(temp,"STYLE"))
      {
        strcpy(temp2,temp+strlen("STYLE "));
        tag.SetGenre(temp2);
      }
    }
    return( tag.Loaded() );
  }
  else
  {
    // TODO: no, then try to atleast fetch the title
  }

  return tag.Loaded();
}
示例#8
0
bool CEncoderLame::Close()
{
  // may return one more mp3 frames
  int iBytes = m_dll.lame_encode_flush(m_pGlobalFlags, m_buffer, sizeof(m_buffer));

  if (iBytes < 0)
  {
    CLog::Log(LOGERROR, "Internal Lame error: %i", iBytes);
    return false;
  }

  WriteStream(m_buffer, iBytes);
  FlushStream();
  FileClose();

  // open again, but now the old way, lame only accepts FILE pointers
  FILE* file = fopen_utf8(m_strFile.c_str(), "rb+");
  if (!file)
  {
    CLog::Log(LOGERROR, "Error: Cannot open file for writing tags: %s", m_strFile.c_str());
    return false;
  }

  m_dll.lame_mp3_tags_fid(m_pGlobalFlags, file); /* add VBR tags to mp3 file */
  fclose(file);

  m_dll.lame_close(m_pGlobalFlags);

  // unload the lame dll
  m_dll.Unload();

  // Store a id3 tag in the ripped file
  CID3Tag id3tag;
  CMusicInfoTag tag;
  tag.SetAlbum(m_strAlbum);
  tag.SetAlbumArtist(m_strAlbumArtist);
  tag.SetArtist(m_strArtist);
  tag.SetGenre(m_strGenre);
  tag.SetTitle(m_strTitle);
  tag.SetTrackNumber(atoi(m_strTrack.c_str()));
  SYSTEMTIME time;
  time.wYear=atoi(m_strYear.c_str());
  tag.SetReleaseDate(time);
  id3tag.SetMusicInfoTag(tag);
  id3tag.Write(m_strFile);

  return true;
}
bool CMusicInfoTagLoaderApe::Load(const CStdString& strFileName, CMusicInfoTag& tag, EmbeddedArt *art)
{
  try
  {
    // retrieve the APE Tag info from strFileName
    // and put it in tag
    tag.SetURL(strFileName);
    DVDPlayerCodec codec;
    if (codec.Init(strFileName, 4096))
    {
      tag.SetDuration((int)(codec.m_TotalTime/1000));
      codec.DeInit();
    }
    CAPEv2Tag myTag;
    if (myTag.ReadTag((char*)strFileName.c_str())) // true to check ID3 tag as well
    {
      tag.SetTitle(myTag.GetTitle());
      tag.SetAlbum(myTag.GetAlbum());
      tag.SetArtist(myTag.GetArtist());
      tag.SetAlbumArtist(myTag.GetAlbumArtist());
      tag.SetGenre(myTag.GetGenre());
      tag.SetTrackNumber(myTag.GetTrackNum());
      tag.SetPartOfSet(myTag.GetDiscNum());
      tag.SetComment(myTag.GetComment());
      tag.SetLyrics(myTag.GetLyrics());
      tag.SetMusicBrainzAlbumArtistID(myTag.GetMusicBrainzAlbumArtistID());
      tag.SetMusicBrainzAlbumID(myTag.GetMusicBrainzAlbumID());
      tag.SetMusicBrainzArtistID(myTag.GetMusicBrainzArtistID());
      tag.SetMusicBrainzTrackID(myTag.GetMusicBrainzTrackID());
      tag.SetMusicBrainzTRMID(myTag.GetMusicBrainzTRMID());
      SYSTEMTIME dateTime;
      ZeroMemory(&dateTime, sizeof(SYSTEMTIME));
      dateTime.wYear = atoi(myTag.GetYear());
      tag.SetRating(myTag.GetRating());
      tag.SetReleaseDate(dateTime);
      tag.SetLoaded();
      return true;
    }
  }
  catch (...)
  {
    CLog::Log(LOGERROR, "Tag loader ape: exception in file %s", strFileName.c_str());
  }

  tag.SetLoaded(false);
  return false;
}
示例#10
0
bool CMusicInfoTagLoaderASAP::Load(const CStdString &strFile, CMusicInfoTag &tag, EmbeddedArt *art)
{
    tag.SetLoaded(false);

    if (!m_dll.Load())
        return false;

    CStdString strFileToLoad = strFile;
    int song = -1;
    CStdString strExtension;
    URIUtils::GetExtension(strFile, strExtension);
    strExtension.MakeLower();
    if (strExtension == ".asapstream")
    {
        CStdString strFileName = URIUtils::GetFileName(strFile);
        int iStart = strFileName.ReverseFind('-') + 1;
        song = atoi(strFileName.substr(iStart, strFileName.size() - iStart - 11).c_str()) - 1;
        CStdString strPath = strFile;
        URIUtils::GetDirectory(strPath, strFileToLoad);
        URIUtils::RemoveSlashAtEnd(strFileToLoad);
    }

    ASAP_SongInfo songInfo;
    if (!m_dll.asapGetInfo(strFileToLoad.c_str(), song, &songInfo))
        return false;

    tag.SetURL(strFileToLoad);
    if (songInfo.name[0] != '\0')
        tag.SetTitle(songInfo.name);
    if (songInfo.author[0] != '\0')
        tag.SetArtist(songInfo.author);
    if (song >= 0)
        tag.SetTrackNumber(song + 1);
    if (songInfo.duration >= 0)
        tag.SetDuration(songInfo.duration / 1000);
    if (songInfo.year > 0)
    {
        SYSTEMTIME dateTime = { (WORD)songInfo.year, (WORD)songInfo.month, 0,
                                (WORD)songInfo.day, 0, 0, 0, 0
                              };
        tag.SetReleaseDate(dateTime);
    }
    tag.SetLoaded(true);
    return true;
}
示例#11
0
int CPVRChannels::GetChannels(CFileItemList* results, int iGroupID /* = -1 */, bool bHidden /* = false */)
{
  int iAmount = 0;

  SortByChannelNumber();

  for (unsigned int ptr = 0; ptr < size(); ptr++)
  {
    CPVRChannel *channel = at(ptr);

    if (channel->IsHidden() != bHidden)
      continue;

    if (iGroupID != -1 && channel->GroupID() != iGroupID)
      continue;

    CFileItemPtr channelFile(new CFileItem(*channel));

    if (channel->IsRadio())
    {
      CMusicInfoTag* musictag = channelFile->GetMusicInfoTag();
      if (musictag)
      {
        const CPVREpgInfoTag *epgNow = channel->GetEPGNow();
        musictag->SetURL(channel->Path());
        musictag->SetTitle(epgNow->Title());
        musictag->SetArtist(channel->ChannelName());
        musictag->SetAlbumArtist(channel->ChannelName());
        musictag->SetGenre(epgNow->Genre());
        musictag->SetDuration(epgNow->GetDuration());
        musictag->SetLoaded(true);
        musictag->SetComment("");
        musictag->SetLyrics("");
      }
    }

    results->Add(channelFile);
    iAmount++;
  }
  return iAmount;
}
// There is no reliable tag information in MIDI files. There is a 'title' field (@T), but it looks
// like everyone puts there song title, artist name, the name of the person who created the lyrics and
// greetings to their friends and family. Therefore we return the song title as file name, and the
// song artist as parent directory.
// A good intention of creating a pattern-based artist/song recognition engine failed greatly. Simple formats
// like %A-%T fail greatly with artists like A-HA and songs like "Ob-la-Di ob-la-Da.mid". So if anyone has
// a good idea which would include cases from above, I'd be happy to hear about it.
bool CMusicInfoTagLoaderMidi::Load(const CStdString & strFileName, CMusicInfoTag & tag, EmbeddedArt *art)
{
  tag.SetURL(strFileName);

  CStdString path, title;
  URIUtils::Split( strFileName, path, title);
  URIUtils::RemoveExtension( title );

  tag.SetTitle( title );

  URIUtils::RemoveSlashAtEnd(path );

  if ( !path.IsEmpty() )
  {
    CStdString artist = URIUtils::GetFileName( path );
    if ( !artist.IsEmpty() )
      tag.SetArtist( artist );
  }

  tag.SetLoaded(true);
  return true;
}
bool CMusicInfoTagLoaderGYM::Load(const CStdString& strFileName, CMusicInfoTag& tag)
{
  tag.SetLoaded(false);

  if (!m_dll.Load())
    return false;

  m_dll.Init();

  m_gym = m_dll.LoadGYM(strFileName.c_str());
  if (!m_gym)
  {
    CLog::Log(LOGERROR,"MusicInfoTagLoaderGYM: failed to open GYM %s",strFileName.c_str());
    return false;
  }

  tag.SetURL(strFileName);

  tag.SetLoaded(false);
  char* szTitle = (char*)m_dll.GetTitle(m_gym); // no alloc
  if (szTitle)
    if( strcmp(szTitle,"") )
    {
      tag.SetTitle(szTitle);
      tag.SetLoaded(true);
    }

  char* szArtist = (char*)m_dll.GetArtist(m_gym); // no alloc
  if (szArtist)
    if( strcmp(szArtist,"") && tag.Loaded() )
      tag.SetArtist(szArtist);

  m_dll.FreeGYM(m_gym);
  m_gym = 0;

  return tag.Loaded();
}
示例#14
0
bool CMusicInfoTagLoaderAdplug::Load(const CStdString& strFileName, CMusicInfoTag& tag)
{
  tag.SetLoaded(false);

  if (!m_dll.Load())
    return false;

  m_adl = m_dll.LoadADL(strFileName.c_str());
  if (!m_adl)
  {
    CLog::Log(LOGERROR,"MusicInfoTagLoaderAdplug: failed to open %s",strFileName.c_str());
    return false;
  }

  tag.SetURL(strFileName);

  tag.SetLoaded(false);
  const char* szTitle = m_dll.GetTitle(m_adl); // no alloc
  if (szTitle)
    if( strcmp(szTitle,"") )
    {
      tag.SetTitle(szTitle);
      tag.SetLoaded(true);
    }

  const char* szArtist = m_dll.GetArtist(m_adl); // no alloc
  if( strcmp(szArtist,"") && tag.Loaded() )
    tag.SetArtist(szArtist);

  tag.SetDuration(m_dll.GetLength(m_adl)/1000);

  m_dll.FreeADL(m_adl);
  m_adl = 0;

  return tag.Loaded();
}
示例#15
0
bool CMusicInfoTagLoaderApe::Load(const CStdString& strFileName, CMusicInfoTag& tag)
{
  try
  {
    // retrieve the APE Tag info from strFileName
    // and put it in tag
    tag.SetURL(strFileName);
    CAPEv2Tag myTag;
    if (myTag.ReadTag((char*)strFileName.c_str())) // true to check ID3 tag as well
    {
      tag.SetTitle(myTag.GetTitle());
      tag.SetAlbum(myTag.GetAlbum());
      tag.SetArtist(myTag.GetArtist());
      tag.SetAlbumArtist(myTag.GetAlbumArtist());
      tag.SetGenre(myTag.GetGenre());
      tag.SetTrackNumber(myTag.GetTrackNum());
      tag.SetPartOfSet(myTag.GetDiscNum());
      tag.SetComment(myTag.GetComment());
      tag.SetLyrics(myTag.GetLyrics());
      SYSTEMTIME dateTime;
      ZeroMemory(&dateTime, sizeof(SYSTEMTIME));
      dateTime.wYear = atoi(myTag.GetYear());
      tag.SetRating(myTag.GetRating());
      tag.SetReleaseDate(dateTime);
      tag.SetLoaded();
      return true;
    }
  }
  catch (...)
  {
    CLog::Log(LOGERROR, "Tag loader ape: exception in file %s", strFileName.c_str());
  }

  tag.SetLoaded(false);
  return false;
}
示例#16
0
bool CPVRManager::UpdateItem(CFileItem& item)
{
  /* Don't update if a recording is played */
  if (item.IsPVRRecording())
    return false;

  if (!item.IsPVRChannel())
  {
    CLog::Log(LOGERROR, "CPVRManager - %s - no channel tag provided", __FUNCTION__);
    return false;
  }

  CSingleLock lock(m_critSection);
  if (!m_currentFile || *m_currentFile->GetPVRChannelInfoTag() == *item.GetPVRChannelInfoTag())
    return false;

  g_application.CurrentFileItem() = *m_currentFile;
  g_infoManager.SetCurrentItem(*m_currentFile);

  CPVRChannel* channelTag = item.GetPVRChannelInfoTag();
  CEpgInfoTag epgTagNow;
  bool bHasTagNow = channelTag->GetEPGNow(epgTagNow);

  if (channelTag->IsRadio())
  {
    CMusicInfoTag* musictag = item.GetMusicInfoTag();
    if (musictag)
    {
      musictag->SetTitle(bHasTagNow ? epgTagNow.Title() : g_localizeStrings.Get(19055));
      if (bHasTagNow)
        musictag->SetGenre(epgTagNow.Genre());
      musictag->SetDuration(bHasTagNow ? epgTagNow.GetDuration() : 3600);
      musictag->SetURL(channelTag->Path());
      musictag->SetArtist(channelTag->ChannelName());
      musictag->SetAlbumArtist(channelTag->ChannelName());
      musictag->SetLoaded(true);
      musictag->SetComment(StringUtils::EmptyString);
      musictag->SetLyrics(StringUtils::EmptyString);
    }
  }
  else
  {
    CVideoInfoTag *videotag = item.GetVideoInfoTag();
    if (videotag)
    {
      videotag->m_strTitle = bHasTagNow ? epgTagNow.Title() : g_localizeStrings.Get(19055);
      if (bHasTagNow)
        videotag->m_genre = epgTagNow.Genre();
      videotag->m_strPath = channelTag->Path();
      videotag->m_strFileNameAndPath = channelTag->Path();
      videotag->m_strPlot = bHasTagNow ? epgTagNow.Plot() : StringUtils::EmptyString;
      videotag->m_strPlotOutline = bHasTagNow ? epgTagNow.PlotOutline() : StringUtils::EmptyString;
      videotag->m_iEpisode = bHasTagNow ? epgTagNow.EpisodeNum() : 0;
    }
  }

  CPVRChannel* tagPrev = item.GetPVRChannelInfoTag();
  if (tagPrev && tagPrev->ChannelNumber() != m_LastChannel)
  {
    m_LastChannel         = tagPrev->ChannelNumber();
    m_LastChannelChanged  = XbmcThreads::SystemClockMillis();
  }
  if (XbmcThreads::SystemClockMillis() - m_LastChannelChanged >= (unsigned int) g_guiSettings.GetInt("pvrplayback.channelentrytimeout") && m_LastChannel != m_PreviousChannel[m_PreviousChannelIndex])
     m_PreviousChannel[m_PreviousChannelIndex ^= 1] = m_LastChannel;
  else
    m_LastChannelChanged = XbmcThreads::SystemClockMillis();

  return false;
}
示例#17
0
bool CTagLoaderTagLib::ParseTag(ASF::Tag *asf, EmbeddedArt *art, CMusicInfoTag& tag)
{
  if (!asf)
    return false;

  ReplayGain replayGainInfo;
  tag.SetTitle(asf->title().to8Bit(true));
  const ASF::AttributeListMap& attributeListMap = asf->attributeListMap();
  for (ASF::AttributeListMap::ConstIterator it = attributeListMap.begin(); it != attributeListMap.end(); ++it)
  {
    if (it->first == "Author")
      SetArtist(tag, GetASFStringList(it->second));
    else if (it->first == "WM/AlbumArtist")
      SetAlbumArtist(tag, GetASFStringList(it->second));
    else if (it->first == "WM/AlbumTitle")
      tag.SetAlbum(it->second.front().toString().to8Bit(true));
    else if (it->first == "WM/TrackNumber" ||
             it->first == "WM/Track")
    {
      if (it->second.front().type() == ASF::Attribute::DWordType)
        tag.SetTrackNumber(it->second.front().toUInt());
      else
        tag.SetTrackNumber(atoi(it->second.front().toString().toCString(true)));
    }
    else if (it->first == "WM/PartOfSet")
      tag.SetDiscNumber(atoi(it->second.front().toString().toCString(true)));
    else if (it->first == "WM/Genre")
      SetGenre(tag, GetASFStringList(it->second));
    else if (it->first == "WM/Mood")
      tag.SetMood(it->second.front().toString().to8Bit(true));
    else if (it->first == "WM/Composer")
      AddArtistRole(tag, "Composer", GetASFStringList(it->second));
    else if (it->first == "WM/Conductor")
      AddArtistRole(tag, "Conductor", GetASFStringList(it->second));
    //No ASF/WMA tag from Taglib for "ensemble"
    else if (it->first == "WM/Writer")
      AddArtistRole(tag, "Lyricist", GetASFStringList(it->second));
    else if (it->first == "WM/ModifiedBy")
      AddArtistRole(tag, "Remixer", GetASFStringList(it->second));
    else if (it->first == "WM/Engineer")
      AddArtistRole(tag, "Engineer", GetASFStringList(it->second));
    else if (it->first == "WM/Producer")
      AddArtistRole(tag, "Producer", GetASFStringList(it->second));
    else if (it->first == "WM/DJMixer")
      AddArtistRole(tag, "DJMixer", GetASFStringList(it->second));
    else if (it->first == "WM/Mixer")
      AddArtistRole(tag, "mixer", GetASFStringList(it->second));
    else if (it->first == "WM/Publisher")
    {} // Known unsupported, supress warnings
    else if (it->first == "WM/AlbumArtistSortOrder")
    {} // Known unsupported, supress warnings
    else if (it->first == "WM/ArtistSortOrder")
    {} // Known unsupported, supress warnings
    else if (it->first == "WM/Script")
    {} // Known unsupported, supress warnings
    else if (it->first == "WM/Year")
      tag.SetYear(atoi(it->second.front().toString().toCString(true)));
    else if (it->first == "MusicBrainz/Artist Id")
      tag.SetMusicBrainzArtistID(SplitMBID(GetASFStringList(it->second)));
    else if (it->first == "MusicBrainz/Album Id")
      tag.SetMusicBrainzAlbumID(it->second.front().toString().to8Bit(true));
    else if (it->first == "MusicBrainz/Album Artist")
      SetAlbumArtist(tag, GetASFStringList(it->second));
    else if (it->first == "MusicBrainz/Album Artist Id")
      tag.SetMusicBrainzAlbumArtistID(SplitMBID(GetASFStringList(it->second)));
    else if (it->first == "MusicBrainz/Track Id")
      tag.SetMusicBrainzTrackID(it->second.front().toString().to8Bit(true));
    else if (it->first == "MusicBrainz/Album Status")
    {}
    else if (it->first == "MusicBrainz/Album Type")
    {}
    else if (it->first == "MusicIP/PUID")
    {}
    else if (it->first == "replaygain_track_gain")
      replayGainInfo.ParseGain(ReplayGain::TRACK, it->second.front().toString().toCString(true));
    else if (it->first == "replaygain_album_gain")
      replayGainInfo.ParseGain(ReplayGain::ALBUM, it->second.front().toString().toCString(true));
    else if (it->first == "replaygain_track_peak")
      replayGainInfo.ParsePeak(ReplayGain::TRACK, it->second.front().toString().toCString(true));
    else if (it->first == "replaygain_album_peak")
      replayGainInfo.ParsePeak(ReplayGain::ALBUM, it->second.front().toString().toCString(true));
    else if (it->first == "WM/Picture")
    { // picture
      ASF::Picture pic = it->second.front().toPicture();
      tag.SetCoverArtInfo(pic.picture().size(), pic.mimeType().toCString());
      if (art)
        art->set(reinterpret_cast<const uint8_t *>(pic.picture().data()), pic.picture().size(), pic.mimeType().toCString());
    }
    else if (g_advancedSettings.m_logLevel == LOG_LEVEL_MAX)
      CLog::Log(LOGDEBUG, "unrecognized ASF tag name: %s", it->first.toCString(true));
  }
  // artist may be specified in the ContentDescription block rather than using the 'Author' attribute.
  if (tag.GetArtist().empty())
    tag.SetArtist(asf->artist().toCString(true));

  if (asf->comment() != String::null)
    tag.SetComment(asf->comment().toCString(true));
  tag.SetReplayGain(replayGainInfo);
  tag.SetLoaded(true);
  return true;
}
void CLastFMDirectory::AddListEntry(const char *name, const char *artist, const char *count, const char *date, const char *icon, CStdString strPath, CFileItemList &items)
{
  CStdString strName;
  CStdString strCount;
  CFileItemPtr pItem(new CFileItem);
  CMusicInfoTag* musicinfotag = pItem->GetMusicInfoTag();
  musicinfotag->SetTitle(name);

  if (artist)
  {
    strName.Format("%s - %s", artist, name);
    musicinfotag->SetArtist(artist);
  }
  else
  {
    strName = name;
  }

  if (count)
  {
    pItem->SetLabel2(count);
    pItem->m_dwSize = _atoi64(count) * 100000000;

    const char *dot;
    if ((dot = (const char *)strstr(count, ".")))
      pItem->m_dwSize += _atoi64(dot + 1);
  }

  pItem->SetLabel(strName);
  pItem->m_strPath = strPath;
  pItem->m_bIsFolder = true;
  pItem->SetLabelPreformated(true);

  if (date)
  {
    LONGLONG ll = Int32x32To64(atoi(date), 10000000) + 116444736000000000LL;
    FILETIME ft;

    ft.dwLowDateTime = (DWORD)(ll & 0xFFFFFFFF);
    ft.dwHighDateTime = (DWORD)(ll >> 32);

    pItem->m_dateTime=ft;
  }

  pItem->SetCanQueue(false);
  //the extra info is used in the mediawindows to determine which items are needed in the contextmenu
  if (m_objname.Equals(g_guiSettings.GetString("lastfm.username")))
  {
    if (m_objrequest.Equals("recentbannedtracks"))
    {
      pItem->SetExtraInfo("lastfmbanned");
    }
    else if (m_objrequest.Equals("recentlovedtracks"))
    {
      pItem->SetExtraInfo("lastfmloved");
    }
  }
  if (pItem->GetExtraInfo().IsEmpty() && strPath.Find("lastfm://xbmc") >= 0)
  {
    pItem->SetExtraInfo("lastfmitem");
  }

  // icons? would probably take too long to retrieve them all
  items.Add(pItem);
}
示例#19
0
void CMusicInfoTagLoaderMP4::ParseTag( unsigned int metaKey, const char* pMetaData, int metaSize, CMusicInfoTag& tag)
{
  switch ( metaKey )
  {
  case g_TitleAtomName:
    {
      // We need to zero-terminate the string, which needs workspace..
      auto_aptr<char> dataWorkspace( new char[ metaSize + 1 ] );
      memcpy( dataWorkspace.get(), pMetaData, metaSize );
      dataWorkspace[ metaSize ] = '\0';

      // we use utf8 internally
      tag.SetLoaded( true );
      tag.SetTitle( dataWorkspace.get() );

      break;
    }

  case g_ArtistAtomName:
    {
      // We need to zero-terminate the string, which needs workspace..
      auto_aptr<char> dataWorkspace( new char[ metaSize + 1 ] );
      memcpy( dataWorkspace.get(), pMetaData, metaSize );
      dataWorkspace[ metaSize ] = '\0';

      tag.SetArtist( dataWorkspace.get() );

      break;
    }

  case g_AlbumAtomName:
    {
      // We need to zero-terminate the string, which needs workspace..
      auto_aptr<char> dataWorkspace( new char[ metaSize + 1 ] );
      memcpy( dataWorkspace.get(), pMetaData, metaSize );
      dataWorkspace[ metaSize ] = '\0';

      tag.SetAlbum( dataWorkspace.get() );

      break;
    }

  case g_AlbumArtistAtomName:
    {
      // We need to zero-terminate the string, which needs workspace..
      auto_aptr<char> dataWorkspace( new char[ metaSize + 1 ] );
      memcpy( dataWorkspace.get(), pMetaData, metaSize );
      dataWorkspace[ metaSize ] = '\0';

      tag.SetAlbumArtist( dataWorkspace.get() );

      break;
    }
  case g_DayAtomName:
    {
      // We need to zero-terminate the string, which needs workspace..
      auto_aptr<char> dataWorkspace( new char[ metaSize + 1 ] );
      memcpy( dataWorkspace.get(), pMetaData, metaSize );
      dataWorkspace[ metaSize ] = '\0';

      SYSTEMTIME dateTime;
      dateTime.wYear = atoi( dataWorkspace.get() );
      tag.SetReleaseDate( dateTime );

      break;
    }

  case g_GenreAtomName:
    {
      // When a genre number is specified, we need to translate to a string for display..
      // Note that AAC/iTunes genre numbers are the same as ID3 numbers, but are offset by 1.
      const char* pGenre = ID3_V1GENRE2DESCRIPTION( (unsigned char)pMetaData[ 1 ] - 1 );
      if ( pGenre )
      {
        tag.SetGenre( pGenre );
      }

      break;
    }
  case g_CompilationAtomName:
    {
      if (metaSize == 1)
        m_isCompilation = *pMetaData == 1;
      break;
    }
  case g_CommentAtomName:
    {
      // We need to zero-terminate the string, which needs workspace..
      auto_aptr<char> dataWorkspace( new char[ metaSize + 1 ] );
      memcpy( dataWorkspace.get(), pMetaData, metaSize );
      dataWorkspace[ metaSize ] = '\0';

      tag.SetComment( dataWorkspace.get() );
      break;
    }
  case g_LyricsAtomName:
    {
      // We need to zero-terminate the string, which needs workspace..
      auto_aptr<char> dataWorkspace( new char[ metaSize + 1 ] );
      memcpy( dataWorkspace.get(), pMetaData, metaSize );
      dataWorkspace[ metaSize ] = '\0';

      tag.SetLyrics( dataWorkspace.get() );
      break;
    }
  case g_CustomGenreAtomName:
    {
      // We need to zero-terminate the string, which needs workspace..
      auto_aptr<char> dataWorkspace( new char[ metaSize + 1 ] );
      memcpy( dataWorkspace.get(), pMetaData, metaSize );
      dataWorkspace[ metaSize ] = '\0';

      tag.SetGenre( dataWorkspace.get() );

      break;
    }

  case g_TrackNumberAtomName:
    {
      tag.SetTrackNumber( pMetaData[ 3 ] );

      break;
    }

  case g_DiscNumberAtomName:
    {
      tag.SetPartOfSet( pMetaData[ 3 ] );

      break;
    }

  case g_CoverArtAtomName:
    {
      // This cover-art handling is pretty much what was in the old MP4 tag processing code..

      // note that according to http://atomicparsley.sourceforge.net/mpeg-4files.html the type
      // of image (PNG=14 or JPG=13) is contained in pMetadata[-5] but we currently don't use this.
      m_thumbSize = metaSize;
      delete[] m_thumbData;
      m_thumbData = new BYTE[m_thumbSize];
      if (m_thumbData)
        memcpy(m_thumbData, pMetaData, metaSize);
      break;
    }
  default:
    break;
  }
}
bool CPVRManager::UpdateItem(CFileItem& item)
{
  /* Don't update if a recording is played */
  if (item.IsPVRRecording())
    return false;

  if (!item.IsPVRChannel())
  {
    CLog::Log(LOGERROR, "CPVRManager - %s - no channel tag provided", __FUNCTION__);
    return false;
  }

  CSingleLock lock(m_critSection);
  if (!m_currentFile || *m_currentFile->GetPVRChannelInfoTag() == *item.GetPVRChannelInfoTag())
    return false;

  g_application.CurrentFileItem() = *m_currentFile;
  g_infoManager.SetCurrentItem(*m_currentFile);

  CPVRChannel* channelTag = item.GetPVRChannelInfoTag();
  CEpgInfoTag epgTagNow;
  bool bHasTagNow = channelTag->GetEPGNow(epgTagNow);

  if (channelTag->IsRadio())
  {
    CMusicInfoTag* musictag = item.GetMusicInfoTag();
    if (musictag)
    {
      musictag->SetTitle(bHasTagNow ?
          epgTagNow.Title() :
          g_guiSettings.GetBool("epg.hidenoinfoavailable") ?
              StringUtils::EmptyString :
              g_localizeStrings.Get(19055)); // no information available
      if (bHasTagNow)
        musictag->SetGenre(epgTagNow.Genre());
      musictag->SetDuration(bHasTagNow ? epgTagNow.GetDuration() : 3600);
      musictag->SetURL(channelTag->Path());
      musictag->SetArtist(channelTag->ChannelName());
      musictag->SetAlbumArtist(channelTag->ChannelName());
      musictag->SetLoaded(true);
      musictag->SetComment(StringUtils::EmptyString);
      musictag->SetLyrics(StringUtils::EmptyString);
    }
  }
  else
  {
    CVideoInfoTag *videotag = item.GetVideoInfoTag();
    if (videotag)
    {
      videotag->m_strTitle = bHasTagNow ?
          epgTagNow.Title() :
          g_guiSettings.GetBool("epg.hidenoinfoavailable") ?
              StringUtils::EmptyString :
              g_localizeStrings.Get(19055); // no information available
      if (bHasTagNow)
        videotag->m_genre = epgTagNow.Genre();
      videotag->m_strPath = channelTag->Path();
      videotag->m_strFileNameAndPath = channelTag->Path();
      videotag->m_strPlot = bHasTagNow ? epgTagNow.Plot() : StringUtils::EmptyString;
      videotag->m_strPlotOutline = bHasTagNow ? epgTagNow.PlotOutline() : StringUtils::EmptyString;
      videotag->m_iEpisode = bHasTagNow ? epgTagNow.EpisodeNum() : 0;
    }
  }

  return false;
}
示例#21
0
bool CMusicInfoTagLoaderCDDA::Load(const std::string& strFileName, CMusicInfoTag& tag, EmbeddedArt *art)
{
#ifdef HAS_DVD_DRIVE
  try
  {
    tag.SetURL(strFileName);
    bool bResult = false;

    // Get information for the inserted disc
    CCdInfo* pCdInfo = g_mediaManager.GetCdInfo();
    if (pCdInfo == NULL)
      return bResult;

    // Prepare cddb
    Xcddb cddb;
    cddb.setCacheDir(CProfilesManager::GetInstance().GetCDDBFolder());

    int iTrack = atoi(strFileName.substr(13, strFileName.size() - 13 - 5).c_str());

    // duration is always available
    tag.SetDuration( ( pCdInfo->GetTrackInformation(iTrack).nMins * 60 )
                     + pCdInfo->GetTrackInformation(iTrack).nSecs );

    // Only load cached cddb info in this tag loader, the internet database query is made in CCDDADirectory
    if (pCdInfo->HasCDDBInfo() && cddb.isCDCached(pCdInfo))
    {
      // get cddb information
      if (cddb.queryCDinfo(pCdInfo))
      {
        // Fill the fileitems music tag with cddb information, if available
        std::string strTitle = cddb.getTrackTitle(iTrack);
        if (!strTitle.empty())
        {
          // Tracknumber
          tag.SetTrackNumber(iTrack);

          // Title
          tag.SetTitle(strTitle);

          // Artist: Use track artist or disc artist
          std::string strArtist = cddb.getTrackArtist(iTrack);
          if (strArtist.empty())
            cddb.getDiskArtist(strArtist);
          tag.SetArtist(strArtist);

          // Album
          std::string strAlbum;
          cddb.getDiskTitle( strAlbum );
          tag.SetAlbum(strAlbum);

          // Album Artist
          std::string strAlbumArtist;
          cddb.getDiskArtist(strAlbumArtist);
          tag.SetAlbumArtist(strAlbumArtist);

          // Year
          SYSTEMTIME dateTime;
          dateTime.wYear = atoi(cddb.getYear().c_str());
          tag.SetReleaseDate( dateTime );

          // Genre
          tag.SetGenre( cddb.getGenre() );

          tag.SetLoaded(true);
          bResult = true;
        }
      }
    }
    else
    {
      // No cddb info, maybe we have CD-Text
      trackinfo ti = pCdInfo->GetTrackInformation(iTrack);

      // Fill the fileitems music tag with CD-Text information, if available
      std::string strTitle = ti.cdtext[CDTEXT_TITLE];
      if (!strTitle.empty())
      {
        // Tracknumber
        tag.SetTrackNumber(iTrack);

        // Title
        tag.SetTitle(strTitle);

        // Get info for track zero, as we may have and need CD-Text Album info
        xbmc_cdtext_t discCDText = pCdInfo->GetDiscCDTextInformation();

        // Artist: Use track artist or disc artist
        std::string strArtist = ti.cdtext[CDTEXT_PERFORMER];
        if (strArtist.empty())
          strArtist = discCDText[CDTEXT_PERFORMER];
        tag.SetArtist(strArtist);

        // Album
        std::string strAlbum;
        strAlbum = discCDText[CDTEXT_TITLE];
        tag.SetAlbum(strAlbum);

        // Genre: use track or disc genre
        std::string strGenre = ti.cdtext[CDTEXT_GENRE];
        if (strGenre.empty())
          strGenre = discCDText[CDTEXT_GENRE];
        tag.SetGenre( strGenre );

        tag.SetLoaded(true);
        bResult = true;
      }
    }
    return bResult;
  }
  catch (...)
  {
    CLog::Log(LOGERROR, "Tag loader CDDB: exception in file %s", strFileName.c_str());
  }

#endif

  tag.SetLoaded(false);

  return false;
}
示例#22
0
void CShoutcastRipFile::GetMusicInfoTag(CMusicInfoTag& tag)
{
  if ( m_recState.bFilenameSet && m_recState.bStreamSet )
  {
    tag.Clear();
    //now distinguish between
    if ( m_recState.bHasMetaData )
    {
      //The filename of RM will be something like "Oasis - Champagne Supernova", thus
      //So, we will make a file i.e "f:music\Record\Limbik Frequencies\Oasis - Champagne Supernova.mp3"
      //get the artist and trackname
      char szArtist[1124];
      char szTrackName[1124];
      char szTokens[1024];
      char* cursor;
      bool tokenUsed = false;
      bool foundArtist = false;
      bool foundTrackName = false;
      strcpy( szTokens, m_szFileName );
      cursor = strtok(szTokens, "-");
      if (!cursor) cursor = strtok(szTokens, ",");
      while (cursor != NULL)
      {
        tokenUsed = false;
        //we will look for two strings,
        //sometimes there's a track number, wich we will throw away
        if ( !foundArtist )
        {
          if ( atoi( cursor ) == 0 )
          {
            //its a string
            strcpy(szArtist, cursor );
            foundArtist = true;
            tokenUsed = true;
          }
        }
        if ( !foundTrackName && !tokenUsed )
        {
          if ( atoi( cursor ) == 0 )
          {
            //its a string
            strcpy(szTrackName, cursor );
            foundTrackName = true;
            tokenUsed = true;
          }
        }
        cursor = strtok (NULL, "-");
        //if (!cursor) cursor=strtok(NULL,",");
      }
      if ( foundTrackName )         //lets hope we found a track name, else it will be unknown
        tag.SetTitle(szTrackName);
      else
        tag.SetTitle(m_szStreamName);
      if ( foundArtist )          //lets hope we found an artist, else it will be unknown
        tag.SetArtist(szArtist);
      tag.SetAlbum(m_szStreamName);  //Jazzmusique (Album is like Directory)
    }
    else
    {
      tag.Clear();
      tag.SetTitle(m_szStreamName);
    }

  }
}
示例#23
0
// Based on MediaInfo
// by J�r�me Martinez, [email protected]
// http://sourceforge.net/projects/mediainfo/
bool CMusicInfoTagLoaderWMA::Load(const CStdString& strFileName, CMusicInfoTag& tag)
{
  try
  {
    tag.SetLoaded(false);
    CFile file;
    if (!file.Open(strFileName)) return false;

    tag.SetURL(strFileName);

    // Note that we're reading in a bit more than the buffer size, because the 'peek'ing
    // below is dealing with integers and reads off the end. Rather than change
    // all the checks below, I've simply allocated a bigger buffer.
    const unsigned int bufferSize = 256*1024;
    auto_aptr<unsigned char> pData(new unsigned char[bufferSize+32]);
    file.Read(pData.get(), bufferSize+32);
    file.Close();

    unsigned int iOffset;
    unsigned int* pDataI;
    CStdString16 utf16String;

    //Play time
    iOffset = 0;
    pDataI = (unsigned int*)pData.get();
    while (!(pDataI[0] == 0x75B22630 && pDataI[1] == 0x11CF668E && pDataI[2] == 0xAA00D9A6 && pDataI[3] == 0x6CCE6200) && iOffset <= bufferSize - 4)
    {
      iOffset++;
      pDataI = (unsigned int*)(pData.get() + iOffset);
    }
    if (iOffset > bufferSize - 4)
      return false;

    //Play time
    iOffset = 0;
    pDataI = (unsigned int*)pData.get();
    while (!(pDataI[0] == 0x8CABDCA1 && pDataI[1] == 0x11CFA947 && pDataI[2] == 0xC000E48E && pDataI[3] == 0x6553200C) && iOffset <= bufferSize - 4)
    {
      iOffset++;
      pDataI = (unsigned int*)(pData.get() + iOffset);
    }
    if (iOffset <= bufferSize - 4)
    {
      iOffset += 64;
      pDataI = (unsigned int*)(pData.get() + iOffset);
      float F1 = (float)pDataI[1];
      F1 = F1 * 0x10000 * 0x10000 + pDataI[0];
      tag.SetDuration((long)((F1 / 10000) / 1000)); // from milliseconds to seconds
    }

    //Description  Title
    iOffset = 0;
    pDataI = (unsigned int*)pData.get();
    while (!(pDataI[0] == 0x75B22633 && pDataI[1] == 0x11CF668E && pDataI[2] == 0xAA00D9A6 && pDataI[3] == 0x6CCE6200) && iOffset <= bufferSize - 4)
    {
      iOffset++;
      pDataI = (unsigned int*)(pData.get() + iOffset);
    }
    if (iOffset <= bufferSize - 4)
    {
      iOffset += 24;
      int nTitleSize = pData[iOffset + 0] + pData[iOffset + 1] * 0x100;
      int nAuthorSize = pData[iOffset + 2] + pData[iOffset + 3] * 0x100;
      //int nCopyrightSize = pData[iOffset + 4] + pData[iOffset + 5] * 0x100;
      //int nCommentsSize = pData[iOffset + 6] + pData[iOffset + 7] * 0x100;

      iOffset += 10;

      CStdString utf8String;
      if (nTitleSize)
      {
        // TODO: UTF-8 Do we need to "fixString" these strings at all?
        utf16String = (uint16_t*)(pData.get()+iOffset);
        g_charsetConverter.utf16LEtoUTF8(utf16String, utf8String);
        tag.SetTitle(utf8String);
      }

      if (nAuthorSize)
      {
        utf8String = "";
        utf16String = (uint16_t*)(pData.get() + iOffset + nTitleSize);
        g_charsetConverter.utf16LEtoUTF8(utf16String, utf8String);
        tag.SetArtist(utf8String);
      }

      //General(ZT("Copyright"))=(LPWSTR)(pData.get()+iOffset+(nTitleSize+nAuthorSize));
      //General(ZT("Comments"))=(LPWSTR)(pData.get()+iOffset+(nTitleSize+nAuthorSize+nCopyrightSize));
    }

    // Maybe these information can be usefull in the future

    //Info audio
    //iOffset=0;
    //pDataI=(unsigned int*)pData;
    //while (!(pDataI[0]==0xF8699E40 && pDataI[1]==0x11CF5B4D && pDataI[2]==0x8000FDA8 && pDataI[3]==0x2B445C5F) && iOffset<=bufferSize-4)
    //{
    //iOffset++;
    //pDataI=(unsigned int*)(pData+iOffset);
    //}
    //if (iOffset<=bufferSize-4)
    //{
    //iOffset+=54;
    ////Codec
    //TCHAR C1[30];
    //_itoa(pData[iOffset]+pData[iOffset+1]*0x100, C1, 16);
    //CStdString Codec=C1;
    //while (Codec.size()<4)
    //  Codec='0'+Codec;
    //Audio[0](ZT("Codec"))=Codec;
    //Audio[0](ZT("Channels"))=pData[iOffset+2]; //2 octets
    //pDataI=(unsigned int*)(pData+iOffset);
    //Audio[0](ZT("SamplingRate"))=pDataI[1];
    //Audio[0](ZT("BitRate"))=pDataI[2]*8;
    //}

    //Info video
    //iOffset=0;
    //pDataI=(unsigned int*)pData;
    //while (!(pDataI[0]==0xBC19EFC0 && pDataI[1]==0x11CF5B4D && pDataI[2]==0x8000FDA8 && pDataI[3]==0x2B445C5F) && iOffset<=bufferSize-4)
    //{
    //iOffset++;
    //pDataI=(unsigned int*)(pData+iOffset);
    //}
    //if (iOffset<=bufferSize-4)
    //{
    //iOffset+=54;
    //iOffset+=15;
    //pDataI=(unsigned int*)(pData+iOffset);
    //Video[0](ZT("Width"))=pDataI[0];
    //Video[0](ZT("Height"))=pDataI[1];
    //Codec
    //unsigned char C1[5]; C1[4]='\0';
    //C1[0]=pData[iOffset+12+0]; C1[1]=pData[iOffset+12+1]; C1[2]=pData[iOffset+12+2]; C1[3]=pData[iOffset+12+3];
    //Video[0](ZT("Codec"))=wxString((char*)C1,wxConvUTF8).c_str();
    //}


    //Read extended metadata
    iOffset = 0;
    pDataI = (unsigned int*)pData.get();
    while (!(pDataI[0] == 0xD2D0A440 && pDataI[1] == 0x11D2E307 && pDataI[2] == 0xA000F097 && pDataI[3] == 0x50A85EC9) && iOffset <= bufferSize - 4)
    {
      iOffset++;
      pDataI = (unsigned int*)(pData.get() + iOffset);
    }

    if (iOffset <= bufferSize - 4)
    {
      iOffset += 24;

      // Walk through all frames in the file
      int iNumOfFrames = pData[iOffset] + pData[iOffset + 1] * 0x100;
      iOffset += 2;
      for (int Pos = 0; Pos < iNumOfFrames; Pos++)
      {
        int iFrameNameSize = pData[iOffset] + (pData[iOffset + 1] * 0x100);
        iOffset += 2;

        // Get frame name
        CStdString strFrameName;
        CStdStringW wString = "";
        utf16String = (uint16_t*)(pData.get() + iOffset);
        g_charsetConverter.utf16LEtoUTF8(utf16String, strFrameName);
        iOffset += iFrameNameSize;

        // Get datatype of frame
        int iFrameType = pData[iOffset] + pData[iOffset + 1];
        iOffset += 2;

        // Size of frame value
        unsigned int iValueSize = pData[iOffset] + (pData[iOffset + 1] * 0x100);
        iOffset += 2;

        // Sanity check for buffer size
        if (iValueSize + iOffset > bufferSize)
        {
          CLog::Log(LOGWARNING, "%s(%s) failed due to tag being larger than %ul", __FUNCTION__, strFileName.c_str(), bufferSize);
          break;
        }

        // Parse frame value and fill
        // tag with extended metadata
        if (iFrameType == WMT_TYPE_STRING && iValueSize > 0)
        {
          // TODO: UTF-8: Do we need to "fixString" these utf8 strings?
          CStdString utf8String;
          utf16String = (uint16_t*)(pData.get() + iOffset);
          g_charsetConverter.utf16LEtoUTF8(utf16String, utf8String);
          SetTagValueString(strFrameName, utf8String, tag);
        }
        else if (iFrameType == WMT_TYPE_BINARY && iValueSize > 0)
        {
          unsigned char* pValue = (unsigned char*)(pData.get() + iOffset); // Raw data
          SetTagValueBinary(strFrameName, pValue, tag);
        }
        else if (iFrameType == WMT_TYPE_BOOL && iValueSize > 0)
        {
          SetTagValueBool(strFrameName, pData[iOffset] != 0, tag);
        }
        else if (iFrameType == WMT_TYPE_DWORD && iValueSize > 0)
        {
          uint32_t value = pData[iOffset] + pData[iOffset + 1] * 0x100 + pData[iOffset + 2] * 0x10000 + pData[iOffset + 3] * 0x1000000;
          SetTagValueUnsigned(strFrameName, value, tag);
        }
        else if (iFrameType == WMT_TYPE_QWORD && iValueSize > 0)
        {
          //DWORD qwValue = pData[iOffset] + pData[iOffset + 1] * 0x100 + pData[iOffset + 2] * 0x10000 + pData[iOffset + 3] * 0x1000000;
        }
        else if (iFrameType == WMT_TYPE_WORD && iValueSize > 0)
        {
          //WORD wValue = pData[iOffset] + pData[iOffset + 1] * 0x100;
        }

        // parse next frame
        iOffset += iValueSize;
      }
    }

    //Read extended metadata 2
    iOffset = 0;
    pDataI = (unsigned int*)pData.get();
    while (!(pDataI[0] == 0x44231C94 && pDataI[1] == 0x49D19498 && pDataI[2] == 0x131D41A1 && pDataI[3] == 0x5470454E) && iOffset <= bufferSize - 4)
    {
      iOffset++;
      pDataI = (unsigned int*)(pData.get() + iOffset);
    }

    if (iOffset <= bufferSize - 4)
    {
      iOffset += 24;

      // Walk through all frames in the file
      int iNumOfFrames = pData[iOffset] + pData[iOffset + 1] * 0x100;
      iOffset += 6;
      for (int Pos = 0; Pos < iNumOfFrames; Pos++)
      {
        int iFrameNameSize = pData[iOffset] + (pData[iOffset + 1] * 0x100);
        iOffset += 2;

        // Get datatype of frame
        int iFrameType = pData[iOffset] + pData[iOffset + 1];
        iOffset += 2;

        // Size of frame value
        unsigned int iValueSize = pData[iOffset] + (pData[iOffset + 1] * 0x100) + (pData[iOffset + 2] * 0x10000);
        iOffset += 4;

        // Get frame name
        CStdString strFrameName = "";
        CStdStringW wString = "";
        utf16String = (uint16_t*)(pData.get() + iOffset);
        g_charsetConverter.utf16LEtoUTF8(utf16String, strFrameName);
        iOffset += iFrameNameSize;

        // Sanity check for buffer size
        if (iValueSize + iOffset > bufferSize)
        {
          CLog::Log(LOGWARNING, "%s(%s) failed due to tag being larger than %ul", __FUNCTION__, strFileName.c_str(), bufferSize);
          break;
        }

        // Parse frame value and fill
        // tag with extended metadata
        if (iFrameType == WMT_TYPE_STRING && iValueSize > 0)
        {
          // TODO: UTF-8: Do we need to "fixString" these utf8 strings?
          CStdString utf8String;
          utf16String = (uint16_t*)(pData.get() + iOffset);
          g_charsetConverter.utf16LEtoUTF8(utf16String, utf8String);
          SetTagValueString(strFrameName, utf8String, tag);
        }
        else if (iFrameType == WMT_TYPE_BINARY && iValueSize > 0)
        {
          unsigned char* pValue = (unsigned char*)(pData.get() + iOffset); // Raw data
          SetTagValueBinary(strFrameName, pValue, tag);
        }
        else if (iFrameType == WMT_TYPE_BOOL && iValueSize > 0)
        {
          SetTagValueBool(strFrameName, pData[iOffset] != 0, tag);
        }
        else if (iFrameType == WMT_TYPE_DWORD && iValueSize > 0)
        {
          uint32_t value = pData[iOffset] + pData[iOffset + 1] * 0x100 + pData[iOffset + 2] * 0x10000 + pData[iOffset + 3] * 0x1000000;
          SetTagValueUnsigned(strFrameName, value, tag);
        }
        else if (iFrameType == WMT_TYPE_QWORD && iValueSize > 0)
        {
          //DWORD qwValue = pData[iOffset] + pData[iOffset + 1] * 0x100 + pData[iOffset + 2] * 0x10000 + pData[iOffset + 3] * 0x1000000;
        }
        else if (iFrameType == WMT_TYPE_WORD && iValueSize > 0)
        {
          //WORD wValue = pData[iOffset] + pData[iOffset + 1] * 0x100;
        }

        // parse next frame
        iOffset += iValueSize + 4;
      }
    }

    tag.SetLoaded(true);
    return true;
  }
  catch (...)
  {
    CLog::Log(LOGERROR, "Tag loader wma: exception in file %s", strFileName.c_str());
  }

  tag.SetLoaded(false);
  return false;
}
示例#24
0
void CMusicInfoTagLoaderWMA::SetTagValueString(const CStdString& strFrameName, const CStdString& strValue, CMusicInfoTag& tag)
{
  if (strFrameName == "WM/AlbumTitle")
  {
    tag.SetAlbum(strValue);
  }
  else if (strFrameName == "WM/AlbumArtist")
  {
    if (tag.GetAlbumArtist().IsEmpty()) tag.SetAlbumArtist(strValue);
  }
  else if (strFrameName == "Author")
  {
    // Multiple artists are stored in multiple "Author" tags we have get them
    // separatly and merge them to our system
    if (tag.GetArtist().IsEmpty())
      tag.SetArtist(strValue);
    else
      tag.SetArtist(tag.GetArtist() + g_advancedSettings.m_musicItemSeparator + strValue);
  }
  else if (strFrameName == "WM/TrackNumber")
  {
    if (tag.GetTrackNumber() <= 0) tag.SetTrackNumber(atoi(strValue.c_str()));
  }
  else if (strFrameName == "WM/PartOfSet")
  {
    tag.SetPartOfSet(atoi(strValue.c_str()));
  }
  //else if (strFrameName=="WM/Track") // Old Tracknumber, should not be used anymore
  else if (strFrameName == "WM/Year")
  {
    SYSTEMTIME dateTime;
    dateTime.wYear = atoi(strValue.c_str());
    tag.SetReleaseDate(dateTime);
  }
  else if (strFrameName == "WM/Genre")
  {
    // Multiple genres are stared in multiple "WM/Genre" tags we have to get them
    // separatly and merge them to our system
    if (tag.GetGenre().IsEmpty())
      tag.SetGenre(strValue);
    else
      tag.SetGenre(tag.GetGenre() + g_advancedSettings.m_musicItemSeparator + strValue);
  }
  else if (strFrameName == "WM/Lyrics")
  {
    tag.SetLyrics(strValue);
  }
  //else if (strFrameName=="WM/DRM")
  //{
  // // File is DRM protected
  // pwszValue;
  //}
  //else if (strFrameName=="WM/Codec")
  //{
  // pwszValue;
  //}
  //else if (strFrameName=="WM/BeatsPerMinute")
  //{
  // pwszValue;
  //}
  //else if (strFrameName=="WM/Mood")
  //{
  // pwszValue;
  //}
  //else if (strFrameName=="WM/RadioStationName")
  //{
  // pwszValue;
  //}
  //else if (strFrameName=="WM/RadioStationOwner")
  //{
  // pwszValue;
  //}
}
void CMusicInfoTagLoaderMP4::ParseTag( unsigned int metaKey, const char* pMetaData, int metaSize, CMusicInfoTag& tag, EmbeddedArt *art)
{
  switch ( metaKey )
  {
  case g_TitleAtomName:
    {
      // We need to zero-terminate the string, which needs workspace..
      auto_aptr<char> dataWorkspace( new char[ metaSize + 1 ] );
      memcpy( dataWorkspace.get(), pMetaData, metaSize );
      dataWorkspace[ metaSize ] = '\0';

      // we use utf8 internally
      tag.SetLoaded( true );
      tag.SetTitle( dataWorkspace.get() );

      break;
    }

  case g_ArtistAtomName:
    {
      // We need to zero-terminate the string, which needs workspace..
      auto_aptr<char> dataWorkspace( new char[ metaSize + 1 ] );
      memcpy( dataWorkspace.get(), pMetaData, metaSize );
      dataWorkspace[ metaSize ] = '\0';

      tag.SetArtist( dataWorkspace.get() );

      break;
    }

  case g_AlbumAtomName:
    {
      // We need to zero-terminate the string, which needs workspace..
      auto_aptr<char> dataWorkspace( new char[ metaSize + 1 ] );
      memcpy( dataWorkspace.get(), pMetaData, metaSize );
      dataWorkspace[ metaSize ] = '\0';

      tag.SetAlbum( dataWorkspace.get() );

      break;
    }

  case g_AlbumArtistAtomName:
    {
      // We need to zero-terminate the string, which needs workspace..
      auto_aptr<char> dataWorkspace( new char[ metaSize + 1 ] );
      memcpy( dataWorkspace.get(), pMetaData, metaSize );
      dataWorkspace[ metaSize ] = '\0';

      tag.SetAlbumArtist( dataWorkspace.get() );

      break;
    }
  case g_DayAtomName:
    {
      // We need to zero-terminate the string, which needs workspace..
      auto_aptr<char> dataWorkspace( new char[ metaSize + 1 ] );
      memcpy( dataWorkspace.get(), pMetaData, metaSize );
      dataWorkspace[ metaSize ] = '\0';

      SYSTEMTIME dateTime;
      dateTime.wYear = atoi( dataWorkspace.get() );
      tag.SetReleaseDate( dateTime );

      break;
    }

  case g_GenreAtomName:
    {
      // When a genre number is specified, we need to translate to a string for display..
      // Note that AAC/iTunes genre numbers are the same as ID3 numbers, but are offset by 1.
      const char* pGenre = ID3_V1GENRE2DESCRIPTION( (unsigned char)pMetaData[ 1 ] - 1 );
      if ( pGenre )
      {
        tag.SetGenre( pGenre );
      }

      break;
    }
  case g_CompilationAtomName:
    {
      if (metaSize == 1)
        tag.SetCompilation(*pMetaData == 1);
      break;
    }
  case g_CommentAtomName:
    {
      // We need to zero-terminate the string, which needs workspace..
      auto_aptr<char> dataWorkspace( new char[ metaSize + 1 ] );
      memcpy( dataWorkspace.get(), pMetaData, metaSize );
      dataWorkspace[ metaSize ] = '\0';

      tag.SetComment( dataWorkspace.get() );
      break;
    }
  case g_LyricsAtomName:
    {
      // We need to zero-terminate the string, which needs workspace..
      auto_aptr<char> dataWorkspace( new char[ metaSize + 1 ] );
      memcpy( dataWorkspace.get(), pMetaData, metaSize );
      dataWorkspace[ metaSize ] = '\0';

      tag.SetLyrics( dataWorkspace.get() );
      break;
    }
  case g_CustomGenreAtomName:
    {
      // We need to zero-terminate the string, which needs workspace..
      auto_aptr<char> dataWorkspace( new char[ metaSize + 1 ] );
      memcpy( dataWorkspace.get(), pMetaData, metaSize );
      dataWorkspace[ metaSize ] = '\0';

      tag.SetGenre( dataWorkspace.get() );

      break;
    }

  case g_TrackNumberAtomName:
    {
      tag.SetTrackNumber( (unsigned char)pMetaData[ 3 ] );

      break;
    }

  case g_DiscNumberAtomName:
    {
      tag.SetPartOfSet( (unsigned char)pMetaData[ 3 ] );

      break;
    }

  case g_CoverArtAtomName:
    {
      // This cover-art handling is pretty much what was in the old MP4 tag processing code..

      // note that according to http://atomicparsley.sourceforge.net/mpeg-4files.html the type
      // of image (PNG=14 or JPG=13) is contained in pMetadata[-5]
      std::string mimeType;
      if (pMetaData[-5] == 13)
        mimeType = "image/jpeg";
      else if (pMetaData[-5] == 14)
        mimeType = "image/png";
      else
        CLog::Log(LOGDEBUG, "Unknown art mimetype %d", pMetaData[-5]);

      tag.SetCoverArtInfo(metaSize, mimeType);
      if (art)
        art->set((const uint8_t*)pMetaData, metaSize, mimeType);
      break;
    }
  default:
    break;
  }
}
示例#26
0
文件: PVRManager.cpp 项目: dpvip/xbmc
bool CPVRManager::UpdateItem(CFileItem& item)
{
  /* Don't update if a recording is played */
  if (item.IsPVRRecording())
    return false;

  if (!item.IsPVRChannel())
  {
    CLog::Log(LOGERROR, "CPVRManager - %s - no channel tag provided", __FUNCTION__);
    return false;
  }

  CSingleLock lock(m_critSection);
  if (!m_currentFile || *m_currentFile->GetPVRChannelInfoTag() == *item.GetPVRChannelInfoTag())
    return false;

  g_application.SetCurrentFileItem(*m_currentFile);
  CFileItemPtr itemptr(new CFileItem(*m_currentFile));
  g_infoManager.SetCurrentItem(itemptr);

  CPVRChannelPtr channelTag(item.GetPVRChannelInfoTag());
  CEpgInfoTagPtr epgTagNow(channelTag->GetEPGNow());

  if (channelTag->IsRadio())
  {
    CMusicInfoTag* musictag = item.GetMusicInfoTag();
    if (musictag)
    {
      musictag->SetTitle(epgTagNow ?
          epgTagNow->Title() :
          CSettings::GetInstance().GetBool(CSettings::SETTING_EPG_HIDENOINFOAVAILABLE) ?
              "" :
              g_localizeStrings.Get(19055)); // no information available
      if (epgTagNow)
        musictag->SetGenre(epgTagNow->Genre());
      musictag->SetDuration(epgTagNow ? epgTagNow->GetDuration() : 3600);
      musictag->SetURL(channelTag->Path());
      musictag->SetArtist(channelTag->ChannelName());
      musictag->SetAlbumArtist(channelTag->ChannelName());
      musictag->SetLoaded(true);
      musictag->SetComment("");
      musictag->SetLyrics("");
    }
  }
  else
  {
    CVideoInfoTag *videotag = item.GetVideoInfoTag();
    if (videotag)
    {
      videotag->m_strTitle = epgTagNow ?
          epgTagNow->Title() :
          CSettings::GetInstance().GetBool(CSettings::SETTING_EPG_HIDENOINFOAVAILABLE) ?
              "" :
              g_localizeStrings.Get(19055); // no information available
      if (epgTagNow)
        videotag->m_genre = epgTagNow->Genre();
      videotag->m_strPath = channelTag->Path();
      videotag->m_strFileNameAndPath = channelTag->Path();
      videotag->m_strPlot = epgTagNow ? epgTagNow->Plot() : "";
      videotag->m_strPlotOutline = epgTagNow ? epgTagNow->PlotOutline() : "";
      videotag->m_iEpisode = epgTagNow ? epgTagNow->EpisodeNumber() : 0;
    }
  }

  return false;
}
bool CMusicInfoTagLoaderSid::Load(const CStdString& strFileName, CMusicInfoTag& tag)
{
  CStdString strFileToLoad = strFileName;
  int iTrack = 0;
  CStdString strExtension;
  CUtil::GetExtension(strFileName,strExtension);
  strExtension.MakeLower();
  if (strExtension==".sidstream")
  {
    //  Extract the track to play
    CStdString strFile=CUtil::GetFileName(strFileName);
    int iStart=strFile.ReverseFind("-")+1;
    iTrack = atoi(strFile.substr(iStart, strFile.size()-iStart-10).c_str());
    //  The directory we are in, is the file
    //  that contains the bitstream to play,
    //  so extract it
    CStdString strPath=strFileName;
    CUtil::GetDirectory(strPath, strFileToLoad);
    CUtil::RemoveSlashAtEnd(strFileToLoad);   // we want the filename
  }
  CStdString strFileNameLower(strFileToLoad);
  strFileNameLower.MakeLower();
  int iHVSC = strFileNameLower.find("hvsc"); // need hvsc in path name since our lookupfile is based on hvsc paths
  if (iHVSC < 0)
  {
    iHVSC = strFileNameLower.find("c64music");
    if (iHVSC >= 0)
      iHVSC += 8;
  }
  else
    iHVSC += 4;
  if( iHVSC < 0 )
  {
    tag.SetLoaded(false);
    return( false );
  }

  CStdString strHVSCpath = strFileToLoad.substr(iHVSC,strFileToLoad.length()-1);

  strHVSCpath.Replace('\\','/'); // unix paths
  strHVSCpath.MakeLower();

  char temp[8192];
  CRegExp reg;
  if (!reg.RegComp("TITLE: ([^\r\n]*)\r?\n[^A]*ARTIST: ([^\r\n]*)\r?\n"))
  {
    CLog::Log(LOGINFO,"MusicInfoTagLoaderSid::Load(..): failed to compile regular expression");
    tag.SetLoaded(false);
    return( false );
  }

  sprintf(temp,"%s\\%s",g_settings.GetDatabaseFolder().c_str(),"stil.txt"); // changeme?
  std::ifstream f(temp);
  if( !f.good() ) {
    CLog::Log(LOGINFO,"MusicInfoTagLoaderSid::Load(..) unable to locate stil.txt");
    tag.SetLoaded(false);
    return( false );
  }

  const char* szStart = NULL;
  const char* szEnd = NULL;
  char temp2[8191];
  char* temp3 = temp2;
  while( !f.eof() && !szEnd )
  {
    f.read(temp,8191);
    CStdString strLower = temp;
    strLower.MakeLower();

    if (!szStart)
      szStart= (char *)strstr(strLower.c_str(),strHVSCpath.c_str());
    if (szStart)
    {
      szEnd = strstr(szStart+strHVSCpath.size(),".sid");
      if (szEnd)
      {
        memcpy(temp3,temp+(szStart-strLower.c_str()),szEnd-szStart);
        temp3 += szEnd-szStart;
      }
      else
      {
        memcpy(temp3,temp+(szStart-strLower.c_str()),strlen(szStart));
        szStart = NULL;
        temp3 += strlen(szStart);
      }
    }
  }
  f.close();

  if (!f.eof() && szEnd)
  {
    temp2[temp3-temp2] = '\0';
    temp3 = strstr(temp2,"TITLE:");
  }
  else
    temp3 = NULL;
  if (temp3)
  {
    for (int i=0;i<iTrack-1;++i) // skip tracks
    {
      int iStart = reg.RegFind(temp3);
      if (!iStart)
      {
        tag.SetLoaded(false);
        return false;
      }
      temp3 += iStart;
    }
    if(reg.RegFind(temp3) > -1)
    {
      char* szTitle = reg.GetReplaceString("\\1");
      char* szArtist = reg.GetReplaceString("\\2");
      char* szMins = NULL;
      char* szSecs = NULL;
      CRegExp reg2;
      reg2.RegComp("(.*) \\(([0-9]*):([0-9]*)\\)");
      if (reg2.RegFind(szTitle) > -1)
      {
        szMins = reg2.GetReplaceString("\\2");
        szSecs = reg2.GetReplaceString("\\3");
        char* szTemp = reg2.GetReplaceString("\\1");
        free(szTitle);
        szTitle = szTemp;
      }
      tag.SetLoaded(true);
      tag.SetURL(strFileToLoad);
      tag.SetTrackNumber(iTrack);
      if (szMins && szSecs)
        tag.SetDuration(atoi(szMins)*60+atoi(szSecs));

      tag.SetTitle(szTitle);
      tag.SetArtist(szArtist);
      if( szTitle )
        free(szTitle);
      if( szArtist )
        free(szArtist);
      if( szMins )
        free(szMins);
      if( szSecs )
        free(szSecs);
    }
  }

  sprintf(temp,"%s\\%s",g_settings.GetDatabaseFolder().c_str(),"sidlist.csv"); // changeme?
  std::ifstream f2(temp);
  if( !f2.good() ) {
    CLog::Log(LOGINFO,"MusicInfoTagLoaderSid::Load(..) unable to locate sidlist.csv");
    tag.SetLoaded(false);
    return( false );
  }

  while( !f2.eof() ) {
    f2.getline(temp,8191);
    CStdString strTemp(temp);
    strTemp.MakeLower();
    unsigned int iFind = strTemp.find(strHVSCpath);
    if (iFind == string::npos)
      continue;

    char temp2[1024];
    char temp3[1024];
    strncpy(temp3,temp+iFind,strlen(strHVSCpath));
    temp3[strlen(strHVSCpath)] = '\0';
    sprintf(temp2,"\"%s\",\"[^\"]*\",\"[^\"]*\",\"([^\"]*)\",\"([^\"]*)\",\"([0-9]*)[^\"]*\",\"[0-9]*\",\"[0-9]*\",\"",temp3);
    for (int i=0;i<iTrack-1;++i)
      strcat(temp2,"[0-9]*:[0-9]* ");
    strcat(temp2,"([0-9]*):([0-9]*)");
    if( !reg.RegComp(temp2) )
    {
      CLog::Log(LOGINFO,"MusicInfoTagLoaderSid::Load(..): failed to compile regular expression");
      tag.SetLoaded(false);
      return( false );
    }
    if( reg.RegFind(temp) >= 0 ) {
      char* szTitle = reg.GetReplaceString("\\1");
      char* szArtist = reg.GetReplaceString("\\2");
      char* szYear = reg.GetReplaceString("\\3");
      char* szMins = reg.GetReplaceString("\\4");
      char* szSecs = reg.GetReplaceString("\\5");
      tag.SetLoaded(true);
      tag.SetTrackNumber(iTrack);
      if (tag.GetDuration() == 0)
        tag.SetDuration(atoi(szMins)*60+atoi(szSecs));
      if (tag.GetTitle() == "")
        tag.SetTitle(szTitle);
      if (tag.GetArtist() == "")
        tag.SetArtist(szArtist);
      SYSTEMTIME dateTime;
      dateTime.wYear = atoi(szYear);
      tag.SetReleaseDate(dateTime);
      if( szTitle )
        free(szTitle);
      if( szArtist )
        free(szArtist);
      if( szYear )
        free(szYear);
      if( szMins )
        free(szMins);
      if( szSecs )
        free(szSecs);
      f2.close();
      return( true );
    }
  }

  f2.close();
  tag.SetLoaded(false);
  return( false );
}