
    M@ch              	       .   d dl Z d dlmZ d dlmZ d dlmZ d dlmZ d dl	m
Z
 d dlmZ d dlmZmZmZ d d	lmZ d d
lmZmZmZmZmZmZmZmZmZmZmZ dZdZ dZ!dZ"dZ#ddZ$d Z%d Z& G d de      Z'd Z(ded    z  ddddd e(       z   d e(       z   ddZ)y)     N)defaultdict)ID3_V2_4TagTemplate)LoaderPlugin)art)prompt)printMsgStyleFore)core)ALBUM_TYPE_IDSTXXX_ALBUM_TYPEEP_MAX_SIZE_HINTLP_TYPEEP_TYPE	COMP_TYPEVARIOUS_TYPE	DEMO_TYPE	LIVE_TYPESINGLE_TYPEVARIOUS_ARTISTSz#${artist} - ${track:num} - ${title}z#${track:num} - ${artist} - ${title}z${artist} - ${title}z&${best_date:prefer_release} - ${album}z(${best_date:prefer_recording} - ${album}c                     t        t        j                  t        j                  z   dz   t        j
                  z   d| z  z   |       y )NChecking %s)end)printr   BRIGHTr   GREEN	RESET_ALL)msgr   s     5/usr/lib/python3/dist-packages/eyed3/plugins/fixup.py_printCheckingr#      s1    	%,,
#j
05??
BUS[
PVYZ    c                     | rGg }| j                         D ]!  }|j                  |j                                # dj                  |      S | S )N )splitappend
capitalizejoin)sfixed_valueswords      r"   _fixCaser.      sH    GGI 	3D 12	3xx%%r$   c                 l    t        |       }d|v r|j                  d      d   }|j                  dd      S )NTr   -.)strr'   replace)dr+   s     r"   dirDater6   &   s4    AA
axGGCLO99S#r$   c                        e Zd ZdgZdZd e       z  Z fdZdedfdZ	d Z
d	 Zd
 Zd Z fdZ fdZd Zd Z xZS )FixupPluginfixupz@Performs various checks and fixes to directories of audio files.a;  
Operates on directories at a time, fixing each as a unit (album,
compilation, live set, etc.). All of these should have common dates,
for example but other characteristics may vary. The ``--type`` should be used
whenever possible, ``lp`` is the default.

The following test and fixes always apply:

    1.  Every file will be given an ID3 tag if one is missing.
    2.  Set ID3 v2.4.
    3.  Set a consistent album name for all files in the directory.
    4.  Set a consistent artist name for all files, unless the type is
        ``various`` in which case the artist may vary (but must exist).
    5.  Ensure each file has a title.
    6.  Ensure each file has a track # and track total.
    7.  Ensure all files have a release and original release date, unless the
        type is ``live`` in which case the recording date is set.
    8.  All ID3 frames of the following types are removed: USER, PRIV
    9.  All ID3 files have TLEN (track length in ms) set (or updated).
    10. The album/dir type is set in the tag. Types of ``lp`` and ``various``
        do not have this field set since the latter is the default and the
        former can be determined during sync. In ID3 terms the value is in
        TXXX (description: ``%(TXXX_ALBUM_TYPE)s``).
    11. Files are renamed as follows:
        - Type ``various``: %(VARIOUS_FNAME_FORMAT)s
        - Type ``single``: %(SINGLE_FNAME_FORMAT)s
        - All other types: %(NORMAL_FNAME_FORMAT)s
        - A rename template can be supplied in --file-rename-pattern
    12. Directories are renamed as follows:
        - Type ``live``: %(LIVE_DNAME_FORMAT)s
        - All other types: %(NORMAL_DNAME_FORMAT)s
        - A rename template can be supplied in --dir-rename-pattern

Album types:

    - ``lp``: A traditinal "album" of songs from a single artist.
      No extra info is written to the tag since this is the default.
    - ``ep``: A short collection of songs from a single artist. The string 'ep'
      is written to the tag's ``%(TXXX_ALBUM_TYPE)s`` field.
    - ``various``: A collection of songs from different artists. The string
      'various' is written to the tag's ``%(TXXX_ALBUM_TYPE)s`` field.
    - ``live``: A collection of live recordings from a single artist. The string
      'live' is written to the tag's ``%(TXXX_ALBUM_TYPE)s`` field.
    - ``compilation``: A collection of songs from various recordings by a single
      artist. The string 'compilation' is written to the tag's
      ``%(TXXX_ALBUM_TYPE)s`` field. Compilation dates, unlike other types, may
      differ.
    - ``demo``: A demo recording by a single artist. The string 'demo' is
      written to the tag's ``%(TXXX_ALBUM_TYPE)s`` field.
    - ``single``: A track that should no be associated with an album (even if
      it has album metadata). The string 'single' is written to the tag's
      ``%(TXXX_ALBUM_TYPE)s`` field.

c                 H   t         t        |   |dd       | j                  }d| _        |j                  dt        dd t        d          |j                  ddd	t        d   
       |j                  ddddt        d   
       |j                  dddt        d   
       |j                  ddt        d          |j                  ddt        d          |j                  ddt        d          |j                  ddt        d          d | _        t               | _
        y )NT)cache_filestrack_imagesF--typedir_type)choicesdestdefaulthelp
--fix-case
store_truefix_case)actionr@   rB   z-n	--dry-rundry_run--no-prompt	no_prompt--dotted-dates)rF   rB   --file-rename-patternfile_rename_pattern)r@   rB   --dir-rename-patterndir_rename_pattern--no-dir-rename)superr8   __init__	arg_group_handled_oneadd_argumentr   	ARGS_HELP_curr_dir_typeset_dir_files_to_remove)self
arg_parserg	__class__s      r"   rR   zFixupPlugin.__init__g   s@   k4)*$7; 	* 	=NN!	xj#)H*= 	 	?	|Lz%l3 	 	5	t[I%k2 	 	4	}\%m4 	 	6	'%&67 	 	9	.5J%&=> 	 	@	-4H%&<= 	 	?	(%&78 	 	:"$'E!r$   NTc                 r   t        |      }d |v r|j                  d        t        |      dk7  rst        dt        |      dk(  rdndd|d|sdn*d	d
j	                  |D cg c]  }t        |       c}      z         t        d|j                         z  |||      }|S |j                         }|S c c}w )N   z	Detected r   0multipler&   z namesr2   z:
	%sz
	zEnter %s)rA   type_required)	rX   removelenr
   r*   r3   r	   titlepop)rZ   keyvaluesrA   Typerc   vvalues           r"   _getOnezFixupPlugin._getOne   s    V6>MM$v;!Fq(j8"$v{{F3KqCF3K'LLN :		3W!%:E
  JJLE 4Ls   B4c                     |D cg c]  }|j                   s|j                    }}t        |D cg c]  }|j                  s|j                   c}      }t        |D cg c]  }|j                  r|j                   c}      }t        |D cg c]  }|j                  s|j                   c}      }d\  }}	}
d	 fd	}d|D cg c]  }|j                   j
                  t        k(  ! c}vs j                  t        k(  rW |d||z  |z        }
|
h}|j                  |       |j                  |       |r |d||z        }	|	h}||z  r |d||z        }nd|D cg c]  }|j                   j
                  t        k(  ! c}vs j                  t        k(  r*t        |      dk7  r |d||z        }nt        |      d   }nxt        |      dk7  r |d||z  |z        }	|	h}nt        |      d   }	t        |      dk7  r |d||z        }|h}nt        |      d   }|j                  ||z        r	 |d|      }
||	|
fS c c}w c c}w c c}w c c}w c c}w c c}w )
N)NNNc                     t        |xs g       dk7  r<j                  | ||rt        |      nd t        j                  j
                        }|S |j                         }|S )Nr_   )rA   rj   )re   rm   r3   r   Dateparserg   )type_str	dates_setdefault_datereducedrZ   s       r"   
reduceDatez)FixupPlugin._getDates.<locals>.reduceDate   s\    9?#q(,,xDPs</@FJ,0IIOO ' = N $--/Nr$   Fzrecording datezoriginal release datezrelease dater_   r   N)tagrX   release_dateoriginal_release_daterecording_date
album_typer   rW   difference_updater   re   list
difference)rZ   audio_filesftagst	rel_dates
orel_dates	rec_datesry   rz   r{   rv   as   `            r"   	_getDateszFixupPlugin._getDates   sw   *4!aee44HAHI	4 6a44 11 6 7
4La1;K;K))LM	>N;+^	 MA!%%**i7MM##y0'(8(1J(>(JLN'(I ((3''	2(23J3=	3I)K%/0J:%).*3j*@ B%02 ! EE,,	9 2 2!!Y. 9~").)j:PQ#Iq1:!#(23J3=	3II3U)W%34
(,Z(8(;%9~").)j:PQ)N	#Iq1##J$:;!+,<i!H2NBBC 5H6L N&2s3   IIII!II"I$I$Ic                 0   | j                   t        k7  sJ |D cg c]  }|j                  s|j                   }}t        |D cg c]  }|j                  s|j                   c}      }d }t        |      dkD  r| j                  d|d      }n|r|j                         }t        t        |D cg c]  }|j                  s|j                   c}            }t        |      dkD  rl|sB| j                   t        k7  r/t        dd      rt        | _         na| j                  d|d      g}nK|t        k(  rB| j                   t        k7  r/t        | _         n#t        |      d	k(  r| j                  dg d      g}t        |      dk(  r@|r>|d	   }||k7  r4t        d
       ||fD ]  }t        d|z          t        d||g      }|g}| j                  j                  r#t!        |      }|D 	cg c]  }	t!        |	       }}	||fS c c}w c c}w c c}w c c}	w )Nr_   zalbum artistF)rc   zAMultiple artist names exist, process directory as various artistsTrA   artistr   zMWhen there is only one artist it should match the album artist. Choices are: z	%sz%Select common artist and album artist)r?   )rW   r   rx   rX   album_artistre   rm   rg   r~   r   r   r	   r   r   argsrE   r.   )
rZ   r   r   r   r   artistsr   r   r+   r   s
             r"   _resolveArtistInfozFixupPlugin._resolveArtistInfo   s   ""k121*4!aee44tF!q~~q~~FG w<!<<%<PL";;=Lsd?ahhAHH?@Aw<!  D$7$7<$G ,59;*6D'#||Hg|MNG/1''<7&2#\Q||Hb4|@AG w<1QZFv% 4 5 ,/ &A&1*%&%&M/5|.D F'.99#L1L,34qx{4G4W$$U 5F @> 5s(   HHH	H	1HH,Hc                 p   |D cg c]  }|j                   s|j                    }}t        |D cg c]  }|j                  s|j                   c}      }t        |      dk(  r|j	                         n| j                  d|      }|sJ | j                  j                  s|S t        |      S c c}w c c}w )Nr_   album)	rx   rX   r   re   rg   rm   r   rE   r.   )rZ   r   r   r   r   albums
album_names          r"   	_getAlbumzFixupPlugin._getAlbum	  s    *4!aee44t7!qwwagg78&)&kQ&6fjjl(,Wf(E 	z!%!3!3zM*9MM 57s   B.B.B3B3c                    d}t        d       | j                  D ]Z  }t        j                  |      }|t        j                  k(  s,t
        j                  j                  |      }t        d|        d}\ |s|D cg c]  }|j                  s|j                   c}D ]  }|r |S |j                  D ]  }	|	j                  |	j                  k(  s|	j                  d      }
t        d|
z         t        t
        j                  j                  ||
      d      5 }|j                  |	j                          |j#                          d}d d d          |S c c}w # 1 sw Y   xY w)NFzfor cover art...	Tcoverz'	Found front cover in tag, writing '%s'wb)r#   _dir_imagesr   matchArtFileFRONT_COVERospathbasenamer   rx   imagespicture_typemakeFileNameopenr*   write
image_dataclose)rZ   	directoryr   valid_coverdimgart_type	dimg_nameafrx   img	file_nameimg_files               r"   _checkCoverArtzFixupPlugin._checkCoverArt  sK    	)*$$ 	#D''-H3??*GG,,T2	9+&'"	#  *5?2? /  :: /C''3??:$'$4$4W$=	H9TU!"'',,y)"DdK /x$NN3>>:$NN,*.K/ /	/	/  @/ /s   =EE.EE$c                     dd l }|j                  rdnd |j                  j                  _        t
        t        |   ||       y )Nr   exit)eyed3.utils.promptrJ   utilsr	   DISABLE_PROMPTrQ   r8   start)rZ   r   configeyed3r]   s       r"   r   zFixupPlugin.start1  s1    !6:nnF$)k4&tV4r$   c                     t        t        | 
  |g|i | | j                  s+|| j                  vr| j
                  j                  |       y y y rw   )rQ   r8   
handleFile
audio_filer   rY   add)rZ   r   r   kwargsr]   s       r"   r   zFixupPlugin.handleFile7  sK    k4+A???1D,<,<#<%%))!, $=r$   c           
      ,   | j                   sy t        j                  j                  |      }t	        dt
        j                  z   t        j                  z   dt
        j                  d|z          d }d| _
        | j                   D ]  }|j                  |j                          ! t        t        | j                         |      }g | _         t               }| j                   j"                  | _        | j$                  Pt        |D cg c]  }|j                  j&                   c}      }t)        |      dk(  r|j+                         | _        | j$                  pt)        |      t,        k  r^d|D cg c]  }|j                  j&                  t.        k(  ! c}v r%t1        d	t)        |      z  d
      rrt.        | _        nft.        | _        nZ| j$                  t.        t2        fv rBt)        |      t,        kD  r0t1        dt)        |      | j$                  fz  d
      rt4        | _        t7        d       }	d }
t               }d }| j$                  t8        k7  r| j;                  |      \  }
}t	        t        j<                  dz   t
        j                  z   |
xs dz          t	        t        j<                  dz   t)        |      dkD  rdndz   dz   t
        j                  z   dj?                  |      z          | jA                  |      }t	        t        j<                  dz   t
        j                  z   |z          | jC                  |      \  }}}d|fd|fd|ffD ]7  \  }}t	        t        j<                   d| dt
        j                   d|        9 t)        |      }t        |D cg c]  }|j                  jD                  d    c}      }t        tG        d|dz               |k7  }g }| j$                  }t        ||      D ]E  }t	        t
        j                  t        jH                  z   dz   t        jJ                  z   t
        j                  z   dt        j                  jM                  |j                        z  z   t
        j                  z          |j                  s,t	        d       |j                          |jO                  |       |j                  }|jP                  tR        k7  r't	        d       tR        |_(        |jO                  |       |t8        k7  r5|
|jT                  k7  r&t	        d|
z         |
|_*        |jO                  |       |jV                  s3|tX        t8        fv r%t1        d|	d   
      |_+        |jV                  |	d<   nWt)        |      dk(  rI|jV                  |d   k7  r7|t8        k7  sJ t	        d |d   z         |d   |_+        |jO                  |       |jZ                  |k7  r/|t8        k7  r&t	        d!|z         ||_-        |jO                  |       |j\                  }|j\                  st1        d"      |_.        |j\                  j_                         |_.        | j                   j`                  rtc        |j\                        |_.        ||j\                  k7  r)t	        d#|j\                  z         |jO                  |       |t8        k7  r |jD                  \  }}d}|k7  rd}|}sd|cxk  r|k  sn d }|te        t1        d$td        %            }d|cxk  r|k  s:n t	        t        jf                  d&z   t        jJ                  z   d'||fz  z          d }nS|v r<t	        t        jf                  d(z   t        jJ                  z   ti        |      z          d }nd}|jk                  |       ||rc||f|_"        t	        d)ti        |jD                        z         |jO                  |       n'|jD                  d*k7  rd*|_"        |jO                  |       |t8        k7  rrB|jl                  |k7  r3t	        d+d,d-ti        |      d.       ||_6        |jO                  |       rB|jn                  |k7  r3t	        d+d/d-ti        |      d.       ||_7        |jO                  |       rB|jp                  |k7  r3t	        d+d0d-ti        |      d.       ||_8        |jO                  |       t        |js                  d1d2g            D ]{  }t	        d3|jt                  d4|jt                  d5k(  r|jv                  n|jx                         |jz                  |jt                     j}                  |       |jO                  |       } |j                  d6      }|c|j                  j                  d7z  }t        |      }||k7  r:t	        d8|z         |j                  d6ti        |             |jO                  |       |j&                  } | |k7  st	        d+t        d9|       ||_        |jO                  |       H 	 | j                  ||      st1        d:d
      s		 g | _F        y g | _F        g }!| j                   j                  r| j                   j                  }"n+|t8        k(  rt        }"n|tX        t        fv rt        }"nt        }"|D ]  }t        j                  j                  t        j                  jM                  |j                              \  }#}$t        |"      j                  |j                  d;      }%|#|%k7  sxt        d<|%|$       |!jk                  ||%|$f        d }&| j                   j                  s|t8        k7  r| j                   j                  r| j                   j                  }'n|t        k(  rt        }'nt        }'t        |'| j                   j                  =      }(|(j                  |d   j                  d;      })t        j                  jM                  |      |)k7  rOt        j                  j?                  t        j                  j                  |      |)      }*t        d>|*z         ||*f}&g }+| j                  rM| j                  D ]>  }t	        d?t        j                  jM                  |      z          |+jk                  |       @ t               | _W        | j                   j                  sgd},|s|!s|&s|+rt1        d@d
      },|,rL|D ]X  }t	        dAt        j                  jM                  |j                        z         |j                  j                  tR        dB       Z |!D ])  \  }}%}$t        dC|%|$       |j                  |%dD       + |+rG|+D ]B  }t        dEt        j                  jM                  |      z         t        j|                  |       D |&rut        dF|&d   z         t        j                  |&d         }-t        j                  |&d   |&d          t        j                  |&d   |-j                  |-j                  f       y y y t        dG       y c c}w c c}w c c}w # g | _F        w xY w)HN
zScanning directoryr&   c                     | j                   S rw   )r   )r   s    r"   _pathz*FixupPlugin.handleDirectory.<locals>._pathD  s    77Nr$   T)rh   r_   Fz/Only %d audio files, process directory as an EPr   z?%d audio files is large for type %s, process directory as an LPc                       y rw    r   r$   r"   <lambda>z-FixupPlugin.handleDirectory.<locals>.<lambda>l  s    r$   zAlbum artist:  Artistr+   z: , zAlbum: ReleaseOriginal	Recordingz date: r   r   r   z	Adding new tagz	Converting to ID3 v2.4z	Setting album artist: %szArtist namer   z	Setting artist: %sz	Setting album: %szTrack titlez	Setting title: %szTrack #)rb   zOut of range: z1 <= %d <= %dzDuplicate value: z	Setting track numbers: %s)NNz		Setting 	recordingz date ()releasezoriginal releaseUSERPRIVz
	Removing z	 frames: s   PRIVTLENi  z	Setting TLEN (%d)z = z Proceed without valid cover file)zeropadzRename file to )dotted_dateszRename directory to %szRemove file: z
Save changesz	Saving %s)versionpreserve_file_timezRenaming file to )r   zRemoving file %szRenaming directory to %sz+
No changes made (run without -n/--dry-run))^_file_cacher   r   abspathr   r   r   r   YELLOWr    rT   rx   initTagsortedr~   rX   r   r>   rW   r|   re   rg   r   r   r	   r   r   r   r   r   BLUEr*   r   r   	track_numranger   RESETr   r   r   r   r   r   r   r   rf   striprE   r.   intREDr3   r(   r{   ry   rz   	frameiteridowner_idtext	frame_setrd   getTextFrameinfo	time_secsfloatsetTextFramer   r   r   rM   SINGLE_FNAME_FORMATr   VARIOUS_FNAME_FORMATNORMAL_FNAME_FORMATsplitextr   
substituter
   no_dir_renamerO   r   LIVE_DNAME_FORMATNORMAL_DNAME_FORMATr   dirnamerY   rH   saverenamestatutimest_atime).rZ   r   _r   r   r   edited_filesr   typeslastr   r   r   rel_date	orel_daterec_datewhatr5   num_audio_files
track_numsfix_track_numsnew_track_numsr>   rx   
orig_titletnumttotupdateframetlenreal_tlen_mstlen_ms	curr_typefile_renames
format_str	orig_nameorig_extnew_name
dir_rename
dir_formattemplatepref_dirnew_dirfile_removes	confirmedr+   s.                                                 r"   handleDirectoryzFixupPlugin.handleDirectory<  sp   GGOOI.	dU\\!DKK/+0??IFG 	H	 ! !! 	Auu}			 T$"2"23?u"ii00&;?a))?@E5zQ&+iik# '$'77kJ))W4JJKk*+"&( +2D'&-#!!gy%99K #33 +.1+.>.2.A.A.CC #$ '.#<(%+-$($;$;K$H!L'$))..@%2' ($))h&W1A#rJ)+/99W+=> ? NN;/E$))i'%//9EAB,0NN;,G)Hi&1'3((35 Ia 1TF'%//1B!A3GHI
 "+.O+FQaeeooa0FGJ q/A*=!>?:MNN&&/ x	$A%,,+j84::E,,"'"''*:*:166*B"BD//" # 55()		  #%%C{{h&01&  #;&<3;K;K+K2\AB#/   #::(|[.I"I#M4>J
!$XW"szzWQZ'?;./.,wqz9:$QZ
  #yyE!h+&=+e34!	  #J99"=1			)CIyy!!$SYY/	SYY&+cii78  #;& ]]
d?*!F*D!!t*F*FD,"6)3#?@ !T <_ <!$((-="=

"J"1T?4K"K#L M#'D!^3!$((-@"@4::"M$'I#. /#'D%)F*11$7 , %)4LCM7#cmm:LLM $$Q' ==L0$0CM $$Q';& 2 2h >(#h-9 :)1C& $$Q' 0 0H <iXOP'/C$ $$Q'!:!:i!G6H69)nF G09C- $$Q'cmmVV,<=> $+088w+>EJJNP Q ehh'..u5  #$ ##F+D vv//$6+l*/,>?$$VS->? $$Q' IH$_hGH!)  #qx	$t	"&&y+>@$O!DrD 99((66J;&0
lI661
0
 	=A"$''"2"22773C3CAFF3K"LIx":.99!%%9NHH$(HEF##Q($;<	= 
yy&&8{+Byy++!YY99
y(!2J!4J":04		0F0FHH  **;q>+=+=t*LHww	*h6'',,rwwy'A8L1G;<'1
 $$.. 'o(8(8(;;<##A&' %(E!yy  I
l"#3TB	% JA+(8(8(@@AEEJJxDJIJ .: @)Ax(KLHHX$H?@  ) % !3bgg6F6Fq6I!IJ		!% 7*Q-GH
1.AIIjmZ];HHZ]QZZ,DE  , CDE @ KN GH  "Ds   
y;4$z ! zz
 
	zc                 4    | j                   st        d       y y )NzNothing to do)rT   r
   )rZ   s    r"   
handleDonezFixupPlugin.handleDoneX  s      _% !r$   )__name__
__module____qualname__NAMESSUMMARYglobalsDESCRIPTIONrR   r3   rm   r   r   r   r   r   r   r  r  __classcell__)r]   s   @r"   r8   r8   -   sj    IEPG5j ik5Kn*2 ,0c,BCH-%^N@5-
ZEx&r$   r8   c                      ddl m}  t         | d      j                  d d      j	                               }|j                          dj                  |D cg c]  }d|z  	 c}      S c c}w )Nr   r   r   Fr   z$%s)eyed3.id3.tagr   r~   _makeMappingkeyssortr*   )r   r'  rk   s      r"   _getTemplateKeysr)  ]  sS    )B,,T59>>@ADIIK99.Aeai.//.s   A(zHow to treat each directory. The default is '%s', although you may be prompted for an alternate choice if the files look like another type.z:Fix casing on each string field by capitalizing each word.zIOnly print the operations that would take place, but do not execute them.zExit if prompted.z>Separate date with '.' instead of '-' when naming directories.zcRename file (the extension is not affected) based on data in the tag using substitution variables: zHRename directory based on data in the tag using substitution variables: zDo not rename the directory.)r=   rC   rG   rI   rK   rL   rN   rP   )r   )*r   collectionsr   	eyed3.id3r   r%  r   eyed3.pluginsr   eyed3.utilsr   r   r	   eyed3.utils.consoler
   r   r   r   r   
eyed3.corer   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r#   r.   r6   r8   r)  rV   r   r$   r"   <module>r0     s    	 #  % &  % 5 5 A A A A < < , > > [m&, m&`09;I!;LM**)"/1A1C"D!A 0 2!3 :#	r$   