make song information handling UTF8 aware trunk
authornathan
Thu, 12 Feb 2009 20:47:23 +0800
branchtrunk
changeset 25887faebaba0a
parent 24 0598c933ccae
child 26 b99a156ae98f
make song information handling UTF8 aware
HISTORY
Makefile
common.h
compat.c
compat.h
decoder-core.h
decoder-mp3.c
decoder-ogg.c
decoder-snd.c
decoder.c
decoder.h
mp3.c
     1.1 --- a/HISTORY	Wed Feb 04 19:34:25 2009 +0800
     1.2 +++ b/HISTORY	Thu Feb 12 20:47:23 2009 +0800
     1.3 @@ -7,6 +7,8 @@
     1.4  - Fixed possible division by zero in libsndfile decoder.
     1.5  - Fixed some gcc 4.x warnings.
     1.6  - Added commandline option for a user defined default background image.
     1.7 +- Made the handling of song information (e.g. ID3) UTF-8 aware. The infocache
     1.8 +  file is kept in UTF-8 format now.
     1.9  - Map audio-button to "switch_audio" slave command in MPlayer replay. Suggested
    1.10    by Martin Dauskardt.
    1.11  - Use blocking IO for OSS output for improved compatibility. Suggested by Martin
     2.1 --- a/Makefile	Wed Feb 04 19:34:25 2009 +0800
     2.2 +++ b/Makefile	Thu Feb 12 20:47:23 2009 +0800
     2.3 @@ -1,7 +1,7 @@
     2.4  #
     2.5  # MP3/MPlayer plugin to VDR
     2.6  #
     2.7 -# (C) 2001-2008 Stefan Huelswitt <s.huelswitt@gmx.de>
     2.8 +# (C) 2001-2009 Stefan Huelswitt <s.huelswitt@gmx.de>
     2.9  #
    2.10  # This code is free software; you can redistribute it and/or
    2.11  # modify it under the terms of the GNU General Public License
    2.12 @@ -108,7 +108,7 @@
    2.13  OBJS     = $(PLUGIN).o $(COM_OBJS)\
    2.14              data-mp3.o setup-mp3.o player-mp3.o stream.o network.o\
    2.15              decoder.o decoder-mp3.o decoder-mp3-stream.o decoder-snd.o \
    2.16 -            decoder-ogg.o
    2.17 +            decoder-ogg.o compat.o
    2.18  LIBS     = -lmad -lid3tag
    2.19  
    2.20  ifndef WITHOUT_LIBSNDFILE
     3.1 --- a/common.h	Wed Feb 04 19:34:25 2009 +0800
     3.2 +++ b/common.h	Thu Feb 12 20:47:23 2009 +0800
     3.3 @@ -30,6 +30,7 @@
     3.4  #include <vdr/config.h>
     3.5  #endif
     3.6  #include "config.h"
     3.7 +#include "compat.h"
     3.8  
     3.9  #if !defined(NO_DEBUG) && defined(DEBUG)
    3.10  #define d(x) { (x); }
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/compat.c	Thu Feb 12 20:47:23 2009 +0800
     4.3 @@ -0,0 +1,107 @@
     4.4 +/*
     4.5 + * MP3/MPlayer plugin to VDR (C++)
     4.6 + *
     4.7 + * (C) 2001-2009 Stefan Huelswitt <s.huelswitt@gmx.de>
     4.8 + *
     4.9 + * This code is free software; you can redistribute it and/or
    4.10 + * modify it under the terms of the GNU General Public License
    4.11 + * as published by the Free Software Foundation; either version 2
    4.12 + * of the License, or (at your option) any later version.
    4.13 + *
    4.14 + * This code is distributed in the hope that it will be useful,
    4.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    4.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    4.17 + * GNU General Public License for more details.
    4.18 + *
    4.19 + * You should have received a copy of the GNU General Public License
    4.20 + * along with this program; if not, write to the Free Software
    4.21 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
    4.22 + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
    4.23 + */
    4.24 +
    4.25 +#include <stdlib.h>
    4.26 +#include <string.h>
    4.27 +
    4.28 +#if APIVERSNUM < 10503
    4.29 +
    4.30 +#include <errno.h>
    4.31 +#include <vdr/tools.h>
    4.32 +#include "common.h"
    4.33 +
    4.34 +// --- cCharSetConv ----------------------------------------------------------
    4.35 +
    4.36 +char *cCharSetConv::systemCharacterTable = NULL;
    4.37 +
    4.38 +cCharSetConv::cCharSetConv(const char *FromCode, const char *ToCode)
    4.39 +{
    4.40 +  if (!FromCode)
    4.41 +     FromCode = systemCharacterTable;
    4.42 +  if (!ToCode)
    4.43 +     ToCode = "UTF-8";
    4.44 +  cd = (FromCode && ToCode) ? iconv_open(ToCode, FromCode) : (iconv_t)-1;
    4.45 +  result = NULL;
    4.46 +  length = 0;
    4.47 +}
    4.48 +
    4.49 +cCharSetConv::~cCharSetConv()
    4.50 +{
    4.51 +  free(result);
    4.52 +  iconv_close(cd);
    4.53 +}
    4.54 +
    4.55 +void cCharSetConv::SetSystemCharacterTableX(const char *CharacterTable)
    4.56 +{
    4.57 +  free(systemCharacterTable);
    4.58 +  systemCharacterTable = NULL;
    4.59 +  if (!strcasestr(CharacterTable, "UTF-8")) {
    4.60 +     systemCharacterTable = strdup(CharacterTable);
    4.61 +     }
    4.62 +}
    4.63 +
    4.64 +const char *cCharSetConv::Convert(const char *From, char *To, size_t ToLength)
    4.65 +{
    4.66 +  if (cd != (iconv_t)-1 && From && *From) {
    4.67 +     char *FromPtr = (char *)From;
    4.68 +     size_t FromLength = strlen(From);
    4.69 +     char *ToPtr = To;
    4.70 +     if (!ToPtr) {
    4.71 +        length = max(length, FromLength * 2); // some reserve to avoid later reallocations
    4.72 +        result = (char *)realloc(result, length);
    4.73 +        ToPtr = result;
    4.74 +        ToLength = length;
    4.75 +        }
    4.76 +     else if (!ToLength)
    4.77 +        return From; // can't convert into a zero sized buffer
    4.78 +     ToLength--; // save space for terminating 0
    4.79 +     char *Converted = ToPtr;
    4.80 +     while (FromLength > 0) {
    4.81 +           if (iconv(cd, &FromPtr, &FromLength, &ToPtr, &ToLength) == size_t(-1)) {
    4.82 +              if (errno == E2BIG || errno == EILSEQ && ToLength < 1) {
    4.83 +                 if (To)
    4.84 +                    break; // caller provided a fixed size buffer, but it was too small
    4.85 +                 // The result buffer is too small, so increase it:
    4.86 +                 size_t d = ToPtr - result;
    4.87 +                 size_t r = length / 2;
    4.88 +                 length += r;
    4.89 +                 Converted = result = (char *)realloc(result, length);
    4.90 +                 ToLength += r;
    4.91 +                 ToPtr = result + d;
    4.92 +                 }
    4.93 +              if (errno == EILSEQ) {
    4.94 +                 // A character can't be converted, so mark it with '?' and proceed:
    4.95 +                 FromPtr++;
    4.96 +                 FromLength--;
    4.97 +                 *ToPtr++ = '?';
    4.98 +                 ToLength--;
    4.99 +                 }
   4.100 +              else if (errno != E2BIG)
   4.101 +                 return From; // unknown error, return original string
   4.102 +              }
   4.103 +           }
   4.104 +     *ToPtr = 0;
   4.105 +     return Converted;
   4.106 +     }
   4.107 +  return From;
   4.108 +}
   4.109 +
   4.110 +#endif
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/compat.h	Thu Feb 12 20:47:23 2009 +0800
     5.3 @@ -0,0 +1,48 @@
     5.4 +/*
     5.5 + * MP3/MPlayer plugin to VDR (C++)
     5.6 + *
     5.7 + * (C) 2001-2009 Stefan Huelswitt <s.huelswitt@gmx.de>
     5.8 + *
     5.9 + * This code is free software; you can redistribute it and/or
    5.10 + * modify it under the terms of the GNU General Public License
    5.11 + * as published by the Free Software Foundation; either version 2
    5.12 + * of the License, or (at your option) any later version.
    5.13 + *
    5.14 + * This code is distributed in the hope that it will be useful,
    5.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    5.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    5.17 + * GNU General Public License for more details.
    5.18 + *
    5.19 + * You should have received a copy of the GNU General Public License
    5.20 + * along with this program; if not, write to the Free Software
    5.21 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
    5.22 + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
    5.23 + */
    5.24 +
    5.25 +#ifndef ___COMPAT_H
    5.26 +#define ___COMPAT_H
    5.27 +
    5.28 +#ifndef APIVERSNUM
    5.29 +#include <vdr/config.h>
    5.30 +#endif
    5.31 +
    5.32 +#if APIVERSNUM < 10503
    5.33 +#include <iconv.h>
    5.34 +
    5.35 +class cCharSetConv {
    5.36 +private:
    5.37 +  iconv_t cd;
    5.38 +  char *result;
    5.39 +  size_t length;
    5.40 +  static char *systemCharacterTable;
    5.41 +public:
    5.42 +  cCharSetConv(const char *FromCode = NULL, const char *ToCode = NULL);
    5.43 +  ~cCharSetConv();
    5.44 +  const char *Convert(const char *From, char *To = NULL, size_t ToLength = 0);
    5.45 +  static const char *SystemCharacterTable(void) { return systemCharacterTable; }
    5.46 +  static void SetSystemCharacterTableX(const char *CharacterTable);
    5.47 +  };
    5.48 +
    5.49 +#endif
    5.50 +
    5.51 +#endif //___COMPAT_H
     6.1 --- a/decoder-core.h	Wed Feb 04 19:34:25 2009 +0800
     6.2 +++ b/decoder-core.h	Thu Feb 12 20:47:23 2009 +0800
     6.3 @@ -1,7 +1,7 @@
     6.4  /*
     6.5   * MP3/MPlayer plugin to VDR (C++)
     6.6   *
     6.7 - * (C) 2001-2005 Stefan Huelswitt <s.huelswitt@gmx.de>
     6.8 + * (C) 2001-2009 Stefan Huelswitt <s.huelswitt@gmx.de>
     6.9   *
    6.10   * This code is free software; you can redistribute it and/or
    6.11   * modify it under the terms of the GNU General Public License
    6.12 @@ -38,7 +38,7 @@
    6.13  
    6.14  // ----------------------------------------------------------------
    6.15  
    6.16 -#define CACHE_VERSION 7
    6.17 +#define CACHE_VERSION 8
    6.18  
    6.19  class cCacheData : public cSongInfo, public cFileInfo, public cListObject {
    6.20  friend class cInfoCache;
    6.21 @@ -46,13 +46,15 @@
    6.22    int hash, version;
    6.23    time_t touch;
    6.24    cMutex lock;
    6.25 +  //
    6.26 +  bool Check8bit(const char *str);
    6.27  protected:
    6.28    bool Save(FILE *f);
    6.29    bool Load(FILE *f);
    6.30    bool Upgrade(void);
    6.31    void Touch(void);
    6.32    bool Purge(void);
    6.33 -  void Create(cFileInfo *fi, cSongInfo *si);
    6.34 +  void Create(cFileInfo *fi, cSongInfo *si, bool update);
    6.35  public:
    6.36    cCacheData(void);
    6.37    void Lock(void) { lock.Lock(); }
     7.1 --- a/decoder-mp3.c	Wed Feb 04 19:34:25 2009 +0800
     7.2 +++ b/decoder-mp3.c	Thu Feb 12 20:47:23 2009 +0800
     7.3 @@ -1,7 +1,7 @@
     7.4  /*
     7.5   * MP3/MPlayer plugin to VDR (C++)
     7.6   *
     7.7 - * (C) 2001-2005 Stefan Huelswitt <s.huelswitt@gmx.de>
     7.8 + * (C) 2001-2009 Stefan Huelswitt <s.huelswitt@gmx.de>
     7.9   *
    7.10   * This code is free software; you can redistribute it and/or
    7.11   * modify it under the terms of the GNU General Public License
    7.12 @@ -369,6 +369,7 @@
    7.13    cCacheData *dat=InfoCache.Search(str);
    7.14    if(dat) {
    7.15      Set(dat); dat->Unlock();
    7.16 +    ConvertToSys();
    7.17      if(!DecoderID) {
    7.18        DecoderID=DEC_MP3;
    7.19        InfoCache.Cache(this,str);
    7.20 @@ -518,6 +519,7 @@
    7.21  
    7.22        if(!has_id3 || !Title) FakeTitle(str->Filename,".mp3");
    7.23        InfoCache.Cache(this,str);
    7.24 +      ConvertToSys();
    7.25        }
    7.26      }
    7.27    return Abort(res);
    7.28 @@ -612,12 +614,7 @@
    7.29      const id3_ucs4_t *ucs4=id3_field_getstrings(field,0);
    7.30      if(!ucs4) return;
    7.31      if(!strcmp(id,ID3_FRAME_GENRE)) ucs4=id3_genre_name(ucs4);
    7.32 -
    7.33 -    id3_latin1_t *latin1=id3_ucs4_latin1duplicate(ucs4);
    7.34 -    if(!latin1) return;
    7.35 -
    7.36 -    data=strdup((char *)latin1);
    7.37 -    free(latin1);
    7.38 +    data=(char *)id3_ucs4_utf8duplicate(ucs4);
    7.39      }
    7.40  }
    7.41  
     8.1 --- a/decoder-ogg.c	Wed Feb 04 19:34:25 2009 +0800
     8.2 +++ b/decoder-ogg.c	Thu Feb 12 20:47:23 2009 +0800
     8.3 @@ -1,7 +1,7 @@
     8.4  /*
     8.5   * MP3/MPlayer plugin to VDR (C++)
     8.6   *
     8.7 - * (C) 2001-2005 Stefan Huelswitt <s.huelswitt@gmx.de>
     8.8 + * (C) 2001-2009 Stefan Huelswitt <s.huelswitt@gmx.de>
     8.9   *
    8.10   * This code is free software; you can redistribute it and/or
    8.11   * modify it under the terms of the GNU General Public License
    8.12 @@ -147,6 +147,7 @@
    8.13    cCacheData *dat=InfoCache.Search(file);
    8.14    if(dat) {
    8.15      Set(dat); dat->Unlock();
    8.16 +    ConvertToSys();
    8.17      if(!DecoderID) {
    8.18        DecoderID=DEC_OGG;
    8.19        InfoCache.Cache(this,file);
    8.20 @@ -205,7 +206,8 @@
    8.21  
    8.22    InfoDone();
    8.23    InfoCache.Cache(this,file);
    8.24 -  return Abort(true);  
    8.25 +  ConvertToSys();
    8.26 +  return Abort(true);
    8.27  }
    8.28  
    8.29  // --- cOggDecoder -------------------------------------------------------------
     9.1 --- a/decoder-snd.c	Wed Feb 04 19:34:25 2009 +0800
     9.2 +++ b/decoder-snd.c	Thu Feb 12 20:47:23 2009 +0800
     9.3 @@ -1,7 +1,7 @@
     9.4  /*
     9.5   * MP3/MPlayer plugin to VDR (C++)
     9.6   *
     9.7 - * (C) 2001-2007 Stefan Huelswitt <s.huelswitt@gmx.de>
     9.8 + * (C) 2001-2009 Stefan Huelswitt <s.huelswitt@gmx.de>
     9.9   *
    9.10   * This code is free software; you can redistribute it and/or
    9.11   * modify it under the terms of the GNU General Public License
    9.12 @@ -58,6 +58,7 @@
    9.13  
    9.14  #define CDDB_PROTO 5                   // used protocol level
    9.15  #define CDDB_TOUT  30*1000             // connection timeout (ms)
    9.16 +#define CDDB_CHARSET "ISO8859-1"       // data charset
    9.17  
    9.18  const char *cddbpath="/var/lib/cddb";  // default local cddb path
    9.19  
    9.20 @@ -410,7 +411,7 @@
    9.21    //
    9.22    cCDDBSong *GetTrack(const char *name, unsigned int pos);
    9.23    cCDDBSong *FindTrack(int tr);
    9.24 -  void Strcat(char * &store, char *value);
    9.25 +  void Strcat(char * &store, const char *value);
    9.26    bool Split(const char *source, char div, char * &first, char * &second, bool only3=false);
    9.27    void Put(const char *from, char * &to);
    9.28    void Clean(void);
    9.29 @@ -472,6 +473,7 @@
    9.30    DiscID=id->discid;
    9.31    FILE *f=fopen(filename,"r");
    9.32    if(f) {
    9.33 +    cCharSetConv csc(CDDB_CHARSET);
    9.34      char buff[1024];
    9.35      while(fgets(buff,sizeof(buff),f)) {
    9.36        int i=strlen(buff);
    9.37 @@ -484,7 +486,7 @@
    9.38          if(p) {
    9.39             *p=0;
    9.40             char *name =compactspace(buff);
    9.41 -           char *value=compactspace(p+1);
    9.42 +           const char *value=csc.Convert(compactspace(p+1));
    9.43             if(*name && *value) {
    9.44               if(!strcasecmp(name,"DTITLE")) Strcat(DTitle,value);
    9.45               else if(!strcasecmp(name,"EXTD")) Strcat(ExtD,value);
    9.46 @@ -588,7 +590,7 @@
    9.47    return false;
    9.48  }
    9.49  
    9.50 -void cCDDBDisc::Strcat(char * &store, char *value)
    9.51 +void cCDDBDisc::Strcat(char * &store, const char *value)
    9.52  {
    9.53    if(store) {
    9.54      char *n=MALLOC(char,strlen(store)+strlen(value)+1);
    9.55 @@ -828,6 +830,7 @@
    9.56    cCacheData *dat=InfoCache.Search(file);
    9.57    if(dat) {
    9.58      Set(dat); dat->Unlock();
    9.59 +    ConvertToSys();
    9.60      if(!DecoderID) {
    9.61        DecoderID=DEC_SND;
    9.62        InfoCache.Cache(this,file);
    9.63 @@ -850,7 +853,8 @@
    9.64  
    9.65    InfoDone();
    9.66    InfoCache.Cache(this,file);
    9.67 -  return Abort(true);  
    9.68 +  ConvertToSys();
    9.69 +  return Abort(true);
    9.70  }
    9.71  
    9.72  bool cSndInfo::CDDBLookup(const char *filename)
    10.1 --- a/decoder.c	Wed Feb 04 19:34:25 2009 +0800
    10.2 +++ b/decoder.c	Thu Feb 12 20:47:23 2009 +0800
    10.3 @@ -1,7 +1,7 @@
    10.4  /*
    10.5   * MP3/MPlayer plugin to VDR (C++)
    10.6   *
    10.7 - * (C) 2001-2007 Stefan Huelswitt <s.huelswitt@gmx.de>
    10.8 + * (C) 2001-2009 Stefan Huelswitt <s.huelswitt@gmx.de>
    10.9   *
   10.10   * This code is free software; you can redistribute it and/or
   10.11   * modify it under the terms of the GNU General Public License
   10.12 @@ -53,6 +53,35 @@
   10.13    return h;
   10.14  }
   10.15  
   10.16 +// --- cStrConv ----------------------------------------------------------------
   10.17 +
   10.18 +class cStrConv : private cMutex {
   10.19 +private:
   10.20 +  cCharSetConv toSys;
   10.21 +public:
   10.22 +  cStrConv(void):toSys("UTF-8",cCharSetConv::SystemCharacterTable()) {}
   10.23 +  char *ToSys(char *from);
   10.24 +  };
   10.25 +
   10.26 +static cStrConv *strconv;
   10.27 +  
   10.28 +char *cStrConv::ToSys(char *from)
   10.29 +{
   10.30 +  if(from) {
   10.31 +    Lock();
   10.32 +    const char *r=toSys.Convert(from);
   10.33 +    Unlock();
   10.34 +    if(r!=from) {
   10.35 +      char *n=strdup(r);
   10.36 +      if(n) {
   10.37 +        free(from);
   10.38 +        return n;
   10.39 +        }
   10.40 +      }
   10.41 +    }
   10.42 +  return from;
   10.43 +}
   10.44 +
   10.45  // --- cSongInfo ---------------------------------------------------------------
   10.46  
   10.47  cSongInfo::cSongInfo(void)
   10.48 @@ -75,12 +104,18 @@
   10.49    free(Album); Album=0;
   10.50    Year=-1;
   10.51    Level=Peak=0.0;
   10.52 -  infoDone=false;
   10.53 -}
   10.54 -
   10.55 -void cSongInfo::Set(cSongInfo *si)
   10.56 -{
   10.57 -  Clear(); InfoDone();
   10.58 +  infoDone=false; utf8clean=true;
   10.59 +}
   10.60 +
   10.61 +void cSongInfo::Set(cSongInfo *si, bool update)
   10.62 +{
   10.63 +  if(!update || si->Utf8Clean()) {
   10.64 +    Clear();
   10.65 +    Title=si->Title ? strdup(si->Title):0;
   10.66 +    Artist=si->Artist ? strdup(si->Artist):0;
   10.67 +    Album=si->Album ? strdup(si->Album):0;
   10.68 +    utf8clean=si->utf8clean;
   10.69 +    }
   10.70    Frames=si->Frames;
   10.71    Total=si->Total;
   10.72    SampleFreq=si->SampleFreq;
   10.73 @@ -89,14 +124,12 @@
   10.74    MaxBitrate=si->MaxBitrate;
   10.75    ChMode=si->ChMode;
   10.76    Year=si->Year;
   10.77 -  Title=si->Title ? strdup(si->Title):0;
   10.78 -  Artist=si->Artist ? strdup(si->Artist):0;
   10.79 -  Album=si->Album ? strdup(si->Album):0;
   10.80    if(si->Level>0.0) { // preserve old level
   10.81      Level=si->Level;
   10.82      Peak=si->Peak;
   10.83      }
   10.84    DecoderID=si->DecoderID;
   10.85 +  InfoDone();
   10.86  }
   10.87  
   10.88  void cSongInfo::FakeTitle(const char *filename, const char *extention)
   10.89 @@ -121,6 +154,16 @@
   10.90      }
   10.91  }
   10.92  
   10.93 +void cSongInfo::ConvertToSys(void)
   10.94 +{
   10.95 +  if(cCharSetConv::SystemCharacterTable()) {
   10.96 +    Title=strconv->ToSys(Title);
   10.97 +    Artist=strconv->ToSys(Artist);
   10.98 +    Album=strconv->ToSys(Album);
   10.99 +    utf8clean=false;
  10.100 +    }
  10.101 +}
  10.102 +
  10.103  // --- cFileInfo ---------------------------------------------------------------
  10.104  
  10.105  cFileInfo::cFileInfo(void)
  10.106 @@ -349,8 +392,18 @@
  10.107    return false;
  10.108  }
  10.109  
  10.110 +bool cCacheData::Check8bit(const char *str)
  10.111 +{
  10.112 +  if(str) while(*str) if(*str++ & 0x80) return true;
  10.113 +  return false;
  10.114 +}
  10.115 +
  10.116  bool cCacheData::Upgrade(void)
  10.117  {
  10.118 +  if(version<8) {
  10.119 +    if(Check8bit(Title) || Check8bit(Artist) || Check8bit(Album))
  10.120 +      return false;              // Trash entries not 7bit clean
  10.121 +    }
  10.122    if(version<7) {
  10.123      if(DecoderID==DEC_SND || (Title && startswith(Title,"track-")))
  10.124        return false;              // Trash older SND entries (incomplete)
  10.125 @@ -372,10 +425,10 @@
  10.126    return true;
  10.127  }
  10.128  
  10.129 -void cCacheData::Create(cFileInfo *fi, cSongInfo *si)
  10.130 +void cCacheData::Create(cFileInfo *fi, cSongInfo *si, bool update)
  10.131  {
  10.132    cFileInfo::Set(fi);
  10.133 -  cSongInfo::Set(si);
  10.134 +  cSongInfo::Set(si,update);
  10.135    hash=MakeHash(Filename);
  10.136    Touch();
  10.137  }
  10.138 @@ -472,14 +525,14 @@
  10.139    lock.Lock();
  10.140    cCacheData *dat=Search(file);
  10.141    if(dat) {
  10.142 -    dat->Create(file,info);
  10.143 +    dat->Create(file,info,true);
  10.144      Modified();
  10.145      dat->Unlock();
  10.146      d(printf("cache: updating infos for %s\n",file->Filename))
  10.147      }
  10.148    else {
  10.149      dat=new cCacheData;
  10.150 -    dat->Create(file,info);
  10.151 +    dat->Create(file,info,false);
  10.152      AddEntry(dat);
  10.153      d(printf("cache: caching infos for %s\n",file->Filename))
  10.154      }
  10.155 @@ -601,6 +654,8 @@
  10.156  
  10.157  void cInfoCache::Load(void)
  10.158  {
  10.159 +  if(!strconv) strconv=new cStrConv;
  10.160 +
  10.161    char *name=CacheFile();
  10.162    if(access(name,F_OK)==0) {
  10.163      isyslog("loading id3 cache from %s",name);
    11.1 --- a/decoder.h	Wed Feb 04 19:34:25 2009 +0800
    11.2 +++ b/decoder.h	Thu Feb 12 20:47:23 2009 +0800
    11.3 @@ -1,7 +1,7 @@
    11.4  /*
    11.5   * MP3/MPlayer plugin to VDR (C++)
    11.6   *
    11.7 - * (C) 2001-2007 Stefan Huelswitt <s.huelswitt@gmx.de>
    11.8 + * (C) 2001-2009 Stefan Huelswitt <s.huelswitt@gmx.de>
    11.9   *
   11.10   * This code is free software; you can redistribute it and/or
   11.11   * modify it under the terms of the GNU General Public License
   11.12 @@ -37,16 +37,18 @@
   11.13  
   11.14  class cSongInfo {
   11.15  private:
   11.16 -  bool infoDone;
   11.17 +  bool infoDone, utf8clean;
   11.18  protected:
   11.19    void Clear(void);
   11.20 -  void Set(cSongInfo *si);
   11.21 +  void Set(cSongInfo *si, bool update=false);
   11.22    void FakeTitle(const char *filename, const char *extention=0);
   11.23    void InfoDone(void) { infoDone=true; }
   11.24  public:
   11.25    cSongInfo(void);
   11.26    ~cSongInfo();
   11.27    bool HasInfo(void) { return infoDone; }
   11.28 +  bool Utf8Clean(void) { return utf8clean; }
   11.29 +  void ConvertToSys(void);
   11.30    // Song
   11.31    char *Title, *Artist, *Album;
   11.32    int Year, Frames, Total;
    12.1 --- a/mp3.c	Wed Feb 04 19:34:25 2009 +0800
    12.2 +++ b/mp3.c	Thu Feb 12 20:47:23 2009 +0800
    12.3 @@ -1541,6 +1541,9 @@
    12.4  #if APIVERSNUM < 10507
    12.5    RegisterI18n(Phrases);
    12.6  #endif
    12.7 +#if APIVERSNUM < 10503
    12.8 +  cCharSetConv::SetSystemCharacterTableX(I18nCharSets()[Setup.OSDLanguage]);
    12.9 +#endif
   12.10    mgr=new cPlayManager;
   12.11    if(!mgr) {
   12.12      esyslog("ERROR: creating playmanager failed");