Exemplo n.º 1
0
int PrintInformation(char *sFileName, const ID3_Tag &myTag)
{
  bool firstLine = true;
  const ID3_Frame * myFrame;
  ID3_Tag::ConstIterator *Iter=myTag.CreateIterator();
  for (size_t nFrames = 0; nFrames < myTag.NumFrames(); nFrames++)
  {
    myFrame = Iter->GetNext();

    if(firstLine) {
      std::cout << "id3v2 tag info for " << sFileName << ":" << std::endl;
      firstLine = false;
    }

    if (NULL != myFrame)
    { 
      const char* desc = myFrame->GetDescription();
      if (!desc) desc = "";
      std::cout << myFrame->GetTextID() << " (" << desc << "): ";
      ID3_FrameID eFrameID = myFrame->GetID();

      switch (eFrameID)
      {
        case ID3FID_ALBUM:
        case ID3FID_BPM:
        case ID3FID_COMPOSER:
        case ID3FID_COPYRIGHT:
        case ID3FID_DATE:
        case ID3FID_PLAYLISTDELAY:
        case ID3FID_ENCODEDBY:
        case ID3FID_LYRICIST:
        case ID3FID_FILETYPE:
        case ID3FID_TIME:
        case ID3FID_CONTENTGROUP:
        case ID3FID_TITLE:
        case ID3FID_SUBTITLE:
        case ID3FID_INITIALKEY:
        case ID3FID_LANGUAGE:
        case ID3FID_SONGLEN:
        case ID3FID_MEDIATYPE:
        case ID3FID_ORIGALBUM:
        case ID3FID_ORIGFILENAME:
        case ID3FID_ORIGLYRICIST:
        case ID3FID_ORIGARTIST:
        case ID3FID_ORIGYEAR:
        case ID3FID_FILEOWNER:
        case ID3FID_LEADARTIST:
        case ID3FID_BAND:
        case ID3FID_CONDUCTOR:
        case ID3FID_MIXARTIST:
        case ID3FID_PARTINSET:
        case ID3FID_PUBLISHER:
        case ID3FID_TRACKNUM:
        case ID3FID_RECORDINGDATES:
        case ID3FID_NETRADIOSTATION:
        case ID3FID_NETRADIOOWNER:
        case ID3FID_SIZE:
        case ID3FID_ISRC:
        case ID3FID_ENCODERSETTINGS:
        case ID3FID_YEAR:
        {
          char *sText = ID3_GetString(myFrame, ID3FN_TEXT);
          std::cout << sText << std::endl;
          delete [] sText;
          break;
        }
        case ID3FID_CONTENTTYPE:
        {
          const char* genre_str;
          int genre_id = 255;
          char *sText = ID3_GetString(myFrame, ID3FN_TEXT);
          sscanf(sText, "(%d)", &genre_id);
          if (genre_id == 255) {
            genre_str = sText;
            genre_id = GetNumFromGenre(sText);
          }
          else
            genre_str = GetGenreFromNum(genre_id);
          std::cout << genre_str << " (" << genre_id << ")" << std::endl;
          delete [] sText;
          break;
        }
        case ID3FID_USERTEXT:
        {
          char 
            *sText = ID3_GetString(myFrame, ID3FN_TEXT), 
            *sDesc = ID3_GetString(myFrame, ID3FN_DESCRIPTION);
          std::cout << "(" << sDesc << "): " << sText << std::endl;
          delete [] sText;
          delete [] sDesc;
          break;
        }
        case ID3FID_TERMSOFUSE:
        {
          char 
            *sText = ID3_GetString(myFrame, ID3FN_TEXT), 
            *sLang = ID3_GetString(myFrame, ID3FN_LANGUAGE);
          std::cout << "[" << sLang << "]: "
               << sText << std::endl;
          delete [] sText;
          delete [] sLang;
          break;
        }
        case ID3FID_COMMENT:
        case ID3FID_UNSYNCEDLYRICS:
        {
          char 
            *sText = ID3_GetString(myFrame, ID3FN_TEXT), 
            *sDesc = ID3_GetString(myFrame, ID3FN_DESCRIPTION), 
            *sLang = ID3_GetString(myFrame, ID3FN_LANGUAGE);
          std::cout << "(" << sDesc << ")[" << sLang << "]: "
               << sText << std::endl;
          delete [] sText;
          delete [] sDesc;
          delete [] sLang;
          break;
        }
        case ID3FID_WWWAUDIOFILE:
        case ID3FID_WWWARTIST:
        case ID3FID_WWWAUDIOSOURCE:
        case ID3FID_WWWCOMMERCIALINFO:
        case ID3FID_WWWCOPYRIGHT:
        case ID3FID_WWWPUBLISHER:
        case ID3FID_WWWPAYMENT:
        case ID3FID_WWWRADIOPAGE:
        {
          char *sURL = ID3_GetString(myFrame, ID3FN_URL);
          std::cout << sURL << std::endl;
          delete [] sURL;
          break;
        }
        case ID3FID_WWWUSER:
        {
          char 
            *sURL = ID3_GetString(myFrame, ID3FN_URL),
            *sDesc = ID3_GetString(myFrame, ID3FN_DESCRIPTION);
          std::cout << "(" << sDesc << "): " << sURL << std::endl;
          delete [] sURL;
          delete [] sDesc;
          break;
        }
        case ID3FID_INVOLVEDPEOPLE:
        {
          // This isn't the right way to do it---will only get first person
          size_t nItems = myFrame->Field(ID3FN_TEXT).GetNumTextItems();
          for (size_t nIndex = 1; nIndex <= nItems; nIndex++)
          {
            char *sPeople = ID3_GetString(myFrame, ID3FN_TEXT, nIndex);
            std::cout << sPeople;
            delete [] sPeople;
            if (nIndex < nItems)
            {
              std::cout << ", ";
            }
          }
          std::cout << std::endl;
          break;
        }
        case ID3FID_PICTURE:
        {
          char
            *sMimeType = ID3_GetString(myFrame, ID3FN_MIMETYPE),
            *sDesc     = ID3_GetString(myFrame, ID3FN_DESCRIPTION),
            *sFormat   = ID3_GetString(myFrame, ID3FN_IMAGEFORMAT);
          size_t
            nPicType   = myFrame->Field(ID3FN_PICTURETYPE).Get(),
            nDataSize  = myFrame->Field(ID3FN_DATA).Size();
          std::cout << "(" << sDesc << ")[" << sFormat << ", "
               << nPicType << "]: " << sMimeType << ", " << nDataSize
               << " bytes" << std::endl;
          delete [] sMimeType;
          delete [] sDesc;
          delete [] sFormat;
          break;
        }
        case ID3FID_GENERALOBJECT:
        {
          char 
          *sMimeType = ID3_GetString(myFrame, ID3FN_MIMETYPE), 
          *sDesc = ID3_GetString(myFrame, ID3FN_DESCRIPTION), 
          *sFileName = ID3_GetString(myFrame, ID3FN_FILENAME);
          size_t nDataSize = myFrame->GetField(ID3FN_DATA)->Size();
          std::cout << "(" << sDesc << ")[" 
               << sFileName << "]: " << sMimeType << ", " << nDataSize
               << " bytes" << std::endl;
          delete [] sMimeType;
          delete [] sDesc;
          delete [] sFileName;
          break;
        }
        case ID3FID_UNIQUEFILEID:
        {
          char *sOwner = ID3_GetString(myFrame, ID3FN_OWNER);
          size_t nDataSize = myFrame->Field(ID3FN_DATA).Size();
          std::cout << sOwner << ", " << nDataSize
               << " bytes" << std::endl;
          delete [] sOwner;
          break;
        }
        case ID3FID_PLAYCOUNTER:
        {
          size_t nCounter = myFrame->Field(ID3FN_COUNTER).Get();
          std::cout << nCounter << std::endl;
          break;
        }
        case ID3FID_POPULARIMETER:
        {
          char *sEmail = ID3_GetString(myFrame, ID3FN_EMAIL);
          size_t
            nCounter = myFrame->Field(ID3FN_COUNTER).Get(),
            nRating = myFrame->Field(ID3FN_RATING).Get();
          std::cout << sEmail << ", counter=" 
               << nCounter << " rating=" << nRating;
          delete [] sEmail;
          break;
        }
        case ID3FID_CRYPTOREG:
        case ID3FID_GROUPINGREG:
        {
          char *sOwner = ID3_GetString(myFrame, ID3FN_OWNER);
          size_t 
            nSymbol = myFrame->Field(ID3FN_ID).Get(),
            nDataSize = myFrame->Field(ID3FN_DATA).Size();
          std::cout << "(" << nSymbol << "): " << sOwner
               << ", " << nDataSize << " bytes";
          break;
        }
        case ID3FID_AUDIOCRYPTO:
        case ID3FID_EQUALIZATION:
        case ID3FID_EVENTTIMING:
        case ID3FID_CDID:
        case ID3FID_MPEGLOOKUP:
        case ID3FID_OWNERSHIP:
        case ID3FID_PRIVATE:
        case ID3FID_POSITIONSYNC:
        case ID3FID_BUFFERSIZE:
        case ID3FID_VOLUMEADJ:
        case ID3FID_REVERB:
        case ID3FID_SYNCEDLYRICS:
        case ID3FID_SYNCEDTEMPO:
        case ID3FID_METACRYPTO:
        {
          std::cout << " (unimplemented)" << std::endl;
          break;
        }
        default:
        {
          std::cout << " frame" << std::endl;
          break;
        }
      }
    }
  }
  delete Iter;
  if(firstLine)
    return 1;
  
  return 0;
}
Exemplo n.º 2
0
//***************************************************************************
bool Kwave::MP3Decoder::parseID3Tags(ID3_Tag &tag)
{
    if (tag.NumFrames() < 1) return true; // no tags, nothing to do

    QDate creation_date;
    QTime creation_time;
    int year  = -1;
    int month = -1;
    int day   = -1;

    ID3_Tag::Iterator *it = tag.CreateIterator();
    ID3_Frame *frame = 0;
    Kwave::FileInfo info(metaData());
    while (it && (frame = it->GetNext())) {
	const ID3_FrameID id = frame->GetID();
	const Kwave::FileProperty property = m_property_map.property(id);
	const ID3_PropertyMap::Encoding encoding = m_property_map.encoding(id);
	switch (encoding) {
	    case ID3_PropertyMap::ENC_TEXT_PARTINSET:
	    {
		QString s = parseId3Frame2String(frame);
		int cd  = 0;
		int cds = 0;
		if (s.contains(QLatin1Char('/'))) {
		    int i = s.indexOf(QLatin1Char('/'));
		    cd = s.left(i).toInt();
		    cds = s.mid(i + 1).toInt();
		} else {
		    cd = s.toInt();
		}
		if (cd  > 0) info.set(Kwave::INF_CD , QVariant(cd));
		if (cds > 0) info.set(Kwave::INF_CDS, QVariant(cds));
		break;
	    }
	    case ID3_PropertyMap::ENC_TRACK_NUM:
	    {
		QString s = parseId3Frame2String(frame);
		int track  = 0;
		int tracks = 0;
		if (s.contains(QLatin1Char('/'))) {
		    int i = s.indexOf(QLatin1Char('/'));
		    track = s.left(i).toInt();
		    tracks = s.mid(i + 1).toInt();
		} else {
		    track = s.toInt();
		}
		if (track  > 0) info.set(Kwave::INF_TRACK , QVariant(track));
		if (tracks > 0) info.set(Kwave::INF_TRACKS, QVariant(tracks));
		break;
	    }
	    case ID3_PropertyMap::ENC_TERMS_OF_USE:
		// the same as ENC_COMMENT, but without "Description"
		/* FALLTHROUGH */
	    case ID3_PropertyMap::ENC_COMMENT:
	    {
		QString s = parseId3Frame2String(frame);

		// optionally prepend language
		char *lang = ID3_GetString(frame, ID3FN_LANGUAGE);
		if (lang) {
		    s = _("[") + _(lang) + _("] ") + s;
		    ID3_FreeString(lang);
		}

		// append to already existing tag, separated by a slash
		if (info.contains(property))
		    s = info.get(property).toString() + _(" / ") + s;
		info.set(property, QVariant(s));
		break;
	    }
	    case ID3_PropertyMap::ENC_GENRE_TYPE:
	    {
		QString s = parseId3Frame2String(frame);
		int genre = Kwave::GenreType::fromID3(s);
		if (genre >= 0)
		    s = Kwave::GenreType::name(genre, false);
		info.set(property, QVariant(s));
		break;
	    }
	    case ID3_PropertyMap::ENC_LENGTH:
	    {
		// length in ms -> convert this to samples
		QString       s    = parseId3Frame2String(frame);
		const double  rate = info.rate();
		bool          ok   = false;
		const double  ms   = s.toDouble(&ok) + 0.5;
		if (ok && (rate > 0)) {
		    // NOTE: this overwrites the length found in the header!
		    sample_index_t length = static_cast<sample_index_t>(
			(rate * ms) / 1000.0);
		    info.setLength(length);
		}
		break;
	    }
	    case ID3_PropertyMap::ENC_TEXT_TIMESTAMP:
	    {
		if (!creation_date.isValid()) {
		    QString s = parseId3Frame2String(frame);
		    switch (id)
		    {
			case ID3FID_RECORDINGDATES:
			    // should be a ISO 8601 timestamp or similar
			    s = Kwave::string2date(s);
			    if (s.length())
				creation_date =
				    QDate::fromString(s, Qt::ISODate);
			    break;
			case ID3FID_DATE: {
			    // DDMM
			    unsigned int ddmm = s.toUInt();
			    day   = ddmm / 100;
			    month = ddmm % 100;
			    break;
			}
			case ID3FID_YEAR: /* FALLTHROUGH */
			case ID3FID_ORIGYEAR:
			    // YYYY
			    year = s.toUInt();
			    break;
			default:
			    break;
		    }
		}

		if (creation_time.isValid()) {
		    switch (id)
		    {
			case ID3FID_TIME:
			    creation_time = QTime::fromString(_("hhmm"));
			    break;
			default:
			    break;
		    }
		}
		break;
	    }
	    case ID3_PropertyMap::ENC_TEXT_SLASH:
	    {
		// append to already existing tag, separated by a slash
		QString s = parseId3Frame2String(frame);
		if (info.contains(property))
		    s = info.get(property).toString() + _(" / ") + s;
		info.set(property, QVariant(s));
		break;
	    }
	    case ID3_PropertyMap::ENC_TEXT_URL:   /* FALLTHROUGH */
	    case ID3_PropertyMap::ENC_TEXT:
		info.set(property, QVariant(parseId3Frame2String(frame)));
		break;
	    case ID3_PropertyMap::ENC_NONE: /* FALLTHROUGH */
	    default:
	    {
		QString s = parseId3Frame2String(frame);
		qWarning("unsupported ID3 tag: %d, descr: '%s', text: '%s'",
			 id, frame->GetDescription(), DBG(s));
		break;
	    }
	}
    }

    /*
     * try to build a valid creation date/time
     */
    if (!creation_date.isValid()) {
	// no complete creation date - try to reassemble from found y/m/d
	creation_date = QDate(year, month, day);
    }
    if (creation_date.isValid() && creation_time.isValid()) {
	// full date + time
	QDateTime dt(creation_date, creation_time);
	info.set(Kwave::INF_CREATION_DATE, dt.toString(
	    _("yyyy-MM-ddTHH:mm:ss")));
    } else if (creation_date.isValid()) {
	// date without time
	info.set(Kwave::INF_CREATION_DATE, creation_date.toString(
	    _("yyyy-MM-dd")));
    } else if (year > 0) {
	// only year
	creation_date = QDate(year, 1, 1);
	info.set(Kwave::INF_CREATION_DATE, creation_date.toString(_("yyyy")));
    }

    metaData().replace(Kwave::MetaDataList(info));

    return true;
}
Exemplo n.º 3
0
//***************************************************************************
bool Kwave::MP3Decoder::open(QWidget *widget, QIODevice &src)
{
    qDebug("MP3Decoder::open()");
    metaData().clear();
    Q_ASSERT(!m_source);
    if (m_source) qWarning("MP3Decoder::open(), already open !");

    /* open the file in readonly mode with seek enabled */
    if (src.isSequential()) return false;
    if (!src.open(QIODevice::ReadOnly)) {
	qWarning("unable to open source in read-only mode!");
	return false;
    }

    /* read all available ID3 tags */
    ID3_Tag tag;
    ID3_QIODeviceReader adapter(src);
    tag.Link(adapter, static_cast<flags_t>(ID3TT_ALL));

    qDebug("NumFrames = %u", Kwave::toUint(tag.NumFrames()));
    /** @bug: id3lib crashes in this line on some MP3 files */
    if (tag.GetSpec() != ID3V2_UNKNOWN) {
	qDebug("Size = %u",      Kwave::toUint(tag.Size()));
    }
    qDebug("HasLyrics = %d", tag.HasLyrics());
    qDebug("HasV1Tag = %d",  tag.HasV1Tag());
    qDebug("HasV2Tag = %d",  tag.HasV2Tag());

    m_prepended_bytes = tag.GetPrependedBytes();
    m_appended_bytes  = tag.GetAppendedBytes();
    qDebug("prepended=%lu, appended=%lu", m_prepended_bytes, m_appended_bytes);

    const Mp3_Headerinfo *mp3hdr = tag.GetMp3HeaderInfo();
    if (!mp3hdr) {
	Kwave::MessageBox::sorry(widget,
	    i18n("The opened file is no MPEG file or it is damaged.\n"
	    "No header information has been found."));
	return false;
    }

    /* parse the MP3 header */
    if (!parseMp3Header(*mp3hdr, widget)) return false;

    /* parse the ID3 tags */
    if (!parseID3Tags(tag)) return false;

    /* accept the source */
    m_source = &src;
    Kwave::FileInfo info(metaData());
    info.set(Kwave::INF_MIMETYPE, _("audio/mpeg"));
    metaData().replace(Kwave::MetaDataList(info));

    // allocate a transfer buffer with 128 kB
    if (m_buffer) free(m_buffer);
    m_buffer_size = (128 << 10);

    m_buffer = static_cast<unsigned char *>(malloc(m_buffer_size));
    if (!m_buffer) return false; // out of memory :-(

    return true;
}
Exemplo n.º 4
0
int main(int argc, char* argv[]) {
  // Parse any command-line options.
  namespace po = boost::program_options;
  po::options_description desc("Allowed options");
  desc.add_options()
    ("help", "show help")
    ("debug-httpd", po::value<bool>(&mp3d_debug_httpd), "show httpd debug output")
    ("root", po::value<std::string>(&mp3d_music_root), "root of file system mp3 tree")
    ("port", po::value<int>(&mp3d_port), "httpd port number")
  ;
  po::variables_map args;
  po::store(po::parse_command_line(argc, argv, desc), args);
  po::notify(args);
  if (args.count("help")) {
    std::cout << desc << std::endl;
    return 1;
  }

  // Index all the mp3s.
  Paths paths;
  find_mp3_files(mp3d_music_root, paths);
  std::cerr << ".mp3 files found: " << paths.size() << std::endl;

  int old_percentage = -1;
  size_t id = 0;
  for (Paths::const_iterator it = paths.begin(); it != paths.end(); ++it) {
    Mp3Info mp3;
    mp3.filename = (*it).string();

    const ID3_Tag tag(mp3.filename.c_str());

    ID3_Tag::ConstIterator* it = tag.CreateIterator();
    for (size_t i = 0; i < tag.NumFrames(); ++i) {
      const ID3_Frame* frame = it->GetNext();
      if (frame != 0) {
        std::string* dst;
        switch (frame->GetID()) {
        case ID3FID_ALBUM: dst = &mp3.album; break;
        case ID3FID_LEADARTIST: dst = &mp3.artist; break;
        case ID3FID_TITLE: dst = &mp3.title; break;
        default: continue;
        }
        char* text = ID3_GetString(frame, ID3FN_TEXT);
        dst->assign(text);
        ID3_FreeString(text);
      }
    }
    
    // FIXME: maybe a hash, to enable bookmarks?
    mp3.id = id++;
    
    all_mp3s.push_back(mp3);
    
    // Show progress. Not really useful when we're not debugging.
    // FIXME: start the web server straight away, and say "Indexing..." there.
    const int new_percentage = (100*all_mp3s.size())/paths.size();
    if (new_percentage != old_percentage) {
      std::cout << "\rScanned: " << new_percentage << "%" << std::flush;
      old_percentage = new_percentage;
    }
  }
  std::cout << "\r.mp3 files scanned: " << all_mp3s.size() << std::endl;

  // Set up the static files we need to serve.
  read_static_file("/static/add.png",
                   "/usr/share/icons/gnome/16x16/actions/gtk-add.png");
  read_static_file("/static/play.png",
                   "/usr/share/icons/gnome/16x16/actions/gtk-media-play-ltr.png");
  read_static_file("/static/remove.png",
                   "/usr/share/icons/gnome/16x16/actions/gtk-remove.png");
  static_file_map["/static/site.css"] = make_css();
  
  // Start the mp3 player thread.
  boost::thread mp3_player_thread(mp3_play_loop);
  
  // Start the HTTP server.
  std::cerr << "Starting HTTP server on port " << mp3d_port << "..." << std::endl;
  const int mhd_flags = MHD_USE_SELECT_INTERNALLY;
  MHD_Daemon* daemon = MHD_start_daemon(mhd_flags, mp3d_port, 0, 0, &handle_request, 0, MHD_OPTION_END);
  if (daemon == 0) {
    fail("MHD_start_daemon failed!");
  }
  
  getchar(); // Wait for the user to hit enter.
  
  MHD_stop_daemon(daemon);
  //mp3_player_thread.join();
  return 0;
}