コード例 #1
0
ファイル: aac.c プロジェクト: jonsafari/mocp
/* Fill info structure with data from aac comments */
static void aac_info (const char *file_name,
		struct file_tags *info,
		const int tags_sel)
{
	if (tags_sel & TAGS_COMMENTS) {
		struct id3_tag *tag;
		struct id3_file *id3file;
		char *track = NULL;

		id3file = id3_file_open (file_name, ID3_FILE_MODE_READONLY);
		if (!id3file)
			return;
		tag = id3_file_tag (id3file);
		if (tag) {
			info->artist = get_tag (tag, ID3_FRAME_ARTIST);
			info->title = get_tag (tag, ID3_FRAME_TITLE);
			info->album = get_tag (tag, ID3_FRAME_ALBUM);
			track = get_tag (tag, ID3_FRAME_TRACK);

			if (track) {
				char *end;

				info->track = strtol (track, &end, 10);
				if (end == track)
					info->track = -1;
				free (track);
			}
		}
		id3_file_close (id3file);
	}

	if (tags_sel & TAGS_TIME) {
		struct aac_data *data;

		data = aac_open_internal (NULL, file_name);

		if (data->ok)
			info->time = aac_count_time (data);
		else
			logit ("%s", decoder_error_text (&data->error));

		aac_close (data);
	}
}
コード例 #2
0
ファイル: mpg321.c プロジェクト: mvd7793/RED-SIREN
static int get_id3_info( const char *fname, struct id3_file **id3struct, struct id3_tag **id3tag)
{
	struct id3_file *s;
	struct id3_tag *t;

	s = id3_file_open(fname, ID3_FILE_MODE_READONLY);
	if( s == NULL )
		return (0);

	t = id3_file_tag(s);
	if(t == NULL)
	{
		id3_file_close(s);
		return (0);
	}

	*id3struct = s;
	*id3tag = t;
	return (1);
}
コード例 #3
0
ファイル: tagger.c プロジェクト: AzagraMac/PS2_SDK
static
int tag_one(struct tagger *tagger, char const *path)
{
  struct id3_file *file;

  file = id3_file_open(path, tagger->mode == TAGGER_MODE_MODIFY ?
		       ID3_FILE_MODE_READWRITE : ID3_FILE_MODE_READONLY);
  if (file == 0) {
    perror(path);
    return -1;
  }

  /* ... */

  if (id3_file_close(file) == -1) {
    perror(path);
    return -1;
  }

  return 0;
}
コード例 #4
0
ファイル: id3.c プロジェクト: pcercuei/dcplaya
int id3_info(playa_info_t * info, const char *fn)
{
  struct id3_file * f;
  int i;

  SDDEBUG(">> %s(%s)\n", __FUNCTION__, fn);

  memset(info, 0, sizeof(*info));
  
  f = id3_file_open(fn, ID3_FILE_MODE_READONLY);
  if (!f) {
    SDERROR("id3 : open error\n");
    return -1;
  }
   
  for (i=0; i<f->ntags; ++i) {
    show_id3(info, f->tags[i].tag);
  }
  
  id3_file_close(f);
  SDDEBUG("<< %s(%s) := [0]\n", __FUNCTION__, fn);
  return 0;
}
コード例 #5
0
ファイル: MP3ID3.cpp プロジェクト: junagit/rns510_dtv
/*
** bool prepareMP3(string strFile, bool bReadOnly)
**
** Prepare a mp3 file to retreive it's tag information if it has
**
** Parameter:
** strFile:		mp3 file with full pathname
** bReadOnly:	Indicate how you are going to open the file. 
*/
bool CMP3ID3::prepareMP3(string strFile, bool bReadOnly){
	if ( m_pID3File != NULL )
		id3_file_close(m_pID3File);

	int fileID = -1;
	if ( bReadOnly )
		fileID = open(strFile.c_str(),O_RDONLY);
	else
		fileID = open(strFile.c_str(),O_RDWR);

	if ( fileID == -1 ) return false;

	if ( bReadOnly )
		m_pID3File = id3_file_fdopen(fileID,ID3_FILE_MODE_READONLY);
	else
		m_pID3File = id3_file_fdopen(fileID,ID3_FILE_MODE_READWRITE);

	if ( m_pID3File == NULL ) return false;

	m_pID3Tag = id3_file_tag(m_pID3File);

	return true;
}
コード例 #6
0
ファイル: ImportMP3.cpp プロジェクト: tuanmasterit/audacity
void MP3ImportFileHandle::ImportID3(Tags *tags)
{
#ifdef USE_LIBID3TAG 
   struct id3_file *fp = id3_file_open(OSFILENAME(mFilename), ID3_FILE_MODE_READONLY);
   if (!fp) {
      return;
   }

   struct id3_tag *tp = id3_file_tag(fp);
   if (!tp) {
      id3_file_close(fp);
      return;
   }

   tags->Clear();
   tags->SetID3V2( tp->options & ID3_TAG_OPTION_ID3V1 ? false : true );

   // Loop through all frames
   for (int i = 0; i < (int) tp->nframes; i++) {
      struct id3_frame *frame = tp->frames[i];

      // printf("ID: %08x '%4s'\n", (int) *(int *)frame->id, frame->id);
      // printf("Desc: %s\n", frame->description);
      // printf("Num fields: %d\n", frame->nfields);

      // for (int j = 0; j < (int) frame->nfields; j++) {
      //    printf("field %d type %d\n", j, frame->fields[j].type );
      //    if (frame->fields[j].type == ID3_FIELD_TYPE_STRINGLIST) {
      //       printf("num strings %d\n", frame->fields[j].stringlist.nstrings);
      //    }
      // }

      wxString n, v;

      // Determine the tag name
      if (strcmp(frame->id, ID3_FRAME_TITLE) == 0) {
         n = TAG_TITLE;
      }
      else if (strcmp(frame->id, ID3_FRAME_ARTIST) == 0) {
         n = TAG_ARTIST;
      }
      else if (strcmp(frame->id, ID3_FRAME_ALBUM) == 0) {
         n = TAG_ALBUM;
      }
      else if (strcmp(frame->id, ID3_FRAME_TRACK) == 0) {
         n = TAG_TRACK;
      }
      else if (strcmp(frame->id, "TYER") == 0) {
         n = TAG_YEAR;
      }
      else if (strcmp(frame->id, ID3_FRAME_YEAR) == 0) {
         n = TAG_YEAR;
      }
      else if (strcmp(frame->id, ID3_FRAME_COMMENT) == 0) {
         n = TAG_COMMENTS;
      }
      else if (strcmp(frame->id, ID3_FRAME_GENRE) == 0) {
         n = TAG_GENRE;
      }
   else {
         // Use frame description as default tag name.  The descriptions
         // may include several "meanings" separated by "/" characters, so
         // we just use the first meaning
         n = UTF8CTOWX(frame->description).BeforeFirst(wxT('/'));
      }

      const id3_ucs4_t *ustr = NULL;

      if (n == TAG_COMMENTS) {
         ustr = id3_field_getfullstring(&frame->fields[3]);
      }
      else if (frame->nfields == 3) {
         ustr = id3_field_getstring(&frame->fields[1]);
         if (ustr) {
            char *str = (char *)id3_ucs4_utf8duplicate(ustr);
            n = UTF8CTOWX(str);
            free(str);
         }

         ustr = id3_field_getstring(&frame->fields[2]);
      }
      else if (frame->nfields >= 2) {
         ustr = id3_field_getstrings(&frame->fields[1], 0);
      }

      if (ustr) {
         char *str = (char *)id3_ucs4_utf8duplicate(ustr);
         v = UTF8CTOWX(str);
         free(str);
      }

      if (!n.IsEmpty() && !v.IsEmpty()) {
         tags->SetTag(n, v);
   }
}

   // Convert v1 genre to name
   if (tags->HasTag(TAG_GENRE)) {
      long g = -1;
      if (tags->GetTag(TAG_GENRE).ToLong(&g)) {
         tags->SetTag(TAG_GENRE, tags->GetGenre(g));
   }
}

   id3_file_close(fp);
#endif // ifdef USE_LIBID3TAG 
}
コード例 #7
0
ファイル: ImportMP3.cpp プロジェクト: aeve/audacity
void MP3ImportFileHandle::ImportID3(Tags *tags)
{
#ifdef USE_LIBID3TAG
   wxFile f;   // will be closed when it goes out of scope
   struct id3_file *fp = NULL;

   if (f.Open(mFilename)) {
      // Use id3_file_fdopen() instead of id3_file_open since wxWidgets can open a
      // file with a Unicode name and id3_file_open() can't (under Windows).
      fp = id3_file_fdopen(f.fd(), ID3_FILE_MODE_READONLY);
   }

   if (!fp) {
      return;
   }

   // The file descriptor is now owned by "fp", so we must tell "f" to forget
   // about it.
   f.Detach();

   struct id3_tag *tp = id3_file_tag(fp);
   if (!tp) {
      id3_file_close(fp);
      return;
   }

   tags->Clear();

   // Loop through all frames
   bool have_year = false;
   for (int i = 0; i < (int) tp->nframes; i++) {
      struct id3_frame *frame = tp->frames[i];

      // printf("ID: %08x '%4s'\n", (int) *(int *)frame->id, frame->id);
      // printf("Desc: %s\n", frame->description);
      // printf("Num fields: %d\n", frame->nfields);

      // for (int j = 0; j < (int) frame->nfields; j++) {
      //    printf("field %d type %d\n", j, frame->fields[j].type );
      //    if (frame->fields[j].type == ID3_FIELD_TYPE_STRINGLIST) {
      //       printf("num strings %d\n", frame->fields[j].stringlist.nstrings);
      //    }
      // }

      wxString n, v;

      // Determine the tag name
      if (strcmp(frame->id, ID3_FRAME_TITLE) == 0) {
         n = TAG_TITLE;
      }
      else if (strcmp(frame->id, ID3_FRAME_ARTIST) == 0) {
         n = TAG_ARTIST;
      }
      else if (strcmp(frame->id, ID3_FRAME_ALBUM) == 0) {
         n = TAG_ALBUM;
      }
      else if (strcmp(frame->id, ID3_FRAME_TRACK) == 0) {
         n = TAG_TRACK;
      }
      else if (strcmp(frame->id, ID3_FRAME_YEAR) == 0) {
         // LLL:  When libid3tag encounters the "TYER" tag, it converts it to a
         //       "ZOBS" (obsolete) tag and adds a "TDRC" tag at the end of the
         //       list of tags using the first 4 characters of the "TYER" tag.
         //       Since we write both the "TDRC" and "TYER" tags, the "TDRC" tag
         //       will always be encountered first in the list.  We want use it
         //       since the converted "TYER" tag may have been truncated.
         if (have_year) {
            continue;
         }
         n = TAG_YEAR;
         have_year = true;
      }
      else if (strcmp(frame->id, ID3_FRAME_COMMENT) == 0) {
         n = TAG_COMMENTS;
      }
      else if (strcmp(frame->id, ID3_FRAME_GENRE) == 0) {
         n = TAG_GENRE;
      }
   else {
         // Use frame description as default tag name.  The descriptions
         // may include several "meanings" separated by "/" characters, so
         // we just use the first meaning
         n = UTF8CTOWX(frame->description).BeforeFirst(wxT('/'));
      }

      const id3_ucs4_t *ustr = NULL;

      if (n == TAG_COMMENTS) {
         ustr = id3_field_getfullstring(&frame->fields[3]);
      }
      else if (frame->nfields == 3) {
         ustr = id3_field_getstring(&frame->fields[1]);
         if (ustr) {
            char *str = (char *)id3_ucs4_utf8duplicate(ustr);
            n = UTF8CTOWX(str);
            free(str);
         }

         ustr = id3_field_getstring(&frame->fields[2]);
      }
      else if (frame->nfields >= 2) {
         ustr = id3_field_getstrings(&frame->fields[1], 0);
      }

      if (ustr) {
         char *str = (char *)id3_ucs4_utf8duplicate(ustr);
         v = UTF8CTOWX(str);
         free(str);
      }

      if (!n.IsEmpty() && !v.IsEmpty()) {
         tags->SetTag(n, v);
   }
}

   // Convert v1 genre to name
   if (tags->HasTag(TAG_GENRE)) {
      long g = -1;
      if (tags->GetTag(TAG_GENRE).ToLong(&g)) {
         tags->SetTag(TAG_GENRE, tags->GetGenre(g));
   }
}

   id3_file_close(fp);
#endif // ifdef USE_LIBID3TAG
}
コード例 #8
0
ファイル: loader_id3.c プロジェクト: Limsik/e17
static context     *
context_create(const char *filename)
{
   context            *node = (context *) malloc(sizeof(context));
   context            *ptr, *last;
   int                 last_id = INT_MAX;

   node->refcount = 1;
   {
      struct id3_file    *file;
      struct id3_tag     *tag;
      unsigned int        i;

      file = id3_file_open(filename, ID3_FILE_MODE_READONLY);
      if (!file)
        {
           fprintf(stderr, "Unable to open tagged file %s: %s\n",
                   filename, strerror(errno));
           goto fail_free;
        }
      tag = id3_file_tag(file);
      if (!tag)
        {
           fprintf(stderr, "Unable to find ID3v2 tags in file %s\n", filename);
           id3_file_close(file);
           goto fail_free;
        }
      node->tag = id3_tag_new();
      for (i = 0; i < id3_tag_get_numframes(tag); i++)
         if (!strcmp(id3_frame_id(id3_tag_get_frame(tag, i)), "APIC"))
            id3_tag_attachframe(node->tag, id3_tag_get_frame(tag, i));
      id3_file_close(file);
   }
   node->filename = strdup(filename);
   if (!id3_ctxs)
     {
        node->id = 1;
        node->next = NULL;
        id3_ctxs = node;
        return node;
     }
   ptr = id3_ctxs;
   last = NULL;
   while (UNLIKELY(ptr && (ptr->id + 1) >= last_id))
     {
        last_id = ptr->id;
        last = ptr;
        ptr = ptr->next;
     }
   /* Paranoid! this can occur only if there are INT_MAX contexts :) */
   if (UNLIKELY(!ptr))
     {
        fprintf(stderr, "Too many open ID3 contexts\n");
        goto fail_close;
     }
   node->id = ptr->id + 1;
   if (UNLIKELY(! !last))
     {
        node->next = last->next;
        last->next = node;
     }
   else
     {
        node->next = id3_ctxs;
        id3_ctxs = node;
     }
   return node;

 fail_close:
   free(node->filename);
   id3_tag_delete(node->tag);
 fail_free:
   free(node);
   return NULL;
}
コード例 #9
0
ファイル: mpgdecoder.cpp プロジェクト: jan-lugfl/RadioMixer
// This is a shorter and faster version of scanFile(), that only scans the samplerate and number of Channels of the stream.
void mpgDecoder::readMetaFromFile( playListItem * pli )
{
#ifdef HAVE_MAD
	// use QFile as input Buffer, which is needed by libMad, cause it cannot detect EOF....
	QFile madFile(pli->getFile());
	madFile.open( QIODevice::ReadOnly );

	unsigned char buffer[65536];

	mad_stream scanStream;
	mad_header scanHeader;

	mad_stream_init (&scanStream);
	mad_header_init (&scanHeader);

	// get some more Byte from File...
	int readCnt = 0;
	while( !madFile.atEnd() && readCnt < 65536 )
	{
                buffer[readCnt] = madFile.read(1).at(0);
		readCnt++;
	}

	if (madFile.atEnd())
		return;

	mad_stream_buffer (&scanStream, buffer, readCnt );

	while (1)
        {
		if (mad_header_decode (&scanHeader, &scanStream) == -1)
		{
			if (scanStream.error == MAD_ERROR_BUFLEN)
				break;
			if (!MAD_RECOVERABLE (scanStream.error))
				break;
			continue;
		}
	}
	pli->setSamplerate( scanHeader.samplerate );
	pli->setChannels( MAD_NCHANNELS(&scanHeader) );

	mad_header_finish (&scanHeader);
	mad_stream_finish (&scanStream);
#endif
// read ID3 Metadata
#ifdef HAVE_ID3TAG
    id3_file* id3f = id3_file_open( pli->getFile().toAscii(), ID3_FILE_MODE_READONLY );
    id3_tag* id3 = id3_file_tag( id3f );

    // only overwrite metadata of playlist-item if files contains own ones...
    QString temp = getID3String(id3, ID3_FRAME_ARTIST);
    if(!temp.isEmpty())
        pli->setArtist( temp );

    temp = getID3String(id3, ID3_FRAME_TITLE);
    if(!temp.isEmpty())
        pli->setTitle( temp );

    temp = getID3String(id3, ID3_FRAME_GENRE);
    if(!temp.isEmpty())
        pli->setGenre( temp );
    id3_file_close( id3f );

#endif
}
コード例 #10
0
ファイル: mp3.c プロジェクト: BackupTheBerlios/beatforce
int
mp3_get_tag (Private * h, char *path, struct SongDBEntry *e)
{ 
    
    FILE *fd;
    mp3Private *mp3_priv = (mp3Private *) h;
    int length = 0;
    long size = 0;

    char *empty = strdup ("");
    char *title = NULL, *artist = NULL, *album = NULL;
    char *comment = NULL, *year = NULL, *genre = NULL;

    if( h == NULL ||  path == NULL ||  e ==NULL)
        return ERROR_INVALID_ARG;
  

    {
	struct id3_file *id3file;
	struct id3_tag *id3tag;
	id3_ucs4_t *ucs4;
	id3_latin1_t *latin1;
	struct id3_frame *frame;

	id3file = id3_file_open ( path, ID3_FILE_MODE_READONLY);
	if (id3file == NULL)
	{
            ERROR("get_tag: Error opening file: %s", strerror (errno));
            return -1;
	}

	id3tag = id3_file_tag (id3file);

	frame = id3_tag_findframe (id3tag, ID3_FRAME_TITLE, 0);
	if (frame != NULL)
	{
            ucs4 =
		(id3_ucs4_t *) id3_field_getstrings ((union id3_field const *)
                                                     &frame->fields[1], 0);
            if (ucs4 != NULL)
            {
		latin1 = id3_ucs4_latin1duplicate (ucs4);
		if (latin1 != NULL)
		{
                    title = strdup (latin1);
		}
            }
	}

	frame = id3_tag_findframe (id3tag, ID3_FRAME_ARTIST, 0);
	if (frame != NULL)
	{
            ucs4 = (id3_ucs4_t *) id3_field_getstrings (&frame->fields[1], 0);
            if (ucs4 != NULL)
            {
		latin1 = id3_ucs4_latin1duplicate (ucs4);
		if (latin1 != NULL)
		{
                    artist = strdup (latin1);
		}
            }
	}

	frame =
            id3_tag_findframe ((struct id3_tag const *) id3tag, ID3_FRAME_ALBUM, 0);
	if (frame != NULL)
	{
            ucs4 = (id3_ucs4_t *) id3_field_getstrings (&frame->fields[1], 0);
            if (ucs4 != NULL)
            {
		latin1 = id3_ucs4_latin1duplicate (ucs4);
		if (latin1 != NULL)
		{
                    album = strdup (latin1);
		}
            }
	}

	frame =
            id3_tag_findframe ((struct id3_tag const *) id3tag, ID3_FRAME_COMMENT,
                               0);
	if (frame != NULL)
	{
            ucs4 = (id3_ucs4_t *) id3_field_getstrings (&frame->fields[1], 0);
            if (ucs4 != NULL)
            {
		latin1 = id3_ucs4_latin1duplicate (ucs4);
		if (latin1 != NULL)
		{
                    comment = strdup (latin1);
		}
            }
	}

	frame =
            id3_tag_findframe ((struct id3_tag const *) id3tag, ID3_FRAME_YEAR, 0);
	if (frame != NULL)
	{
            ucs4 = (id3_ucs4_t *) id3_field_getstrings (&frame->fields[1], 0);
            if (ucs4 != NULL)
            {
		latin1 = id3_ucs4_latin1duplicate (ucs4);
		if (latin1 != NULL)
		{
                    year = strdup (latin1);
		}
            }
	}

	frame =
            id3_tag_findframe ((struct id3_tag const *) id3tag, ID3_FRAME_GENRE, 0);
	if (frame != NULL)
	{
            ucs4 = (id3_ucs4_t *) id3_field_getstrings (&frame->fields[1], 0);
            if (ucs4 != NULL)
            {
		ucs4 = (id3_ucs4_t *) id3_genre_name (ucs4);
		if (ucs4 != NULL)
		{
                    latin1 = id3_ucs4_latin1duplicate (ucs4);
                    if (latin1 != NULL)
                    {
			genre = strdup (latin1);
                    }
		}
            }
	}


	id3_file_close (id3file);
    }



     e->title   = title;
     e->artist  = artist;
     e->album   = album;
     e->comment = comment;
     e->year    = year;
     e->genre   = genre;


/* length calculation stuff */
    {
	struct mad_header header;
	struct xing xing;

	if(  e->AddInfo == NULL )
	{
             e->AddInfo = malloc( sizeof(struct SongAddInfo) );
            if( e->AddInfo == NULL)
                return ERROR_NO_MEMORY;
            memset(  e->AddInfo, 0, sizeof( struct SongAddInfo ));
	}

	fd = fopen ( path, "rb");
	if (fd == NULL)
	{
            ERROR("get_tag: Error opening file %s:%s",  path, strerror (errno));
            return ERROR_OPEN_ERROR;
	}

        fseek(fd,0,SEEK_END);
        size=ftell(fd);
        fseek(fd,0,SEEK_SET);
	 e->filesize = size;
        
	if (scan_header (fd, &header, &xing) == -1)
	{
            fclose (fd);

//            printf ("get_tag: Error Reading File\n");
            return ERROR_READ_SEEK_ERROR;
	}

	switch( header.layer )
	{
        case MAD_LAYER_I:  e->AddInfo->type = str_mpeg1_l1; break;
        case MAD_LAYER_II:  e->AddInfo->type = str_mpeg1_l2; break;
        case MAD_LAYER_III:
            if( header.flags & MAD_FLAG_MPEG_2_5_EXT )
                e->AddInfo->type = str_mpeg25_l3;
            else 
                 e->AddInfo->type = str_mpeg1_l3;
            break;
        default:  e->AddInfo->type = NULL; break;
	}
	 e->AddInfo->n_ch = MAD_NCHANNELS(&header);
	 e->AddInfo->SampleRate = header.samplerate;
	 e->AddInfo->bitrate = header.bitrate;

	 e->AddInfo->err_protection = ((header.flags & MAD_FLAG_PROTECTION) >0);
	 e->AddInfo->copyright = ((header.flags & MAD_FLAG_COPYRIGHT) >0);
	 e->AddInfo->original = ((header.flags & MAD_FLAG_ORIGINAL) >0);

	fseek (fd, 0, SEEK_SET);

//	   bitrate = 0;

	if (xing.flags & XING_FRAMES)
	{
            mad_timer_t timer;

            timer = header.duration;
            mad_timer_multiply (&timer, xing.frames);

            length = mad_timer_count (timer, MAD_UNITS_MILLISECONDS);
/*
  if (xing.flags & XING_BYTES)
  bitrate = xing.bytes * 8 / length;
*/
//				printf ("XING header w/ XING_FRAMES found. length = %d\n", length);

	}
	else
	{
            if (!cfg->lengthcalc)
		length = (size * 8 / (header.bitrate / 1000)); /* est. */
            else
            {
		fseek (fd, 0, SEEK_SET);
		scan_file (fd, &length, NULL);
            }
	}

	 e->time   = length;
        mp3_priv->length = length;
    }

    fclose (fd);
    mp3_priv->size = size;
    mp3_priv->position = 0;
 
    return 1;

}
コード例 #11
0
ファイル: MP3ID3.cpp プロジェクト: junagit/rns510_dtv
CMP3ID3::~CMP3ID3(void)
{
	if ( m_pID3File != NULL )
		id3_file_close(m_pID3File);
}
コード例 #12
0
ファイル: Decode.cpp プロジェクト: hihua/hihuacode
void DecodeTag(PLAYERINFO* playerinfo)
{
	const PLAYERDECODE* decode = &playerinfo->decode;
	AVFormatContext* format = decode->format;
	AVCodecContext* context = decode->context;
	PLAYERTAG* playertag = &playerinfo->tag;
	if (playertag->read)
		return;

	if (format != NULL && context != NULL)
	{
		const AVCodecDescriptor* descriptor = context->codec_descriptor;
		const char* name = descriptor->name;
		if (name != NULL)
		{
			CharToWideChar(name, 3, playertag->ext, 3);
			_wcsupr_s(playertag->ext, sizeof(playertag->ext) / sizeof(wchar_t));
		}
		
		if (StrCmp(playertag->ext, L"MP3") == 0)
		{
			const char* filename = playerinfo->filename;
			id3_file* file = id3_file_open(filename, ID3_FILE_MODE_READONLY);
			id3_tag* tag = id3_file_tag(file);
			if (tag != NULL && tag->nframes > 0)
			{
				wchar_t* title = GetMP3Tag(tag, ID3_FRAME_TITLE);
				if (title == NULL)		
					title = GetMP3Tag(tag, ID3_FRAME_ALBUM);

				wchar_t* artist = GetMP3Tag(tag, ID3_FRAME_ARTIST);

				playertag->artist = artist;
				playertag->title = title;
			}

			SAFE_DELETE_ARRAY(file->path);
			id3_file_close(file);
		}
		else
		{
			AVDictionary* dictionary = format->metadata;
			if (dictionary != NULL)
			{
				AVDictionaryEntry* entry = av_dict_get(dictionary, "title", NULL, 0);
				if (entry != NULL && entry->value != NULL)
				{
					wchar_t* title = UTF8toWideChar(entry->value, strlen(entry->value));
					playertag->title = title;
				}
				else
				{
					entry = av_dict_get(dictionary, "album", NULL, 0);
					if (entry != NULL && entry->value != NULL)
					{
						wchar_t* title = UTF8toWideChar(entry->value, strlen(entry->value));
						playertag->title = title;
					}
				}

				entry = av_dict_get(dictionary, "artist", NULL, 0);
				if (entry != NULL && entry->value != NULL)
				{
					wchar_t* artist = UTF8toWideChar(entry->value, strlen(entry->value));
					playertag->artist = artist;
				}
			}					
		}

		if (StrCmp(playertag->ext, L"PCM") == 0)		
			StrCpy(playertag->ext, L"WAV");
		
		if (playertag->title == NULL)
		{
			SAFE_DELETE_ARRAY(playertag->artist);
			SplitTag(playerinfo->filename, &playertag->title, &playertag->artist);
			if (playertag->title == NULL)
			{
				wchar_t* title = GetFileName(playerinfo->filename);
				if (title != NULL)
				{
					SplitTitle(title, &playertag->title);
					if (playertag->title == NULL)
						playertag->title = title;
					else
						SAFE_DELETE_ARRAY(title);
				}
			}

			if (playertag->title != NULL)
			{
				wchar_t* title = playertag->title;
				wchar_t* first = NULL;
				wchar_t* second = NULL;
				Split(title, L".", &first, &second);
				if (first != NULL && second != NULL)
				{
					if (IsNumber(first))
					{
						SAFE_DELETE_ARRAY(title);
						playertag->title = second;
					}
					else
					{
						SAFE_DELETE_ARRAY(second);
					}

					SAFE_DELETE_ARRAY(first);
				}				
			}
		}
		
		long duration = format->duration / 1000;
		playerinfo->duration = duration;
		duration = duration / 1000;
		long minute = duration / 60;
		long second = duration % 60;
		wsprintf(playertag->timer, L"%d:%02d", minute, second);
		wsprintf(playertag->sample, L"%dHz", context->sample_rate);

		if (context->bit_rate > 0)
			wsprintf(playertag->bitrate, L"%dkbps", context->bit_rate / 1000);
		else
			wsprintf(playertag->bitrate, L"%dkbps", format->bit_rate / 1000);

		switch (context->channels)
		{
		case 1:
			StrCpy(playertag->channels, L"单声道");
			break;

		case 4:
			StrCpy(playertag->channels, L"四声道");
			break;

		case 5:
			StrCpy(playertag->channels, L"4.1声道");
			break;

		case 6:
			StrCpy(playertag->channels, L"5.1声道");
			break;

		case 7:
			StrCpy(playertag->channels, L"6.1声道");
			break;

		case 8:
			StrCpy(playertag->channels, L"7.1声道");
			break;

		default:
			StrCpy(playertag->channels, L"立体声");
			break;
		}		
	}
	
	playertag->read = TRUE;
}
コード例 #13
0
ファイル: tagutils-mp3.c プロジェクト: MelissaJS/minidlna
static int
_get_mp3tags(char *file, struct song_metadata *psong)
{
	struct id3_file *pid3file;
	struct id3_tag *pid3tag;
	struct id3_frame *pid3frame;
	int err;
	int index;
	int used;
	unsigned char *utf8_text;
	int genre = WINAMP_GENRE_UNKNOWN;
	int have_utf8;
	int have_text;
	id3_ucs4_t const *native_text;
	char *tmp;
	int got_numeric_genre;
	id3_byte_t const *image;
	id3_length_t image_size = 0;

	pid3file = id3_file_open(file, ID3_FILE_MODE_READONLY);
	if(!pid3file)
	{
		DPRINTF(E_ERROR, L_SCANNER, "Cannot open %s\n", file);
		return -1;
	}

	pid3tag = id3_file_tag(pid3file);

	if(!pid3tag)
	{
		err = errno;
		id3_file_close(pid3file);
		errno = err;
		DPRINTF(E_WARN, L_SCANNER, "Cannot get ID3 tag for %s\n", file);
		return -1;
	}

	index = 0;
	while((pid3frame = id3_tag_findframe(pid3tag, "", index)))
	{
		used = 0;
		utf8_text = NULL;
		native_text = NULL;
		have_utf8 = 0;
		have_text = 0;

		if(!strcmp(pid3frame->id, "YTCP"))   /* for id3v2.2 */
		{
			psong->compilation = 1;
			DPRINTF(E_DEBUG, L_SCANNER, "Compilation: %d [%s]\n", psong->compilation, basename(file));
		}
		else if(!strcmp(pid3frame->id, "APIC") && !image_size)
		{
			if( (strcmp((char*)id3_field_getlatin1(&pid3frame->fields[1]), "image/jpeg") == 0) ||
			    (strcmp((char*)id3_field_getlatin1(&pid3frame->fields[1]), "image/jpg") == 0) ||
			    (strcmp((char*)id3_field_getlatin1(&pid3frame->fields[1]), "jpeg") == 0)
#if HAVE_LIBPNG
			    || (strcmp((char*)id3_field_getlatin1(&pid3frame->fields[1]), "image/png") == 0) ||
				(strcmp((char*)id3_field_getlatin1(&pid3frame->fields[1]), "png") == 0)
#endif
			)
			{
				image = id3_field_getbinarydata(&pid3frame->fields[4], &image_size);
				if( image_size )
				{
					psong->image = malloc(image_size);
					memcpy(psong->image, image, image_size);
					psong->image_size = image_size;
					//DEBUG DPRINTF(E_DEBUG, L_SCANNER, "Found thumbnail: %d\n", psong->image_size);
				}
			}
		}

		if(((pid3frame->id[0] == 'T') || (strcmp(pid3frame->id, "COMM") == 0)) &&
		   (id3_field_getnstrings(&pid3frame->fields[1])))
			have_text = 1;

		if(have_text)
		{
			native_text = id3_field_getstrings(&pid3frame->fields[1], 0);

			if(native_text)
			{
				have_utf8 = 1;
				if(lang_index >= 0)
					utf8_text = _get_utf8_text(native_text); // through iconv
				else
					utf8_text = (unsigned char*)id3_ucs4_utf8duplicate(native_text);

				if(!strcmp(pid3frame->id, "TIT2"))
				{
					used = 1;
					psong->title = (char*)utf8_text;
				}
				else if(!strcmp(pid3frame->id, "TPE1"))
				{
					used = 1;
					psong->contributor[ROLE_ARTIST] = (char*)utf8_text;
				}
				else if(!strcmp(pid3frame->id, "TALB"))
				{
					used = 1;
					psong->album = (char*)utf8_text;
				}
				else if(!strcmp(pid3frame->id, "TCOM"))
				{
					used = 1;
					psong->contributor[ROLE_COMPOSER] = (char*)utf8_text;
				}
				else if(!strcmp(pid3frame->id, "TIT1"))
				{
					used = 1;
					psong->grouping = (char*)utf8_text;
				}
				else if(!strcmp(pid3frame->id, "TPE2"))
				{
					used = 1;
					psong->contributor[ROLE_BAND] = (char*)utf8_text;
				}
				else if(!strcmp(pid3frame->id, "TPE3"))
				{
					used = 1;
					psong->contributor[ROLE_CONDUCTOR] = (char*)utf8_text;
				}
				else if(!strcmp(pid3frame->id, "TCON"))
				{
					used = 1;
					psong->genre = (char*)utf8_text;
					got_numeric_genre = 0;
					if(psong->genre)
					{
						if(!strlen(psong->genre))
						{
							genre = WINAMP_GENRE_UNKNOWN;
							got_numeric_genre = 1;
						}
						else if(isdigit(psong->genre[0]))
						{
							genre = atoi(psong->genre);
							got_numeric_genre = 1;
						}
						else if((psong->genre[0] == '(') && (isdigit(psong->genre[1])))
						{
							genre = atoi((char*)&psong->genre[1]);
							got_numeric_genre = 1;
						}

						if(got_numeric_genre)
						{
							if((genre < 0) || (genre > WINAMP_GENRE_UNKNOWN))
								genre = WINAMP_GENRE_UNKNOWN;
							free(psong->genre);
							psong->genre = strdup(winamp_genre[genre]);
						}
					}
				}
				else if(!strcmp(pid3frame->id, "COMM"))
				{
					used = 1;
					psong->comment = (char*)utf8_text;
				}
				else if(!strcmp(pid3frame->id, "TPOS"))
				{
					tmp = (char*)utf8_text;
					strsep(&tmp, "/");
					if(tmp)
					{
						psong->total_discs = atoi(tmp);
					}
					psong->disc = atoi((char*)utf8_text);
				}
				else if(!strcmp(pid3frame->id, "TRCK"))
				{
					tmp = (char*)utf8_text;
					strsep(&tmp, "/");
					if(tmp)
					{
						psong->total_tracks = atoi(tmp);
					}
					psong->track = atoi((char*)utf8_text);
				}
				else if(!strcmp(pid3frame->id, "TDRC"))
				{
					psong->year = atoi((char*)utf8_text);
				}
				else if(!strcmp(pid3frame->id, "TLEN"))
				{
					psong->song_length = atoi((char*)utf8_text);
				}
				else if(!strcmp(pid3frame->id, "TBPM"))
				{
					psong->bpm = atoi((char*)utf8_text);
				}
				else if(!strcmp(pid3frame->id, "TCMP"))
				{
					psong->compilation = (char)atoi((char*)utf8_text);
				}
			}
		}

		// check if text tag
		if((!used) && (have_utf8) && (utf8_text))
			free(utf8_text);

		// v2 COMM
		if((!strcmp(pid3frame->id, "COMM")) && (pid3frame->nfields == 4))
		{
			native_text = id3_field_getstring(&pid3frame->fields[2]);
			if(native_text)
			{
				utf8_text = (unsigned char*)id3_ucs4_utf8duplicate(native_text);
				if((utf8_text) && (strncasecmp((char*)utf8_text, "iTun", 4) != 0))
				{
					// read comment
					free(utf8_text);

					native_text = id3_field_getfullstring(&pid3frame->fields[3]);
					if(native_text)
					{
						utf8_text = (unsigned char*)id3_ucs4_utf8duplicate(native_text);
						if(utf8_text)
						{
							free(psong->comment);
							psong->comment = (char*)utf8_text;
						}
					}
				}
				else
				{
					free(utf8_text);
				}
			}
		}

		index++;
	}

	id3_file_close(pid3file);
	//DEBUG DPRINTF(E_INFO, L_SCANNER, "Got id3 tag successfully for file=%s\n", file);
	return 0;
}
コード例 #14
0
ファイル: mpg321.c プロジェクト: mvd7793/RED-SIREN
int main(int argc, char *argv[])
{
    int fd = 0;
    char *currentfile, old_dir[PATH_MAX];
    playlist *pl = NULL;
    struct id3_file *id3struct = NULL;
    struct id3_tag *id3tag = NULL;
    int retval;

    buffer playbuf;
    
    struct mad_decoder decoder;
    pthread_t keyb_thread;

    key_t sem_key;
    key_t mem_key;
    key_t frames_key;

    union semun sem_ops;
    int shm_id;
    int frames_id;
    mad_decoder_position = 0;
    output_buffer_position = 0;
    
    old_dir[0] = '\0';

    playbuf.pl = pl = new_playlist();

    if (!pl)
    {
        fprintf(stderr, "malloc failed at startup!\n");
        exit(1);
    }

    loop_remaining = 1;

    options.volume = MAD_F_ONE;

    status = MPG321_PLAYING;
    
    /* Get the command line options */
    parse_options(argc, argv, pl);

    if(options.opt & MPG321_PRINT_FFT)
	    if(!(options.opt & MPG321_REMOTE_PLAY))
	    {
		    /* printf("FFT analysis can only be used in Remote mode play.\n\n"); */
		    usage(argv[0]);			
		    exit(0);
	    }


    /* If there were no files and no playlist specified just print the usage */
    if (!playlist_file && optind == argc)
    {
        usage(argv[0]);
        exit(0);
    }

    if (playlist_file)
        load_playlist(pl, playlist_file);

    if(options.opt & MPG321_RECURSIVE_DIR)
	    add_cmdline_files_recursive_dir(pl, argv);
    else
	    add_cmdline_files(pl, argv);

    if (shuffle_play)
        shuffle_files(pl);

    if(options.opt & MPG321_ENABLE_BUFFER)
    {
	    /* Initialize semaphore and shared memeory */
	    if(access(argv[0],X_OK) == 0)
		    sem_key = ftok(argv[0],0);
	    else
		    sem_key = ftok(MPG321_PATH,0);
	    if(sem_key == -1)
	    {
		    perror("Cannot obtain resources for semaphores");
		    exit(EXIT_FAILURE);
	    }
	    semarray = semget(sem_key,3,IPC_CREAT | IPC_EXCL | S_IRWXU);
	    if(semarray == -1)
	    {
		    perror("Cannot initialize semaphores");
		    exit(EXIT_FAILURE);
	    }
	    sem_ops.val = buffer_size-1;
	    if(semctl(semarray,0,SETVAL,sem_ops) == -1)
	    {
		    perror("Error while initializing mad_decoder semaphore");
		    if(semctl(semarray,0,IPC_RMID) == -1)
			    perror("Error while destroying semaphores");
		    goto out;
		    //exit(EXIT_FAILURE);
	    }
	    sem_ops.val = 0;
	    if(semctl(semarray,1,SETVAL,sem_ops) == -1)
	    {
		    perror("Error while initializing mad_decoder semaphore");
		    if(semctl(semarray,0,IPC_RMID) == -1)
			    perror("Error while destroying semaphores");
		    goto out;
		    //exit(EXIT_FAILURE);
	    }
	    sem_ops.val = 0;
	    if(semctl(semarray,2,SETVAL,sem_ops) == -1)
	    {
		    perror("Error while initializing mad_decoder semaphore");
		    if(semctl(semarray,0,IPC_RMID) == -1)
			    perror("Error while destroying semaphores");
		    goto out;
		    //exit(EXIT_FAILURE);
	    }

	    /* Shared Memory */
	    mem_key = ftok(argv[0],1);
	    shm_id = shmget(mem_key,buffer_size * sizeof(output_frame), IPC_CREAT | S_IREAD | S_IWRITE);
	    if(shm_id == -1)
	    {
		    perror("Cannot initialize shared buffer");
		    goto out;
		    //exit(EXIT_FAILURE);
	    }
	    Output_Queue = shmat(shm_id,NULL,0);
	    if(*(int *)Output_Queue == -1)
	    {
		    perror("Error while attaching shared buffer to mad_decoder");
		    if(shmctl(shm_id,IPC_RMID,NULL))
			    perror("Cannot destroy shared buffer");
		    goto out;
		    //exit(EXIT_FAILURE);
	    }
	    static int n;
	    for(n=0;n<buffer_size;n++)
	    {
		    memset((Output_Queue+n)->data,'\0',4608);
		    memset((Output_Queue+n)->time,'\0',80);
		    (Output_Queue+n)->length = 0;
		    (Output_Queue+n)->seconds = 0;
		    (Output_Queue+n)->num_frames = 0;
	    }
	    
	    frames_key = ftok(argv[0],2);
	    frames_id = shmget(frames_key,buffer_size * sizeof(decoded_frames), IPC_CREAT | S_IREAD | S_IWRITE);
	    if(frames_id == -1)
	    {
		    perror("Cannot initialize shared frames counter");
		    goto out;
		    //exit(EXIT_FAILURE);
	    }
	    Decoded_Frames = shmat(frames_id,NULL,0);
	    if(*(int *)Decoded_Frames == -1)
	    {
		    perror("Error while attaching shared frames counter to mad_decoder");
		    if(shmctl(frames_id,IPC_RMID,NULL))
			    perror("Cannot destroy shared frames counter");
		    goto out;
		    //exit(EXIT_FAILURE);
	    }
	    	
	    Decoded_Frames->is_http = 0;
	    Decoded_Frames->is_file = 0;

    }
    else {
	    ao_initialize();
	    check_default_play_device();
    }
    
    if (!(options.opt & MPG321_REMOTE_PLAY))
    {
        handle_signals(-1); /* initialize signal handler */
        remote_input_buf[0] = '\0';
    }
    
    if (!(options.opt & MPG321_QUIET_PLAY)) 
        mpg123_boilerplate();
    
    if (options.opt & MPG321_REMOTE_PLAY)
    {
        printf ("@R MPG123\n");
	if(options.opt & MPG321_ENABLE_BUFFER)
	{
#ifdef HAVE_ALSA
		init_alsa_volume_control("default"); /* For the moment use "default", it works on most of the systems. Tested in Debian,Fedora,Ubuntu,RedHat,CentOS,Gentoo */
		if(options.volume != MAD_F_ONE)
			mpg321_alsa_set_volume((long)options.volume*volume_max/100);
#endif
	}
    }

    /* Fork here. */
    if(options.opt & MPG321_ENABLE_BUFFER)
    {
	    output_pid = fork();
	    if(output_pid == -1)
	    {
		    perror("Error while forking output process");
		    goto out; /* Release shared memeory and semaphores */
		//    exit(EXIT_FAILURE);
	    }

	    if(output_pid == 0)
	    {
		    frame_buffer_p();
		    exit(EXIT_SUCCESS);
	    }
	    signal(SIGUSR1,handle_signals);
	    if(!(options.opt & MPG321_REMOTE_PLAY))
	    {
#ifdef HAVE_ALSA
		    init_alsa_volume_control("default");
		    if(options.volume != MAD_F_ONE)
			    mpg321_alsa_set_volume((long)options.volume*volume_max/100);
#endif
	    }
    }

    if( (options.volume != MAD_F_ONE) && !(options.opt & MPG321_ENABLE_BUFFER))
    {
	    options.volume = mad_f_tofixed((long)options.volume/100.0);
    }
    else{
	    options.volume = MAD_F_ONE; /* When using the buffer options.volume when decoding each frame should be equal to MAD_F_ONE */
//	    options.volume = mad_f_tofixed((long)100.0/100.0);
    }

    if (!(options.opt & MPG321_REMOTE_PLAY))
    {
	     if(options.opt & MPG321_ENABLE_BASIC)
	     {
	 	     /* Now create and detach the basic controls thread */
		     sem_init(&main_lock,0,0);
	 	     pthread_create(&keyb_thread,NULL,read_keyb,NULL);
		     pthread_detach(keyb_thread);
	     }
     }
    if(set_xterm)
    {
	    tty_control();
	    get_term_title(title);
    }else
    {
     	
	    if (!(options.opt & MPG321_REMOTE_PLAY))
	    {
	    	    if (tcgetattr(0, &terminal_settings) < 0)
	    		    perror("tcgetattr()");
	    	    memcpy(&old_terminal_settings, &terminal_settings, sizeof(struct termios));
		    /* Early thread start */
		    sem_post(&main_lock);
	    }
    }
    /* Play the mpeg files or zip it! */
    while((currentfile = get_next_file(pl, &playbuf)))
    {
        //printf("Current File: %s\n",currentfile);
	   if (quit_now) 
            break;
        
        signal(SIGINT, SIG_DFL);
        
        playbuf.buf = NULL;
        playbuf.fd = -1;
        playbuf.length = 0;
        playbuf.done = 0;
        playbuf.num_frames = 0;
        current_frame = 0;
        playbuf.max_frames = -1;
        strncpy(playbuf.filename,currentfile, PATH_MAX);
        playbuf.filename[PATH_MAX-1] = '\0';
        
        if (status == MPG321_PLAYING || status == MPG321_STOPPED) 
            file_change = 1;

        mad_timer_reset(&playbuf.duration);
        
        mad_timer_reset(&current_time);

	id3struct = NULL;

        if (!(options.opt & MPG321_QUIET_PLAY) && file_change)
        {
           /* id3struct = id3_file_open (currentfile, ID3_FILE_MODE_READONLY);*/

            if (id3struct == NULL)
		    get_id3_info(currentfile, &id3struct, &id3tag);
	    if(id3tag)
		    show_id3(id3tag);
	}

	scrobbler_time = -1;
	if(options.opt & MPG321_USE_SCROBBLER)
	{
		if(id3struct == NULL)
			get_id3_info(currentfile,&id3struct,&id3tag);
                
	    if (id3tag)
	    {
		    char emptystring[31], emptyyear[5] = "    ";
		    int i;

		    if(parse_id3(scrobbler_args, id3tag))
		    {
			    memset(emptystring, ' ', 30);
			    emptystring[30] = '\0';
	    		    if((options.opt & MPG321_VERBOSE_PLAY) && (options.opt & MPG321_USE_SCROBBLER))
			    {
				    fprintf(stderr, "\nPreparing for the AudioScrobbler:\n");
				    for(i = 0; i < 6; i++)
				    {
					    if(scrobbler_args[i] == NULL)
						    scrobbler_args[i] =
							    ( i == 3 ? emptyyear: emptystring);
					    fprintf(stderr, "- %s\n", scrobbler_args[i]);
				    }
			    }
		    }
	    }
	}
      

        if (options.opt & MPG321_REMOTE_PLAY && file_change)
        {
		if(id3struct == NULL)
			get_id3_info(currentfile, &id3struct, &id3tag);
		if(id3tag)
                {
                    if (!show_id3(id3tag))
                    {
                        /* This shouldn't be necessary, but it appears that
                           libid3tag doesn't necessarily know if there are no
                           id3 tags on a given mp3 */
                        char * basec = strdup(currentfile);
                        char * basen = basename(basec);
                        
                        char * dot = strrchr(basen, '.');
                        
                        if (dot)
                            *dot = '\0';
                        
                        printf("@I %s\n", basen);

                        free(basec);
                    }
                }
            else
            {
                char * basec = strdup(currentfile);
                char * basen = basename(basec);
                
                char * dot = strrchr(basen, '.');
                
                if (dot)
                    *dot = '\0';
                
                printf("@I %s\n", basen);

                free(basec);
            }
        }

	if(id3struct != NULL)
		id3_file_close(id3struct);

        /* Create the MPEG stream */
        /* Check if source is on the network */
        if((fd = raw_open(currentfile)) != 0 || (fd = http_open(currentfile)) != 0
            || (fd = ftp_open(currentfile)) != 0)
        {
            playbuf.fd = fd;
            playbuf.buf = malloc(BUF_SIZE);
            playbuf.length = BUF_SIZE;
	    if(options.opt & MPG321_ENABLE_BUFFER)
	    {
		    Decoded_Frames->is_http = 1;
		    Decoded_Frames->is_file = 0;
	    }
	    calc_http_length(&playbuf);

            mad_decoder_init(&decoder, &playbuf, read_from_fd, read_header, /*filter*/0,
                            output, handle_error, /* message */ 0);
        }

        /* Check if we are to use stdin for input */
        else if(strcmp(currentfile, "-") == 0)
        {
            playbuf.fd = fileno(stdin);
            playbuf.buf = malloc(BUF_SIZE);
            playbuf.length = BUF_SIZE;

            mad_decoder_init(&decoder, &playbuf, read_from_fd, read_header, /*filter*/0,
                            output, handle_error, /* message */ 0);
        }
            
        /* currentfile is a local file (presumably.) mmap() it */
        else
        {
            struct stat stat;
            
            if((fd = open(currentfile, O_RDONLY)) == -1)
            {
	    
                mpg321_error(currentfile);
		/* Restore TTY from keyboard reader thread */
	        if(options.opt & MPG321_ENABLE_BASIC)
			if (tcsetattr(0, TCSANOW, &old_terminal_settings) < 0)
				perror("tcsetattr ICANON");
		if(set_xterm)
	    	{
			set_tty_restore();
	    		osc_print(0,0,title);
	    		if (ctty)
	    			fclose(ctty);
	    	}
		if( options.opt & MPG321_REMOTE_PLAY)
			if(remote_restart)
			{	
				clear_remote_file(pl); /* If restart is enabled, restart remote shell when file doesn't exist*/
				continue;
			}
		if(options.opt & MPG321_ENABLE_BUFFER)
			goto out;
		else
			exit(1);
                /* mpg123 stops immediately if it can't open a file */
		/* If sth goes wrong break!!!*/
                break;
            }

	    if(options.opt & MPG321_ENABLE_BUFFER)
	    {
		    Decoded_Frames->is_http = 0;
		    Decoded_Frames->is_file = 1;
	    }
            
            if(fstat(fd, &stat) == -1)
            {
                mpg321_error(currentfile);
		close(fd);
                continue;
            }
            
            if (!S_ISREG(stat.st_mode))
            {
		    if(S_ISFIFO(stat.st_mode))
		    {
			    fallback = 1;
			    goto fall_back_to_read_from_fd;
		    }

		close(fd);    
                continue;
            }
            
            retval = calc_length(currentfile, &playbuf); //FIXME Check also if it is an mp3 file. If not break and go to the next file possible
	    if(retval < 0)
	    {
		    if(options.opt & MPG321_REMOTE_PLAY)
		    {
			    fprintf(stderr,"@E Corrupted file: %s\n",currentfile);
			    close(fd);
			    if(remote_restart)
			    {
				    clear_remote_file(pl); /* If restart is enabled, restart remote shell when file is corrupted */
				    continue;
			    }
			    break;
		    }
		    mpg321_error(currentfile);
		    close(fd);
//		    break; //FIXME Break and stop OR continue the playlist ????
		    continue;
	    }

	    if((options.opt & MPG321_VERBOSE_PLAY) && (options.opt & MPG321_USE_SCROBBLER))
		    fprintf(stderr, "Track duration: %ld seconds\n",playbuf.duration.seconds);

	    if(options.opt & MPG321_USE_SCROBBLER)
		    scrobbler_set_time(playbuf.duration.seconds);

            if ((options.maxframes != -1) && (options.maxframes <= playbuf.num_frames))
            { 
                playbuf.max_frames = options.maxframes;
            }
            
            playbuf.frames = malloc((playbuf.num_frames + 1) * sizeof(void*));
            playbuf.times = malloc((playbuf.num_frames + 1) * sizeof(mad_timer_t));
#ifdef __uClinux__
	    if((playbuf.buf = mmap(0, playbuf.length, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED)
#else       
 	    if((playbuf.buf = mmap(0, playbuf.length, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED)
#endif		    
            {
                mpg321_error(currentfile);
                continue;
            }
            
            playbuf.frames[0] = playbuf.buf;
		    
	    mad_decoder_init(&decoder, &playbuf, read_from_mmap, read_header, /*filter*/0,
            
	    		    output, handle_error, /* message */ 0);
fall_back_to_read_from_fd:	//FIXME. Reported that on some embedded systems with low memory, less than 16MB doesn't work properly.
	    if(fallback)
	    {
	    
		    playbuf.fd = fd;
		    playbuf.buf = malloc(BUF_SIZE);
		    playbuf.length = BUF_SIZE;
		    mad_decoder_init(&decoder, &playbuf, read_from_fd, read_header, /*filter*/0,
				    output, handle_error, /* message */ 0);
		    fallback = 1;
	    }
        }

        if(!(options.opt & MPG321_QUIET_PLAY))/*zip it!!!*/
        {
            /* Because dirname might modify the argument */
            char * dirc = strdup(currentfile);
            char * basec = strdup(currentfile);

            char * basen = basename(basec);
            char * dirn = dirname(dirc);
            
            /* make sure that the file has a pathname; otherwise don't print out
               a Directory: listing */
            if(strchr(currentfile, '/') && strncmp(old_dir, dirn, PATH_MAX) != 0)
            {
                /* Print information about the file */
                fprintf(stderr, "\n");
                fprintf(stderr,"Directory: %s\n", dirn);
                
                strncpy(old_dir, dirn, PATH_MAX);
                old_dir[PATH_MAX-1] = '\0';
            }
            
            /* print a newline between different songs only, not after
               Directory: listing */
            else
            {
                fprintf(stderr, "\n");
            }

            fprintf(stderr,"Playing MPEG stream from %s ...\n", basen);
            
	    /* Printing xterm title */
	    if(set_xterm)
	    {
		    osc_print(0,0,basen);
	    }
	    
            free(dirc);
            free(basec);
        }    

        signal(SIGINT, handle_signals);
	signal(SIGCHLD, handle_sigchld);
        /*Give control back so that we can implement SIG's*/
	if(set_xterm)
	{
		set_tty_restore();
		if (tcgetattr(0, &terminal_settings) < 0)
			perror("tcgetattr()");
		memcpy(&old_terminal_settings, &terminal_settings, sizeof(struct termios));
		/* disable canonical mode processing in the line discipline driver */
		terminal_settings.c_lflag &= ~(ICANON | ECHO);
		/* apply our new settings */
		if (tcsetattr(0, TCSANOW, &terminal_settings) < 0)
			perror("tcsetattr ICANON");
		if(options.opt & MPG321_ENABLE_BASIC)
		{
			/* Late thread start */
			sem_post(&main_lock);
		}
	}
        /* Every time the user gets us to rewind, we exit decoding,
           reinitialize it, and re-start it */
	    
	if(options.opt & MPG321_ENABLE_BUFFER)
    	{
		Decoded_Frames->total_decoded_frames = 0;
		Decoded_Frames->done = 0;
	}
      
        while (1)
        {
            decoder.options |= MAD_OPTION_IGNORECRC;
            mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC);
	    if(options.opt & MPG321_ENABLE_BUFFER)
	    {
		    static struct sembuf start_sops = {2,-1,0};
		    semop(semarray,&start_sops,1);
		    mad_decoder_position = 0;
		    output_buffer_position = 0;
		    union semun sem_ops;
		    sem_ops.val = 0;
		    semctl(semarray,2,SETVAL,sem_ops);
		    Decoded_Frames->total_decoded_frames = 0;
		    Decoded_Frames->done = 0;
		    Decoded_Frames->is_http = 0;
		    Decoded_Frames->is_file = 0;
	    }
            /* if we're rewinding on an mmap()ed stream */
            if(status == MPG321_REWINDING && playbuf.fd == -1) 
            {
                mad_decoder_init(&decoder, &playbuf, read_from_mmap, read_header, /*filter*/0,
                    output, /*error*/0, /* message */ 0);
            }    
            else
                break;
        } 

        if (!(options.opt & MPG321_QUIET_PLAY))
        {
            char time_formatted[11];
            mad_timer_string(current_time, time_formatted, "%.1u:%.2u", MAD_UNITS_MINUTES,
                       MAD_UNITS_SECONDS, 0);
	    fprintf(stderr,"                                                                            \r");
	    fprintf(stderr, "\n[%s] Decoding of %s finished.\n",time_formatted, basename(currentfile)); /* Report total decoded seconds. Maybe for the frame buffer report only total played time?? */
        }
        
        if (options.opt & MPG321_REMOTE_PLAY && status == MPG321_STOPPED)
        {
            clear_remote_file(pl);
        }

        mad_decoder_finish(&decoder);

        if (playbuf.frames)
             free(playbuf.frames);

        if (playbuf.times)
            free(playbuf.times);
            
        if (playbuf.fd == -1)
        {
            munmap(playbuf.buf, playbuf.length);
            close(fd);
        }

        else
        {
            free(playbuf.buf);
            if (playbuf.fd != fileno(stdin)) 
                close(playbuf.fd);
        }
    }

    if(!(options.opt & MPG321_ENABLE_BUFFER))
    {
  	     if(playdevice)
		     ao_close(playdevice);
	     ao_shutdown();
     }

     if (!(options.opt & MPG321_REMOTE_PLAY))
     {
	     if(options.opt & MPG321_ENABLE_BASIC)
	     {
	 	     pflag = 1;
		     /* Restore TTY from keyboard reader thread */
	 	     if (tcsetattr(0, TCSANOW, &old_terminal_settings) < 0)
		 	     perror("tcsetattr ICANON");
	     }
     }
    /*Restoring TTY*/
    if(set_xterm)
    {
	    set_tty_restore();
	    osc_print(0,0,title);
	    if (ctty)
		    fclose(ctty);
    }

out:
    if(options.opt & MPG321_ENABLE_BUFFER)
    {
	    if(kill(output_pid,SIGUSR1) == -1)
		    perror("Error while stopping output process");
	    static int wstatus;
	    wait(&wstatus);
	    if(wstatus == -1)
		    perror("Error while waiting for output process to exit");
	    if(semctl(semarray,0,IPC_RMID) == -1)
		    perror("Error while destroying semaphores");
	    if(shmdt(Output_Queue) == -1)
		    perror("Error while detaching shared buffer");
	    if(shmctl(shm_id,IPC_RMID,NULL))
		    perror("Cannot destroy shared buffer");
	    if(shmctl(frames_id,IPC_RMID,NULL))
		    perror("Cannot destroy shared buffer");
    }
    return(0);
}
コード例 #15
0
ファイル: Tags.cpp プロジェクト: andreipaga/audacity
void Tags::ImportID3(wxString fileName)
{
#ifdef USE_LIBID3TAG 

   struct id3_file *fp = id3_file_open(OSFILENAME(fileName),
                                          ID3_FILE_MODE_READONLY);
   if (!fp) return;

   struct id3_tag *tp = id3_file_tag(fp);
   if (!tp) return;

   mTitle = GetID3FieldStr(tp, ID3_FRAME_TITLE);
   mArtist = GetID3FieldStr(tp, ID3_FRAME_ARTIST);
   mAlbum = GetID3FieldStr(tp, ID3_FRAME_ALBUM);   
   mYear = GetID3FieldStr(tp, ID3_FRAME_YEAR);
   mComments = GetID3FieldStr(tp, ID3_FRAME_COMMENT);

   long l;
   wxString s;
   if ((s = GetID3FieldStr(tp, ID3_FRAME_TRACK)).ToLong(&l))
      mTrackNum = l;

   mID3V2 = ( tp->options & ID3_TAG_OPTION_ID3V1 ) ? false : true;
   
   s = GetID3FieldStr(tp, ID3_FRAME_GENRE);

   if( mID3V2 ) {
      int numGenres = GetNumGenres();
      for(int i=0; i<numGenres; i++)
         if (0 == s.CmpNoCase(GetGenreNum(i)))
            mGenre = i;
   }
   else {
      if( s.ToLong( &l ) )
         mGenre = l;
   }

   // Loop through all remaining frames
   int i;
   for(i=0; i<(int)tp->nframes; i++) {
      struct id3_frame *frame = tp->frames[i];

      //printf("ID: %08x '%4s'\n", (int) *(int *)frame->id, frame->id);
      //printf("Desc: %s\n", frame->description);
      //printf("Num fields: %d\n", frame->nfields);
      
      if (!strcmp(frame->id, ID3_FRAME_TITLE) ||
          !strcmp(frame->id, ID3_FRAME_ARTIST) ||
          !strcmp(frame->id, ID3_FRAME_ALBUM) ||
          !strcmp(frame->id, ID3_FRAME_YEAR) ||
          !strcmp(frame->id, ID3_FRAME_COMMENT) ||
          !strcmp(frame->id, ID3_FRAME_GENRE) ||
          !strcmp(frame->id, ID3_FRAME_TRACK)) {
         continue;
      }

      const id3_ucs4_t *ustr;

      if (frame->nfields>=2) {
         ustr = id3_field_getstrings(&frame->fields[1], 0);
         if (ustr) {
            wxString name = UTF8CTOWX(frame->description);
            
            char *str = (char *)id3_ucs4_utf8duplicate(ustr);
            wxString value = UTF8CTOWX(str);
            free(str);
            
            mExtraNames.Add(name);
            mExtraValues.Add(value);
         }
      }

      if (frame->nfields==3) {
         wxString name, value;

         ustr = id3_field_getstring(&frame->fields[2]);
         if (ustr) {
            char *str = (char *)id3_ucs4_utf8duplicate(ustr);
            value = UTF8CTOWX(str);
            free(str);
         }

         ustr = id3_field_getstring(&frame->fields[1]);
         if (ustr) {
            char *str = (char *)id3_ucs4_utf8duplicate(ustr);
            name = UTF8CTOWX(str);
            free(str);
         }

         mExtraNames.Add(name);
         mExtraValues.Add(value);
      }

   }

   id3_file_close(fp);
#endif // ifdef USE_LIBID3TAG 
}
コード例 #16
0
int scan_mp3_get_mp3tags(char *file, MP3FILE *pmp3) {
    struct id3_file *pid3file;
    struct id3_tag *pid3tag;
    struct id3_frame *pid3frame;
    int err;
    int index;
    int used;
    char *utf8_text;
    int genre=WINAMP_GENRE_UNKNOWN;
    int have_utf8;
    int have_text;
    id3_ucs4_t const *native_text;
    char *tmp;
    int got_numeric_genre;
    int rating;
    char *conversion_codepage;

    pid3file=id3_file_open(file,ID3_FILE_MODE_READONLY);
    if(!pid3file) {
        DPRINTF(E_WARN,L_SCAN,"Cannot open %s\n",file);
        return FALSE;
    }

    pid3tag=id3_file_tag(pid3file);

    if(!pid3tag) {
        err=errno;
        id3_file_close(pid3file);
        errno=err;
        DPRINTF(E_WARN,L_SCAN,"Cannot get ID3 tag for %s\n",file);
        return FALSE;
    }

    DPRINTF(E_SPAM,L_SCAN,"Starting mp3 tag scan\n");

    conversion_codepage = conf_alloc_string("scanning","mp3_tag_codepage",
                                            "ISO-8859-1");

    index=0;
    while((pid3frame=id3_tag_findframe(pid3tag,"",index))) {
        used=0;
        utf8_text=NULL;
        native_text=NULL;
        have_utf8=0;
        have_text=0;

        DPRINTF(E_SPAM,L_SCAN,"Found tag %s\n",pid3frame->id);

        if(!strcmp(pid3frame->id,"YTCP")) { /* for id3v2.2 */
            pmp3->compilation = 1;
            DPRINTF(E_DBG,L_SCAN,"Compilation: %d\n", pmp3->compilation);
        }

        if(((pid3frame->id[0] == 'T')||(strcmp(pid3frame->id,"COMM")==0)) &&
           (id3_field_getnstrings(&pid3frame->fields[1])))
            have_text=1;

        if(have_text) {
            native_text=id3_field_getstrings(&pid3frame->fields[1],0);

            if(native_text) {
                have_utf8=1;


                utf8_text = (char*)id3_ucs4_utf8duplicate(native_text);
                if(utf8_text)
                    mem_register(utf8_text,0);

                if(id3_field_gettextencoding(&pid3frame->fields[1]) ==
                   ID3_FIELD_TEXTENCODING_ISO_8859_1) {
#ifdef HAVE_ICONV
                    /* this is kinda cheesy, but ucs4* == char* for 8859-1 */
                    free(utf8_text);
                    utf8_text =
                        (char*)util_xtoutf8_alloc((unsigned char*)native_text,
                                                  strlen((char*)native_text),
                                                  conversion_codepage);
#endif
                }



                if(!strcmp(pid3frame->id,"TIT2")) { /* Title */
                    used=1;
                    pmp3->title = utf8_text;
                    DPRINTF(E_DBG,L_SCAN," Title: %s\n",utf8_text);
                } else if(!strcmp(pid3frame->id,"TPE1")) {
                    used=1;
                    pmp3->artist = utf8_text;
                    DPRINTF(E_DBG,L_SCAN," Artist: %s\n",utf8_text);
                } else if(!strcmp(pid3frame->id,"TALB")) {
                    used=1;
                    pmp3->album = utf8_text;
                    DPRINTF(E_DBG,L_SCAN," Album: %s\n",utf8_text);
                } else if(!strcmp(pid3frame->id,"TCOM")) {
                    used=1;
                    pmp3->composer = utf8_text;
                    DPRINTF(E_DBG,L_SCAN," Composer: %s\n",utf8_text);
                } else if(!strcmp(pid3frame->id,"TIT1")) {
                    used=1;
                    pmp3->grouping = utf8_text;
                    DPRINTF(E_DBG,L_SCAN," Grouping: %s\n",utf8_text);
                } else if(!strcmp(pid3frame->id,"TPE2")) {
                    used=1;
                    pmp3->orchestra = utf8_text;
                    DPRINTF(E_DBG,L_SCAN," Orchestra: %s\n",utf8_text);
                } else if(!strcmp(pid3frame->id,"TPE3")) {
                    used=1;
                    pmp3->conductor = utf8_text;
                    DPRINTF(E_DBG,L_SCAN," Conductor: %s\n",utf8_text);
                } else if(!strcmp(pid3frame->id,"TCON")) {
                    used=1;
                    pmp3->genre = utf8_text;
                    got_numeric_genre=0;
                    DPRINTF(E_DBG,L_SCAN," Genre: %s\n",utf8_text);
                    if(pmp3->genre) {
                        if(!strlen(pmp3->genre)) {
                            genre=WINAMP_GENRE_UNKNOWN;
                            got_numeric_genre=1;
                        } else if (scan_mp3_is_numeric(pmp3->genre)) {
                            genre=atoi(pmp3->genre);
                            got_numeric_genre=1;
                        } else if ((pmp3->genre[0] == '(') && (isdigit(pmp3->genre[1]))) {
                            genre=atoi((char*)&pmp3->genre[1]);
                            got_numeric_genre=1;
                        }

                        if(got_numeric_genre) {
                            if((genre < 0) || (genre > WINAMP_GENRE_UNKNOWN))
                                genre=WINAMP_GENRE_UNKNOWN;
                            free(pmp3->genre);
                            pmp3->genre=strdup(scan_winamp_genre[genre]);
                        }
                    }
                } else if(!strcmp(pid3frame->id,"COMM")) {
                    used=1;
                    pmp3->comment = utf8_text;
                    DPRINTF(E_DBG,L_SCAN," Comment: %s\n",pmp3->comment);
                } else if(!strcmp(pid3frame->id,"TPOS")) {
                    tmp=utf8_text;
                    strsep(&tmp,"/");
                    if(tmp) {
                        pmp3->total_discs=atoi(tmp);
                    }
                    pmp3->disc=atoi(utf8_text);
                    DPRINTF(E_DBG,L_SCAN," Disc %d of %d\n",pmp3->disc,pmp3->total_discs);
                } else if(!strcmp(pid3frame->id,"TRCK")) {
                    tmp=utf8_text;
                    strsep(&tmp,"/");
                    if(tmp) {
                        pmp3->total_tracks=atoi(tmp);
                    }
                    pmp3->track=atoi(utf8_text);
                    DPRINTF(E_DBG,L_SCAN," Track %d of %d\n",pmp3->track,pmp3->total_tracks);
                } else if(!strcmp(pid3frame->id,"TDRC")) {
                    pmp3->year = atoi(utf8_text);
                    DPRINTF(E_DBG,L_SCAN," Year: %d\n",pmp3->year);
                } else if(!strcmp(pid3frame->id,"TLEN")) {
                    pmp3->song_length = atoi(utf8_text); /* now in ms */
                    DPRINTF(E_DBG,L_SCAN," Length: %d\n", pmp3->song_length);
                } else if(!strcmp(pid3frame->id,"TBPM")) {
                    pmp3->bpm = atoi(utf8_text);
                    DPRINTF(E_DBG,L_SCAN,"BPM: %d\n", pmp3->bpm);
                } else if(!strcmp(pid3frame->id,"TCMP")) { /* for id3v2.3 */
                    pmp3->compilation = (char)atoi(utf8_text);
                    DPRINTF(E_DBG,L_SCAN,"Compilation: %d\n", pmp3->compilation);
                }
            }
        }

        /* can check for non-text tags here */
        if((!used) && (have_utf8) && (utf8_text))
            free(utf8_text);

        if((!strcmp(pid3frame->id,"POPM")) && (pid3frame->nfields == 3)) {
            rating = id3_field_getint(&pid3frame->fields[1]);
            if(rating >= 0x01)
                pmp3->rating = 20;
            if(rating >= 0x40)
                pmp3->rating = 40;
            if(rating >= 0x80)
                pmp3->rating = 60;
            if(rating >= 0xC4)
                pmp3->rating = 80;
            if(rating >= 0xFF)
                pmp3->rating = 100;
        }


        /* v2 COMM tags are a bit different than v1 */
        if((!strcmp(pid3frame->id,"COMM")) && (pid3frame->nfields == 4)) {
            /* Make sure it isn't a application-specific comment...
             * This currently includes the following:
             *
             * iTunes_CDDB_IDs
             * iTunNORM
             *
             * If other apps stuff crap into comment fields, then we'll ignore them
             * here.
             */
            native_text=id3_field_getstring(&pid3frame->fields[2]);
            if(native_text) {
                utf8_text=(char*)id3_ucs4_utf8duplicate(native_text);
                if(utf8_text)
                    mem_register(utf8_text,0);

                if((utf8_text) && (strncasecmp(utf8_text,"iTun",4) != 0)) {
                    /* it's a real comment */
                    if(utf8_text)
                        free(utf8_text);

                    native_text=id3_field_getfullstring(&pid3frame->fields[3]);
                    if(native_text) {
                        if(pmp3->comment)
                            free(pmp3->comment);
                        utf8_text=(char*)id3_ucs4_utf8duplicate(native_text);
                        if(utf8_text) {
                            mem_register(utf8_text,0);
                            pmp3->comment=utf8_text;
                        }
                    }
                } else {
                    if(utf8_text)
                        free(utf8_text);
                }
            }
        }

        index++;
    }

    free(conversion_codepage);
    id3_file_close(pid3file);
    DPRINTF(E_DBG,L_SCAN,"Got id3 tag successfully\n");
    return TRUE;
}
コード例 #17
0
ファイル: mpg321.c プロジェクト: e3c/mpg321
int main(int argc, char *argv[])
{
    int fd = 0;
    char *currentfile, old_dir[PATH_MAX];
    playlist *pl = NULL;
    struct id3_file *id3struct = NULL;
    struct id3_tag *id3tag = NULL;

    buffer playbuf;
    
    struct mad_decoder decoder;

    old_dir[0] = '\0';

    playbuf.pl = pl = new_playlist();

    if (!pl)
    {
        fprintf(stderr, "malloc failed at startup!\n");
        exit(1);
    }

    options.volume = MAD_F_ONE;

    status = MPG321_PLAYING;
    
    /* Get the command line options */
    parse_options(argc, argv, pl);

    /* If there were no files and no playlist specified just print the usage */
    if (!playlist_file && optind == argc)
    {
        usage(argv[0]);
        exit(0);
    }

    if (playlist_file)
        load_playlist(pl, playlist_file);
    
    add_cmdline_files(pl, argv);

    if (shuffle_play)
        shuffle_files(pl);

    ao_initialize();

    check_default_play_device();
    
    if (!(options.opt & MPG321_REMOTE_PLAY))
    {
        handle_signals(-1); /* initialize signal handler */
     
        remote_input_buf[0] = '\0';
    }
    
    if (!(options.opt & MPG321_QUIET_PLAY)) 
        mpg123_boilerplate();
    
    if (options.opt & MPG321_REMOTE_PLAY)
    {
        printf ("@R MPG123\n");
    }
    
    /* Play the mpeg files or zip it! */
    while((currentfile = get_next_file(pl, &playbuf)))
    {
        if (quit_now) 
            break;
        
        signal(SIGINT, SIG_DFL);
        
        playbuf.buf = NULL;
        playbuf.fd = -1;
        playbuf.length = 0;
        playbuf.done = 0;
        playbuf.num_frames = 0;
        playbuf.max_frames = -1;
        strncpy(playbuf.filename,currentfile, PATH_MAX);
        playbuf.filename[PATH_MAX-1] = '\0';
        
        if (status == MPG321_PLAYING) 
            file_change = 1;

        mad_timer_reset(&playbuf.duration);
        
        mad_timer_reset(&current_time);

        if (!(options.opt & MPG321_QUIET_PLAY) && file_change)
        {
            id3struct = id3_file_open (currentfile, ID3_FILE_MODE_READONLY);

            if (id3struct)
            {
                id3tag = id3_file_tag (id3struct);
            
                if (id3tag)
                {
                    show_id3 (id3tag);
                }

                id3_file_close (id3struct);
            }
        }

        if (options.opt & MPG321_REMOTE_PLAY && file_change)
        {
            id3struct = id3_file_open (currentfile, ID3_FILE_MODE_READONLY);

            if (id3struct)
            {
                id3tag = id3_file_tag (id3struct);
            
                if (id3tag)
                {
                    if (!show_id3(id3tag))
                    {
                        /* This shouldn't be necessary, but it appears that
                           libid3tag doesn't necessarily know if there are no
                           id3 tags on a given mp3 */
                        char * basec = strdup(currentfile);
                        char * basen = basename(basec);
                        
                        char * dot = strrchr(basen, '.');
                        
                        if (dot)
                            *dot = '\0';
                        
                        printf("@I %s\n", basen);

                        free(basec);
                    }
                }
                
                else
                {
                    fprintf(stderr, "Allocation error");
                    exit(1);
                }

                id3_file_close (id3struct);
            }
            
            else
            {
                char * basec = strdup(currentfile);
                char * basen = basename(basec);
                
                char * dot = strrchr(basen, '.');
                
                if (dot)
                    *dot = '\0';
                
                printf("@I %s\n", basen);

                free(basec);
            }
        }

        /* Create the MPEG stream */
        /* Check if source is on the network */
        if((fd = raw_open(currentfile)) != 0 || (fd = http_open(currentfile)) != 0
            || (fd = ftp_open(currentfile)) != 0)
        {
            playbuf.fd = fd;
            playbuf.buf = malloc(BUF_SIZE);
            playbuf.length = BUF_SIZE;
            
            mad_decoder_init(&decoder, &playbuf, read_from_fd, read_header, /*filter*/0,
                            output, /*error*/0, /* message */ 0);
        }

        /* Check if we are to use stdin for input */
        else if(strcmp(currentfile, "-") == 0)
        {
            playbuf.fd = fileno(stdin);
            playbuf.buf = malloc(BUF_SIZE);
            playbuf.length = BUF_SIZE;

            mad_decoder_init(&decoder, &playbuf, read_from_fd, read_header, /*filter*/0,
                            output, /*error*/0, /* message */ 0);
        }
            
        /* currentfile is a local file (presumably.) mmap() it */
        else
        {
            struct stat stat;
            
            if((fd = open(currentfile, O_RDONLY)) == -1)
            {
                mpg321_error(currentfile);

                /* mpg123 stops immediately if it can't open a file */
                break;
            }
            
            if(fstat(fd, &stat) == -1)
            {
                close(fd);
                mpg321_error(currentfile);
                continue;
            }
            
            if (!S_ISREG(stat.st_mode))
            {
                close(fd);
                continue;
            }
            
            calc_length(currentfile, &playbuf);

            if ((options.maxframes != -1) && (options.maxframes <= playbuf.num_frames))
            { 
                playbuf.max_frames = options.maxframes;
            }
            
            playbuf.frames = malloc((playbuf.num_frames + 1) * sizeof(void*));
            playbuf.times = malloc((playbuf.num_frames + 1) * sizeof(mad_timer_t));
    
            if((playbuf.buf = mmap(0, playbuf.length, PROT_READ, MAP_SHARED, fd, 0))
                                == MAP_FAILED)
            {
                close(fd);
                mpg321_error(currentfile);
                continue;
            }
            
            close(fd);
            playbuf.frames[0] = playbuf.buf;
            
            mad_decoder_init(&decoder, &playbuf, read_from_mmap, read_header, /*filter*/0,
                            output, /*error*/0, /* message */ 0);
        }

        if(!(options.opt & MPG321_QUIET_PLAY))/*zip it!!!*/
        {
            /* Because dirname might modify the argument */
            char * dirc = strdup(currentfile);
            char * basec = strdup(currentfile);

            char * basen = basename(basec);
            char * dirn = dirname(dirc);
            
            /* make sure that the file has a pathname; otherwise don't print out
               a Directory: listing */
            if(strchr(currentfile, '/') && strncmp(old_dir, dirn, PATH_MAX) != 0)
            {
                /* Print information about the file */
                fprintf(stderr, "\n");
                fprintf(stderr,"Directory: %s/\n", dirn);
                
                strncpy(old_dir, dirn, PATH_MAX);
                old_dir[PATH_MAX-1] = '\0';
            }
            
            /* print a newline between different songs only, not after
               Directory: listing */
            else
            {
                fprintf(stderr, "\n");
            }

            fprintf(stderr,"Playing MPEG stream from %s ...\n", basen);
    
            free(dirc);
            free(basec);
        }    

        signal(SIGINT, handle_signals);

        /* Every time the user gets us to rewind, we exit decoding,
           reinitialize it, and re-start it */
        while (1)
        {
            mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC);
            
            /* if we're rewinding on an mmap()ed stream */
            if(status == MPG321_REWINDING && playbuf.fd == -1) 
            {
                mad_decoder_init(&decoder, &playbuf, read_from_mmap, read_header, /*filter*/0,
                    output, /*error*/0, /* message */ 0);
            }    
            else
                break;
        } 

        if (!(options.opt & MPG321_QUIET_PLAY))
        {
            char time_formatted[11];
            mad_timer_string(current_time, time_formatted, "%.1u:%.2u", MAD_UNITS_MINUTES,
                       MAD_UNITS_SECONDS, 0);
            fprintf(stderr, "\n[%s] Decoding of %s finished.\n",time_formatted, basename(currentfile));
        }
        
        if (options.opt & MPG321_REMOTE_PLAY && status == MPG321_STOPPED)
        {
            clear_remote_file(pl);
        }

        mad_decoder_finish(&decoder);

        if (quit_now)
            break;

        if (playbuf.frames)
             free(playbuf.frames);

        if (playbuf.times)
            free(playbuf.times);
            
        if (playbuf.fd == -1)
        {
            munmap(playbuf.buf, playbuf.length);
        }

        else
        {
            free(playbuf.buf);
            if (playbuf.fd != fileno(stdin)) 
                close(playbuf.fd);
        }
    }

    if(playdevice)
        ao_close(playdevice);

    ao_shutdown();

#if defined(RAW_SUPPORT) || defined(HTTP_SUPPORT) || defined(FTP_SUPPORT) 
    if(fd) close(fd);
#endif

    return(0);
}