knowthelist-2.3.0/0000775000175000017500000000000012423536022013070 5ustar mariomarioknowthelist-2.3.0/dist/0000775000175000017500000000000012423536022014033 5ustar mariomarioknowthelist-2.3.0/dist/knowthelist.desktop0000664000175000017500000000071512423536022020004 0ustar mariomario[Desktop Entry] Name=Knowthelist Name[de]=Knowthelist Name[fr]=Knowthelist GenericName=Party Music Player GenericName[de]=Party Musik Player GenericName[fr]=Lecteur de musique pour les soirées Comment=Party Music Player Comment[de]=Party Musik Player Comment[fr]=Lecteur de musique pour les soirées Exec=knowthelist Icon=knowthelist Terminal=false Type=Application StartupNotify=false Keywords=music;party;player;dj;mix;playlist; Categories=AudioVideo;Player;knowthelist-2.3.0/dist/build_msi.cmd0000664000175000017500000000076412423536022016476 0ustar mariomario"%WIX%\bin\candle.exe" -v -dLang=en -out ..\..\knowthelist.wixobj -arch x86 -ext "%WIX%\bin\WixDifxAppExtension.dll" -ext "%WIX%\bin\WixUtilExtension.dll" -ext "%WIX%\bin\WixUIExtension.dll" knowthelist.wxs "%WIX%\bin\Light.exe" -v -cultures:en-us -ext "%WIX%\bin\WixDifxAppExtension.dll" -ext "%WIX%\bin\WixUtilExtension.dll" -ext "%WIX%\bin\WixUIExtension.dll" -out ..\..\Knowthelist-Setup.msi -pdbout ..\..\knowthelist.wixpdb -sice:ICE09 ..\..\knowthelist.wixobj "%WIX%\bin\difxapp_x86.wixlib" knowthelist-2.3.0/dist/dialog.bmp0000664000175000017500000160576612423536022016017 0ustar mariomarioBM 6(8  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((())))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff[[[RRRPPPQQQWWWaaafffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffPPP000 999XXXfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffgggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggSSS"""$$$NNNggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg666%%%XXXggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhiiiUUV<<>>  :NGGG^^^YYYZZZ[[[]]]___aaaccceeegggiiijjjkkklllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm``a==>==>899  ?BXXX[[[XXXYYYZZZ[[[]]]___aaadddfffhhhjjjlllmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmRRR==>AAB.//   8I+++___XXXXXXXXXYYYZZZ[[[]]]___aaadddgggiiikkklllmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnlllFFF??@CCD&&'  <@  mmmIII^^^XXXXXXYYYYYYZZZ[[[\\\^^^```cccfffhhhkkklllnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnndddAAAAAACCC""" {JJK$$$]]]YYYXXXXXXXXXXXXYYYZZZ[[[\\\^^^aaaeeehhhjjjlllmmmnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooonnnnnnmmmmmmmmmmmmlllmmmmmmmmmmmmnnnnnnnnnooooooooooooooooooooooooooooooooooooooo[[[BBCCCDBBC!!!   [p###ssuwxxuuu볳CDD___YYYYYYYYYYYYYYYZZZZZZ[[[\\\^^^aaadddgggjjjlllnnnoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooonnnmmmmmmllllllkkkjjjiiiiiiiiiiiiiiiiiijjjjjjkkkkkkllllllmmmmmmnnnnnnooooooooooooooooooooooooSSSDDDEEEAAA###!!!######"""&' DSCCC~~eeexxx ^^^ZZZYYYYYYYYYYYYYYYZZZZZZZZZ[[[]]]```cccgggjjjlllnnnooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooopppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppooonnnllllllllllllkkkiiigggeeeeeeeeedddddddddeeeeeeeeefffggghhhiiijjjkkklllmmmnnnoooooopppppppppppppppNNNEEEGHH@@A%%%%%%''''''%%% @D7BVWWffg}}}JIIJLM___ZZZZZZZZZZZZZZZZZZZZZZZZ[[[[[[]]]```cccgggjjjmmmoooppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpppooooooqqqqqqllleeeaaa```cccgggiiieeeaaa````````````aaaaaabbbcccccceeefffgggiiijjjlllmmmnnnooopppqqqqqqmmmLLKHHGJJJBBA)))+++++++++((("""SZ4>ddemmn핕mll(/1bbbZZZZZZZZZZZZZZZZZZZZZ[[[[[[[[[\\\^^^```ccchhhlllnnnpppqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqiiiNNN111 333NNNaaaccc]]]]]]]]]]]]^^^^^^^^^___```aaabbbccceeefffhhhjjjlllmmmoooqqqiiiJJKIIIKKKCCC---000///...+++%%%Zd:Elllwwwvvv:87 Y^^]]]ZZZZZZZZZZZZZZZZZZZZZ[[[[[[[[[\\\^^^```dddhhhllloooqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq```AAA)))FFFaaa___[[[[[[\\\\\\\\\]]]]]]]]]^^^___```aaaccceeegggiiikkkqqqgggLLLKKKLLLEEE222333333222...'''[d KWjjj|||푒ROMAX[aaaZZZZZZZZZZZZZZZZZZZZZZZZZZZ[[[[[[\\\^^^aaaeeeiiimmmpppqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrYYY''' TTTbbb[[[[[[\\\\\\\\\]]]]]]]]]]]]^^^___```aaaccceeegggqqqdddMNNLMMMNNHHH666777777555111*** U^ dt[[[{{{d``#$%QWbbb[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[\\\\\\]]]___ccchhhlllppprrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrriii--- DDDddd\\\[[[[[[\\\\\\\\\\\\\\\]]]]]]]]]^^^___aaabbblllaaaOOPNNOOOPKKK;;;;;;;;;999444,,,""" EM>>>xww%%%MW[_`]]][[[[[[[[[[[[[[[[[[[[[[[[[[[[[[\\\\\\^^^aaaeeejjjnnnqqqrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrsssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssZZZ<<>>222'''>E7=AAB̶?>> pTSSbbb^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^___aaaeeejjjooosssuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu... %%%+++///000,,,"""???fff^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^___```]]]Z[[YZZZ[[VWWQQQQQQNNNIIIBBB777+++!!!111111LHHddd^^^^^^^^^_________^^^^^^^^^^^^______```dddiiimmmqqqtttuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvUUU '''///888@@@EEEHHHFFF===(((^^^bbb^^^^^^^^^^^^^^^^^^^^^^^^^^^___ddd^^^]]^[[\[\\ZZZTTTTTTRRRNNNFFF<<33rrrjjjjjjjjjjjjiiifffcccaaa``````___``````aaabbbeeehhhllloooqqqtttvvvwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwttt !!!444===/// PPPkkkLLL BBBggg___________________________bbb```bbbbbbaaaaaa```]]]]]]ZZZTTTLLL@@@333)))%%%#############",.NRZZZ<<< 18<53wwwpppppppppooommmiiieeebbbaaa```______``````aaabbbdddgggjjjmmmqqqtttwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxTTT (((111444jjjIII !!!fffaaa````````````````````````aaafffccceffccccccbccaaa```^^^YYYRRRGGG:::///'''$$$$$$$$$$$$$%%%[jGJ+++???cccGGG eq=;:xxxvvvvvvuuutttqqqlllgggdddaaa```````````````aaaaaabbbdddgggkkkppptttwwwxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,,,  (() ///eee<<< UUUeee```````````````````````````hhhbbbggheeeeeeeeedddcccbbb^^^WWWNNNAAA555,,,(((%%%&&&&&&&&&&$#&_bBCDppqjjljjj``a?Dw ?@@xxxxxxxxxwwwuuuqqqmmmgggcccaaaaaa```````````````aaaaaaccceeeiiinnnssswwwxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyykkk $$% !!!;;;\\\))) >>>jjjaaaaaaaaaaaaaaaaaaaaaaaaaaaeeeaaahiighhfggfggfggffffffbbb]]]TTTHHH;;;000+++''''''''''''''(( &.0#78nhjffgiijkklhhippqmcc-SW>HCDDyyyyyyyyyxxxuuuqqqlllgggdddbbbaaaaaaaaaaaaaaaaaabbbbbbdddfffjjjooossswwwyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyOOO %%%!! !!!!!!!!!!!!!!!!!!!!!###QQQGGG '''gggbbbaaaaaaaaaaaaaaaaaaaaaaaabbbggggggkklhiihiihiiiiiiiigggccc[[[PPPCCC777///***(((((((((((((())%@HMk]]kklyyzxxyxxyxwy}yy.HHHyyyyyyxxxvvvsssooojjjfffcccbbbaaaaaaaaaaaaaaaaaabbbccceeegggkkkooossswwwyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz555%%%$$$$$$##$##$##$##$##$##$##$$$$%%& $$$XXX*** ___dddbbbbbbbbbbbbbbbbbbbbbbbbbbbjjjeeemmnjkkjkkjkkkkkkkkjjjgggaaaXXXKKK>>>444...***)))))))))))))***&FP\rziba~~}c9BSSSzzzzzzwwwtttppplllhhhdddccccccbbbbbbbbbbbbbbbbbbcccdddgggjjjmmmpppssswwwyyyzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{vvv)))&&%&&&&&&&&&&&&&&&&&&&&&&&&&&&((' HHH@@@RRRiiibbbbbbbbbbbbbbbbbbbbbbbbbbbeeeeeelmmmnnlllllllllmnnnnnlllggg```TTTGGG;;;333...+++**********++*+++'BJ bknmii!^q ___{{{xxxuuuqqqmmmiiifffdddccccccbbbbbbbbbbbbbbbcccdddfffiiimmmoooqqqtttwwwzzz{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{fff !!!###$$$###!!"***(((((((((((((((((((((((((((((()))&&& ***MMMDDDkkkbbbbbbbbbbbbbbbbbbcccbbbccccccllljjjpqqmnnmnnmnnoooqqqooolllfff]]]QQQCCC888222...,,,++++++++++,,+,,-!*24"djmoll&!  !!!jjj{{{uuuqqqmmmiiigggdddccccccbbbbbbbbbbbbbbbccccccdddgggkkkoooqqqrrrtttvvvyyy{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||TTT &&&&&&''''''&&&!!!(((,,,**+**+**+**+**+**+**+**+**+**++++,,,  III+++777kkkddddddddddddddddddddddddeeeeeeiiihhhppppppoopoopooprrrrrrqqqmmmfff[[[NNNBBB888222...,,,,,,,,,,,,,--,---&$.# 'Tc!fnqjgf!"##!!!***sssyyyqqqmmmjjjgggfffddddddccccccccccccccccccddddddfffiiimmmrrrsssttttttvvvyyy{{{|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||FFF'''+++,,,---,,,)))###---...---------------------------------//0===555,,,kkkfffeeeeeeeeeeeeeeeffffffggghhhhhhsssoootttqqqqqrqqrrrruuuuuurrrmmmdddXXXKKK@@@777222///----------------...,,/#+))0OZinpgggvvw!""######==={{{qqqmmmjjjgggeeedddddddddccccccccccccccccccdddeeegggjjjooosssuuuuuutttvvvyyy{{{|||||||||||||||||||||||||||||||||}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}999---000000111///,,,$$$111000000000000000000000000000000000000222$$$000:::'''kkkjjjhhhhhhiiiiiiiiijjjjjjkkkmmmnnnssssssvvvsttsssrsssssvvvxxxvvvsssmmmcccVVVJJJ???888333000......///////////////,)(7/,lkknophhi͖aab***$$$%%%QQQyyyllliiigggfffeeedddddddddddddddddddddddddddeeefffiiimmmrrrwwwwwwvvvuuuvvvyyy|||}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}///444555555555333///$$$556334334334334334334334334334334334334556)))''';;;%%%mmmooonnnnnnnnnnnnoooooopppqqqssstttuuu}}}xxywwwtttttttttuuuzzzzzzxxxtttmmmcccVVVJJJ@@@999444111000000000000000000---778mmnppqnnoihjrrrgghkkl...%%%'''bbbppphhhgggeeeeeedddddddddddddddddddddddddddeeeeeegggkkkpppuuuxxxxxxvvvuuuuuuxxx{{{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}zzz'''999999999999666111&&&999666666666666666666666666666666666666888---###999###oootttssstttttttttuuuuuuvvvwwwxxxyyyzzz}}}}}}{{{vvvvwwvvvuvvxyy}}}}}}yyyuuunnncccWWWKKKBBB:::555333222111111111111...889nnpqqrqprppqjjk``_bbbiijoop///'''888mmmhhhfffeeeddddddddddddddddddddddddddddddeeeeeegggiiinnnsssxxxzzzyyyvvvtttuuuxxx{{{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~xxx&&&""">>>>>>>>>===:::555((( <<<899899899899899899899899899899899899:;;/00!!!777"""qqqxxxxxxyyyzzzzzz{{{{{{{{{|||}}}}}}~~~~~~~~~{{{|||wwwwxxwxxwww{{{~~~{{{vvvoooeeeYYYNNNDDD===777555222222222222///;;;pqrsstrrsrrsrrsffglllhiippq111)))RRRpppffffffeeeeeeeeeeeeeeeeeeeeeffffffffffffggghhhjjjnnnrrrwww{{{|||zzzwwwuuuuuuyyy|||~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~uuu$$$%%%CCCBBBBBBAAA>>>777***!""@AA<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>344###444"""pppyyyyyy{{{|||}}}~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~yzzyxyyyyyyyyyy~~~}}}xxxqqqggg\\\QQQHHH@@@;;;777555333222///>>>stttuusttstttuucddvvwddeqrr222111fffhhheeeeeeeeeeeeeeeeeeffffffffffffgggggghhhhhhkkknnnrrrvvvzzz||||||yyyvvvtttuuuyyy|||~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~vvv%%%&&&IIIGGGFFFEEEAAA:::---"""CBB?>>?>>?>>?>>?>>?>>?>>?>>?>>?>>?>>?>>A@@555###000###nnnvvvxxx{{{~~~zz{zz{z{{z{{{{{{{{ssskkkaaaWWWNNNGGGAAA===999777333DDEvvwvvwuuvuuvvvwddeccdrrs333OOOoooffffffffffffffffffggggggggghhhhhhiiijjjkkklllooossswww{{{}}}~~~}}}zzzvvvtttwwwzzz}}}www&&&'''LLLLLLKKKHHHDDD===000"""DDEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACCC666$$$+++%%%kkkrrrtttxxx{{{}}}~~~|||{{{{{{{{{|||}}}wwwppphhh```XXXQQQLLLHHHDDD???QQQyyzwwxwwxwwxyyzghhcccnooBBBkkkgggffffffgggggggggggghhhhhhiiijjjjjjkkklllnnnqqqtttwww{{{}}}~~~~~~|||xxxuuuuuuwww{{{~~~yyy***&&&OOOPPPNNNLLLHHHAAA333!!!!!!GGGDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDGGG667!!!!!!!!!%%%'''(((kkknnnpppssswwwzzz|||~~~~~~~~~|}}|}}|}}}~~|||uuuooohhhbbb]]]YYYUUUPPP^^_z{{xxyxxyxxyzz{llmaaappr```mmmgggggghhhhhhhhhiiijjjkkkllllllmmmnnnoooqqqsssvvvyyy|||~~~~~~{{{wwwuuuvvvyyy}}}}}}... %%%QQQUUUSSSPPPLLLDDD777$$$HHHHHHGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGJJJ555!!!$$$$$$$$$&&&###---mmmlllmmmpppsssvvvxxxzzz|||}}}~~~~~~~~~~~~~~zzzuuupppkkkgggddd___iii||}zz{zz{zz{{||lmn```xxxllljjjjjjjjjkkkllllllmmmnnnooopppqqqqqqrrrtttvvvxxx{{{}}}}}}zzzxxxwwwyyy|||777!!! ###QQQ[[[WWWTTTPPPIII;;;''' EEELLMJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJLLL111$$$&&&&&&'''%%%""" 555pppjjjkkkllloooqqqsssvvvxxxzzz|||}}}}}}~~~~~~~~~~~~~~~}}}}}}|}}~~~~zzzvvvrrrnnniiirqr}}~{||{||{|||}}rrsccctttnnnmmmmmmmmmnnnooopppqqqrrrrrrssstttuuuvvvwwwzzz|||~~~~~~|||yyyxxxyyy{{{~~~CCC###"""!!!NNN```\\\YYYTTTMMMAAA,,,!!!===PPPLMMLMMLMMLMMLMMLMMLMMLMMLMMLMMMMMKKK+++'''(((((()))%%%"""!!!BBBuuukkkkkklllmmmnnnppprrrtttvvvwwwyyyzzz{{{{{{{{{zzzyyyyyywww{{{zzz}~~~~~zzzvvvqqqxxx~}}~}}~}}~~~xxyxxxgggppqvvvpppqqqrrrssstttttttttuuuuuuvvvwwwxxxzzz|||}}}~~~|||zzzyyyyyy{{{~~~OOO$$$$$$ HHHeee```]]]YYYRRRFFF222### ///TUUOOOOOOOOOOOOOOOOOOOOOOOOOOOOOORRREEE)))************%%%""""""TTTzzzooonnnnnnnnnpppqqqrrrtttuuuvvvwwwxxxyyyyyyyyyxxxwwwvvvtttsssuuuzzzwww{{{www|||{{{{{{hhhsss~~~vvvwwwwwwwwwwwwwwwxxxxxxxxxzzz{{{}}}~~~}}}|||{{{{{{}}}___%%%%%%!!!>>>iiidddbbb]]]VVVKKK999'''"""RRRSSSRRRRRRRRRRRRRRRRRRRRRRRRQQQTTT;;;***---,,,---***$$$###"""!!!iii}}}tttsssrrrrrrssstttuuuvvvwwwxxxxxxyyyyyyyyyyyyxxxwwwvvvuuutttrrrsss{{{vvv~~~yyyuuunnnuuvzzzzzzzzzzzzzzz{{{{{{{{{}}}~~~~~~~~~}}}~~~qqq)))'''###444jjjiiifffbbb\\\QQQAAA,,,%%%"""AAAYZZSTTTTTTTTTTTTTTTTTTTTTTTUVVQQQ000---......///'''$$$$$$"""---|||yyyxxxvvvuuuvvvvvvwwwxxxxxxyyyzzzzzz{{{zzzzzzzzzyyyyyyxxxwwwwwwvvvuuu{{{}}}{{{ssstttuuu{{{{{{{{{{{{||||||}}}~~~~~~~~~~~~~~~222((('''***dddpppkkkgggaaaXXXIII333&&&### $$$YYYXXXVVVVWWVWWVWWVWWVWWVVVZZZBBB---111000111---$$$%%%$$$###BBB}}}{{{zzzzzzzzzzzzzzzzzz{{{||||||}}}}}}}}}}}}}}}}}}}}}}}}|||||||||||||||}}}tttvvvsss|||}}}}}}~~~FFF))))))$$$VVVvvvooolllggg^^^QQQ===***&&&###???___XYYXXXXXXXXXXXXXXX\\\PPP111222222222333'''$$$%%%$$$###]]]~~~}}}|||{{{{{{{{{{{{{{{||||||}}}}}}}}}~~~~~~zzzwwwwwwwwwzzztuuyyyooo~~~~~~___******%%%BBByyytttrrrnnneeeYYYHHH222(((%%%!!!NNN`aa[\\YZZYZZZ[[]^^WWW788111444444666,,,###%%%%%%$$$(((zzz~~~}}}}}}|||||||||||||||}}}}}}}}}~~~~~~~~~~llltttmmmsssxxx...+++***)))ooo|||wwwssslllaaaRRR>>>,,,'''$$$!!!LLL^^^_``_``^__STT:::333555666888000###$$$&&&&&&&&&DDD~~~}}}}}}||||||{{{{{{{{{{{{{{{{{{{{{||||||}}}~~~~~~~nnooopmmnppqttu|}}EEE---'''RRR{{{yyysssjjj\\\KKK666***((($$$ ???PPPNOODDD555444777888999///!!!###&&&&&&&&&&&&jjj~~~~~~}}}||||||{{{zzzzzzzzz{{{{{{|||}}}~~~~~~~~~}}}}}}|||||}}}~~~~~}}~~~hhh..."""---~~~zzzrrrgggXXXEEE111***((($$$!!!+++444888:::;;;999444((("""&&&(((((((((888~~~}}}}}}|||{{{{{{||||||}}}~~~~~~~~~}}}}}}}}}999!!! ___{{{rrreeeTTT@@@///+++)))%%%"""(((---,,,$$$$$$'''))))))))))))cccZZZ!!!"""///{{{qqqcccQQQ>>>///,,,***'''###!!!!!!%%%(((******++++++;;;hhh))* ###UUU}}}qqqcccRRR???111---+++)))%%%$$$"""!!!!!!"""###%%%(((***+++,,,---,,,---nnneefCCC ###""""""zzz~~~tttfffWWWGGG888000---+++***)))(((((((((***+++---...////////////SSSȝ]]^UUU444!!!&&&555xxxlll```SSSGGG<<<666222000/////////000000111222222222111@@@Ϸ\\]VVWRRR+++$$$'''KKK~~~uuulllbbbZZZRRRLLLFFFBBB@@@???===<<<:::666444333999yyy~uuuyyy]]^WWW[[[MMM&&&&&&'''[[[}}}vvvpppjjjeeeaaa[[[XXXUUUPPPKKKEEE>>>999999qqq~~}^^^ZZZZZZ^^_JJJ&&%'''((( bbb~~~yyytttpppkkkfff```ZZZSSSLLLEEEDDDrrr{{{__`]]^]]^]]^bbbKKL)))'''((((((\\\}}}xxxsssllleee^^^WWWQQQUUU}}}~{{{aba````````````eeeSTT...%%%222000GGG|||vvvpppiiibbb[[[jjj}}}ccccccccccccccccccggg^^_===223888222333XXXzzzsssmmmrrrffgffgffgffgffgffgffgiijjjkiiiOOO999777111555KKKeeeuuu|||{{{zzz}}}}}}|||ijjijjijjijjijjijjijjijjjjj|||dddTTTIIIBBB???CCCOOO___vvv{{{lmmlmmlmmlmmlmmlmmlmmlmmlmm|||~~~}}}ppppppppppppppppppppppppppp|||yyyrtsrtsrtsrtsrtsrtsrtsrtsrts|||tttvvvvvvvvvvvvvvvvvvvvvvvvvvv|||xxxvvvyyzyyzyyzyyzyyzyyzyyzyyzyyzyyyooo~~~||}||}||}||}||}||}||}||}||}}}}iiitttqqqnnn|||eee|||vvv}}}cccqqqpppnnnÉ|||mmmǙpppɣ{{{zzzlllfffǭ{{{DDDƭyyyNNNabblllϭ{{{eeeeeeMMMijjɣzzziii]]]ZZZNNNغ}}}{{{kkkXXXqqqXXX ~~~www{{{WWWsssaaaddd۷|||~~~^^^pppuuuWWWݾ}}}vvvooohhhddd]]]ٻ|||fffwww```zzzʰuuurrr]]]˴rrrrrriii;zzzlll|||ɼwww}}}iii|||}}}kkkzzz|||sss~~~~~~wwwzzz~~~´ÙǾ¤ǽӿknowthelist-2.3.0/dist/knowthelist.png0000664000175000017500000003533212423536022017122 0ustar mariomarioPNG  IHDR>a:IDATx]|+!$$zM:қ ('D"M)TQP@Z轇${f/~rN}j_zIK%ӿxdrwOttW>$]pb ,gF/ 8Y!..Nrrr [2755UL899\]]FnDDϗ#^N(RH"Cnݺŋo nX[2,2V KIIy 1ߞ|~xNT)<~)x<5ľjժ]sthظqOڵ)( >O>-i*'O܍o AA RΝ;%CBBj!hj5[pЦҥKXBtgnnnP"dWEivGHǐ&ND/3ǀB(Wq9۷,tҥ2njfdOnGtB -*޸qAȴccc 1p¤ %]| Ő1eQb"~ 5B n?m4o޼>Ç}:}&><<<}TL[nmK#(E]O-,'@邃ܾ}Fm|B9A mhѢܶ~p8C`ƽAI@+5i 2(J di;իW?ݻ̹vy<0ɓtBu{VY}ibrsӧ{v"WX12oŠ\C7!CC髋K.]zy78@b^<<ѣ!o_~%y+"6xy/ AQOÏ;wD)4gŋ (A*ThĠAS AmSڵkExV R 3ӧϭ\>;g7j#G ;r w}xo`}UV3fZav:t1G4"(\QFWB .e:>1{lJD$D[O0$k7ptlzƠ󡡡1ݝ,[|C GYn'\masfn޼yRݺun JVAܚw'sr]vzE,v OF?рSwšDcFӓ䔘ի]zc#bBt7ng5/_ ͨM6t}ʔ\C_Y =H`'c5`ΝUA7C7svv:d26`y0T Gy{^*UcmaÆ?B=df͛7'Zlo̚5k9ݻOް'^hvK֭{g߾}{/;NTuqqo2UwҺdfȑ0=FP\`~n\.`K{~~~~WѷCBBbTETpq_Q=vD;مuZd?55.cqۇJ- KHHLCfBN>=rɒ%;2J*upQϽѣG/A/'z>mLMMqΝ.G8 :Y2yܸ0/v'羱3@{ի/I&M+XDfhrg}6r6lYڵ-Ȝ8cw޽{b dɒ=zǾ}Zׯ_{(oQJ K^D`0Ea 4˖)z3r/^$::wN:5CPlll9sj"2{)[tС3'N޼y.)8P+22޽{h0C&dG6? [h: WT$}rұ30=~B,|UٲegԩSءCʕk ߻woM6C]D7nXvϓIyITϞ=aLA?zP߿ǏDZ ;HRm??%5k@o__^juڪzM&qpm &˳(S6ϧk?m鴓W̛`zٲeb ꫯlF;okjΡ٫t($I甲@^/2*U$/_-11IU>>޽;txflx"+pwңߠ[eD=Bŕ33 8x43I"$7NcMƳj$ DqtQW7!q嗣3gΌE:2;Fp9iHeB$F9$jhk"WwD,-\ŋg;vv34{0:u_X{)K4jԨ8QbQFUB_jhh+VTgݺ5Sj=cؽ(u12W5wyIǫLW<]]]L.\2`&?>}zzO?tObbbC%ДzB^*/^T!55<>,OhѻO4xA鏃+c+Gnu" '_A :|gϞ ?P B3p ,,?BvŜ9_Dy04v®c?FC^ wSjsk 46n85k0$nݺj gjo0D,7n܇nDN~A鸽עB7,;8qb3tI_^ CpG_I/ 雲;%`89o^)Vz~,"Hnnnpe`4fa(]ޖ-[~ptەS& I!&M^F[wTƳ\ETrd8PCCˈaN&%%E]MG9ӳ})S6;J{R:鞛t1$&$KH0LGs܎6F0ԩSϞ=B5T #NvwЩ%S>[ *:>}zb޼y'˹xq'4/*0~Xz/gэx^;P 5h(…  p.iȏ>b\\\Њ+:"O( [@ӷ5k+;vl'`Tn%_ɓ'bbb.~W봱c~ xaFU0f̘6fw^k9g?݈۶}un%ƍ9/^i-~a P~1]ѐR)켾`L&M6jWdE?iSN#<}Yw=00Qxx˗/stۘT0r7QT3f8ܠA:EjaGUi6֤J j4A㷠< mݺ]m5'QhHNIAmpݺuN:svrt,ϩ尡C[!l.B)Pl1ѣE=*M2XKROET#j\N%''\p 7F7o"QbŞ㩭 J@Mpl̙'O< >Rؿn*`4R1%%&j%[G/_zg)Yuhh a aai!&:XdBFEE7o^?GH})~M;)ܼu#%*oٲ%hX%D 1]ǏY3YZfLOTL gR-%|VG?Aڂ>}OMI=^l>-zu hR۶m+.YUJfO}ԩS{9YsHV#l[" ]t%$&vر}{˗/?-5@>^/ K҄ b>1;R;YSC ѱ7m >'a^)Ξ={d̟܋M @g044 R<ݍ|.^qѣG_EgN= 6L$2~A /(}z?)h4B95 rIY/Z]MutlBk.;""#;޾}[|f\ݡD,d*bbb${G{\{IYђ%t@33q{)<XZ$s%K.ib# Hs-|СC5rV *ULBFOw(P@~r y }b$_+13|@,Ch.:L:P9qP[{aڐj>eڴi ɢ?@LwwɴD- <8HXm3HsC}[ERK~֓?0bD OAO\z57iﴊ4EFMr,mϝ{RTdfSѨ0@P.81(TMډ$Q#''бJ泩 Gc02O6|#^I-i2Q4P{J7P|F^rQ'O~H (ݻw7KP4S@Zjdsm^T7nj׮IS1/%/S J6)GNN uƍ=ٴEdNx`ዢioSmqݺuQ^Y|(Ғ בiӧWd39!I+{əḟ$$쿜ı|: -+s5P1 o޼n6ת0^MՋڒ:_tZ>m gWyjGl\,DGE[4l?aPEDyL7\2Cŋ[R\~xpKT|u_SRRR{Ҟ%Nף{0d ܺ*</2]lA|Ӧ.wqq,:|, h*#ibw{ZC"U%`=VZPT)ٞGO_dUZU:Dt}.{Oc{*mIβLk)b1bD)|ܨdwwۅ z 5(*-uCRf-x"ٳ @lK V*U%X(*aÆ\>?5Is6nB eȏlYӈkoAT'y P2|+?q4~瘟K~#6:>IZʜ^j421F$4-4Ugj&H @ŊkoTb9m8 ߔ#f?+Ej&&iiK&8w'͹oAQNCf^Vv "VM:thBZo Oa2OLreS&(D|W!((BCBzqF"gWn"Ԣje ǝ4!IB?5Q+~["Pɧ34MC 4;g`ݫ5ܖ6_XC,ZQ_`+Ԗm@/tʕg^Aތ`Y Y\rX d>笟4VPByi#S)^{+kς`:);?I3A8| .2z?/3ռ4+y#MQ1摒jv#jլ 8@vٲeXɆJ-+P# V]lYz}jWjժI\T R EyHheZ>2Ghߥ{ff})`ATQzuv„sċj4:KChpuve((i2\MC@t2<@=, /D߈A+C^icVSG ̟#-7C4D拝%JU0nܧ^)Zz^tbGG=U.X4K^MQٳgw u AvTpAILrF(+Ur)d`P*T~ ht?+tÍJQt؁6iٲ%ßҤXgə[.j@.aKXbŋIۊ > (VLrϞ= ^^ [~񽐐ZBq%(DS  &d&+L(BMJ a 5GyO@2e =NR4 f$lnǟ' WmҴiSwvTzt?ze%o y5]+2*CܹsG2GuܹsTL`ʳJ0(D-&_,:M Ŋ+f @eNRBj`L;(U9HH+3h:N@$m)SSRǂU/%/qY+Ҿ *z 1yd >La0YGW~V@` *g`"Xҭ/9nKTѡNNh b)"PQQ{+4ş#Z/M>3GbSQ1"ڒ _ OcիkϤ1k׮ޕ+:tݻR1(|PnX@dy6:XSHr"Exヒ(̠Vȸ)N yzKy ZTJbbvti-~.5*:Hү_b؎r4@g\JY8oZ[X4-tM{quq4\WɃh! mm QAD;pG< `̌bH5p9v3`P  @ZɍG)jA?~3NbP99U΢fQ?ꁖ"9$#xZlRH x7o最2W)I 2hK&D EV V9sE ZǢx19@v4z']i$\qt Uh{A$&njyN^KlK>sVVxCf/T F%? Q,#^4iXb6OA AbN 1i0J9#9&2\Ǝ9}EJb:* ,KIj̃'c٪UxRm#iO/4()%zghָ.8R9u$N:',3!eHĊ#YCۜ Z IC%8!d}Q/q7B{2JJ DILR_*Hz fuӧwA>Cs4gȅ)DbOlaO|F45+8b2KCV--S"[?< :Tf]z2gH 3 1jo_ܭɞrES8$eҐy9}{̀ 0}(W9! BIreEKtZQwǎw=||1eU8Ix 4Ъf jE !!EM4U?=< ,~oa1#kv*oIL͖Pkb'#HgpgP3ϵR2RQ.]"RZrĒ*^z}_pfR,df$hFuJ6uA3H/X~%PNMd]xczbt<Ç3mCBf4X]mEJߤY\,Jh"Hr)#.۬@9pi֬K.qوi4lsϞ=~/ije<cGiFt7I &V ҌP98W@?4~!`>x[~o}Zx28na%+fB|Z$!EqvcfSc)&pILU4l鸬| xKOSaBP;=AQ~mڵkשl2s Vo<(Uҏܡqayh;BAb%V7/A?Cipm]"d$tv%X3WKg:J4Ӳ43\yhA8~& @M/J uIh,]oJ8wk x(8zCjఏgE'hxȇLGӗᤛ UM;Ѡ Kzj'pw›w@"`i25^WL⮁$1C;mS &޳&H ` K0]0ybkTHy=J\bMBΜ9h-fZ+lѢwnHp?yODV h|Z+_!tt}4|8Ԫ%?b: $q>3=|Z7r -bZ:Z-IiW)M3P2(JU;ٮmfxjxrH9B?IEŤHz*\rEF>ɨPa(3j߾}E)b=V})^O"Q/ "2_ 8X.YZjժCŊzkny3>NZX `ⷨ܌KxKr= TGv&B'۷fx[$ Q Sha:8Y!O̧ a4h"8GrG k &{KZ,c&2m@Radt|R|t {ZQ)r͛7-njsF䇓3$%GES'2]v#fv9P dUƄ sи@-&if:q\r ^QGu8]Fk֬)!$'%Ṡ`>Ga&;pVLj1 vc&E!M[ؾ3SZImpQn8*ue2Cji.X 8CfGP@R6Ծ#\.栍uhXW#{4tLN$|R|iCt}*5iܸa׈$S`.0RS4J0s*DƠ%u&U|3dモ-Ұ^t|~q:lgX AXQ\Q2 }B(8-n3[LsBfQ]=)@''0Iٴ'211ҽ0P'hs h99e x{Ȟى,hBM"$ }ǒ;wdE*UB~,Ӗ`ڔ/y@HYcl! R󫖄g pA@oM:$м~$Hc̢90{ꥆ&tyۛ|IdPR؇0qpDŚ`]bб,4߀$;vL2i(&_8M J+fk 3>2|КmH0޳㭀 uz~8$ Fb;w^is yXcL}E*;z Aȯ2sIEHbfömۤY\`ؔxtr4_r*2*g;|@l,Di%{Des q( D+kTc:LTVZmku !_0B Ufc"ugςmF_Au-9_KO\$G]>}ȑ0u'pK:93j{`NCb5{< h״,{Rļ=|0LU['PK}wh5͜+b kԬ#kHY@^ Gi\nTo#Lb(Y hSжg$pvҥ(^0j&๓yi0ˊ|n29h/{$"*ɲ DW:5l\' 1//Wvze˖H2qr8bs?mc -PQ W'>PZR,4*W"H$K@ܺu+L<Zֹ?uQnג2\=%x@*9Hue mn4u:IeӠAEVҽ5VD껟1BQ!jt&h= _UװÆ {2E*jOq.U=<6j)xbţ?[#;w)?P)fz ӈ$BF:fMaw;M`22RK>E?|=ZC%/ZP"C,T N d2k·+FU@qk3m vcD*[ ;L]eEd'5)WsE&+`]ʪI֯@R4I11K xV ROCޞ:X= W6m cF^CX 5krwB\ҿsa 1T1ybTKXNhm~=8ABf\gLYf>5<7ST@ ZA <9q0gzn߾ݻw_rhl>P@͛턊%qlRޫg͒9g*ad m)Z Q6Q9:y`,yvڵg9 FSY:DpPh}h7 ~EÖ=I >|8JȴiFa-J?'~a~0{7+e}D%C'?y@$7Q`^0nWkq#;iom[Tdڃ4yq,kT @X2C+OBQQqȑ#r` GORߥKBI [lG­]Sd?vKF @FCFk:dn{M7IۗJ3ΣyQA LqD$jFt度su?@w3j]4p4CZ%K=zHo,4,|5غe#$'FlMWjAey@b=hFV 9*ū-7otuyg ILQߢv|;v!C ˻u իU5kJ+iOM UN>5zk{')'CiDq7ZG@y]qjVJR.੶N&jۦ^ 1EJ5$%Hnգ:EYsC?PZj56+V;C^p0,\OJtqZ =C4fT^jj 3*豋ӑݻ`Lt_79AݚH= ύ?ĩޓ0ӱ#@UH}٠ɓ'7?d&Z`t>vqϚO/x1 {2|& "gzJqS%ƚ`NH=DF-Q66[P!ieFK(GYA~ܺuS4}f<3^EH)uԩ@Lt%X3\&.4o}[![k'MjMFr߾}f"RTF DJG̟xe}X̂? -[MOKC^yð"WWm:u"L7oJ5y%J$')0S'B-ca OjzI9~b>-2]dm45jS+?@U9iJ~r7=|/3޷o=d\0}lyxK/ 5nx`xT˗85;LygYS`P'yi zCR82~?2b~Vj˽*3yN/5kV6555 wܵ d;`. (}Cmk=i`ӦS :Q\bNuȉ;Ṵ!/2]sz)@ԸQW]bs)yT*Cb1xlTkpI̿bO1VmvME6]~]N%Qf`P&H3@t@sGmr0NGT^zvy`ZBR5񷞴*Qk'%̿yV׷uJ>ʼnq^J߽[Ō}/_j鲱M&!9}K .?Rt0䖨s G)' %&tb-EvtrnG?Fz{^!V?grE<wq^G? N{(yC^<冂y  KN% IENDB`knowthelist-2.3.0/dist/package.sh0000775000175000017500000000206312423536022015766 0ustar mariomario#!/bin/bash dist="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" version=$(grep "APP_VERSION.*$" ${dist}/../src/src.pro| sed 's/^.*APP_VERSION.*\([0-9]\.[0-9]\.[0-9]\).*$/\1/') target=${dist}"/../../knowthelist-"${version} rm -rf ${target} && mkdir ${target} cp -R ${dist}/../../knowthelist/* ${target} rm ${target}/knowthelist.pro.user rm ${target}/src/Makefile rm ${target}/Makefile cd ${target} tar -czf ../knowthelist_${version}.orig.tar.gz ../knowthelist-${version}/ dpkg-buildpackage -k${GPGKEY} # Suse / Fedora spec sed -i 's/Version: 1/Version: '${version}'/g' ${target}/dist/knowthelist.spec mv ${target}/dist/knowthelist.spec ${dist}/../../knowthelist_${version}.spec #process=$(objdump -p "$1" |grep NEEDED | cut -d ' ' -f 18) results(){ for package in $process do dpkg -S $package | cut -d: -f1 | sort -u done }knowthelist-2.3.0/dist/banner.bmp0000664000175000017500000024760612423536022016017 0ustar mariomarioBMO6(:PO䞞\\\+++888lll===A@@{z{vww }QVppp@B #&uuuHHH   "! 669   x~CSiii"""111xyx0/0 %0:::!!!kkkhhh///%%%'''+0"tuu@AAȂ<<<"""888ttt^__555//0///29%DKI444]^_<==888666$$$ ,1.6cmmex|kkkjjj^^`FEFBBB???***"LVEGFݩ:_fllleefLLLJJJEEE333 ~z{HU!!!222BBB+++vvvQQQSSSOOO>>>Xe&(|}}`^]&(Ma444444HHH<<qrtm`_:fq>>;;;;<;;;;=>>455)))iijvvvoooXXXBBB888---233onqonouuwRSTbbb GGGNNN>>> =<=EDD@@@AAA@@@DDD999 !!!``azyywwweeeVVVEEEJJJvuwtvuyxyxxxLLLZZZIII%%% 888NNOHHGHHHHHHKKK<<<%%%%%%(((nooxxyyyyjjjkjkyyzwwwMMMcccSSS,,,)))WWXMMMNNNMMMRRR:::''')))999캻z{{hii}~~xxxwww}}~zzzFFFooo```;;;!!!]^^UUURRRVWWTUU222,,,***uuu︸sssrrr{{{"""111vvvoooOOO)))+++lll\]]___BBB000000'''~wwxooo hhheee===""" 333Z\\CCC333555$$$򈈊nmoggh ===~~~```222$$$&&&'''$$$Ʉ000uuu}}}[[[333((("""!!!)))GGGABB---mmmPPPAAA:::888888 111ƎLLMDDDEEE~~~sssfffVVV===FFFԛNMNbbbMMM ,,,qqqjjjeeeڠRSSfgg^_`HHH???SSS䧨\]]lon]^]ᡢcccstscccަmkllmm{}}nnožono򈈈sttwxx귷}}}}~ͱ拌Ѹ»џrssˬWWX㹹ՅhhhߪnnnڔʿΟƒɥًܐܰ鵵ܾ}}}ȵ떖ڟҶͽknowthelist-2.3.0/dist/License.rtf0000664000175000017500000002066612423536022016144 0ustar mariomario{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Calibri Light;}} {\*\generator Msftedit 5.41.21.2510;}\viewkind4\uc1\pard\lang1031\f0\fs22 \b GNU LESSER GENERAL PUBLIC LICENSE\b0\par Version 3, 29 June 2007\par \par Copyright (C) 2007 Free Software Foundation, Inc. \par Everyone is permitted to copy and distribute verbatim copies\par of this license document, but changing it is not allowed.\par \par \par This version of the GNU Lesser General Public License incorporates\par the terms and conditions of version 3 of the GNU General Public\par License, supplemented by the additional permissions listed below.\par \par 0. Additional Definitions.\par \par As used herein, "this License" refers to version 3 of the GNU Lesser\par General Public License, and the "GNU GPL" refers to version 3 of the GNU\par General Public License.\par \par "The Library" refers to a covered work governed by this License,\par other than an Application or a Combined Work as defined below.\par \par An "Application" is any work that makes use of an interface provided\par by the Library, but which is not otherwise based on the Library.\par Defining a subclass of a class defined by the Library is deemed a mode\par of using an interface provided by the Library.\par \par A "Combined Work" is a work produced by combining or linking an\par Application with the Library. The particular version of the Library\par with which the Combined Work was made is also called the "Linked\par Version".\par \par The "Minimal Corresponding Source" for a Combined Work means the\par Corresponding Source for the Combined Work, excluding any source code\par for portions of the Combined Work that, considered in isolation, are\par based on the Application, and not on the Linked Version.\par \par The "Corresponding Application Code" for a Combined Work means the\par object code and/or source code for the Application, including any data\par and utility programs needed for reproducing the Combined Work from the\par Application, but excluding the System Libraries of the Combined Work.\par \par 1. Exception to Section 3 of the GNU GPL.\par \par You may convey a covered work under sections 3 and 4 of this License\par without being bound by section 3 of the GNU GPL.\par \par 2. Conveying Modified Versions.\par \par If you modify a copy of the Library, and, in your modifications, a\par facility refers to a function or data to be supplied by an Application\par that uses the facility (other than as an argument passed when the\par facility is invoked), then you may convey a copy of the modified\par version:\par \par a) under this License, provided that you make a good faith effort to\par ensure that, in the event an Application does not supply the\par function or data, the facility still operates, and performs\par whatever part of its purpose remains meaningful, or\par \par b) under the GNU GPL, with none of the additional permissions of\par this License applicable to that copy.\par \par 3. Object Code Incorporating Material from Library Header Files.\par \par The object code form of an Application may incorporate material from\par a header file that is part of the Library. You may convey such object\par code under terms of your choice, provided that, if the incorporated\par material is not limited to numerical parameters, data structure\par layouts and accessors, or small macros, inline functions and templates\par (ten or fewer lines in length), you do both of the following:\par \par a) Give prominent notice with each copy of the object code that the\par Library is used in it and that the Library and its use are\par covered by this License.\par \par b) Accompany the object code with a copy of the GNU GPL and this license\par document.\par \par 4. Combined Works.\par \par You may convey a Combined Work under terms of your choice that,\par taken together, effectively do not restrict modification of the\par portions of the Library contained in the Combined Work and reverse\par engineering for debugging such modifications, if you also do each of\par the following:\par \par a) Give prominent notice with each copy of the Combined Work that\par the Library is used in it and that the Library and its use are\par covered by this License.\par \par b) Accompany the Combined Work with a copy of the GNU GPL and this license\par document.\par \par c) For a Combined Work that displays copyright notices during\par execution, include the copyright notice for the Library among\par these notices, as well as a reference directing the user to the\par copies of the GNU GPL and this license document.\par \par d) Do one of the following:\par \par 0) Convey the Minimal Corresponding Source under the terms of this\par License, and the Corresponding Application Code in a form\par suitable for, and under terms that permit, the user to\par recombine or relink the Application with a modified version of\par the Linked Version to produce a modified Combined Work, in the\par manner specified by section 6 of the GNU GPL for conveying\par Corresponding Source.\par \par 1) Use a suitable shared library mechanism for linking with the\par Library. A suitable mechanism is one that (a) uses at run time\par a copy of the Library already present on the user's computer\par system, and (b) will operate properly with a modified version\par of the Library that is interface-compatible with the Linked\par Version.\par \par e) Provide Installation Information, but only if you would otherwise\par be required to provide such information under section 6 of the\par GNU GPL, and only to the extent that such information is\par necessary to install and execute a modified version of the\par Combined Work produced by recombining or relinking the\par Application with a modified version of the Linked Version. (If\par you use option 4d0, the Installation Information must accompany\par the Minimal Corresponding Source and Corresponding Application\par Code. If you use option 4d1, you must provide the Installation\par Information in the manner specified by section 6 of the GNU GPL\par for conveying Corresponding Source.)\par \par 5. Combined Libraries.\par \par You may place library facilities that are a work based on the\par Library side by side in a single library together with other library\par facilities that are not Applications and are not covered by this\par License, and convey such a combined library under terms of your\par choice, if you do both of the following:\par \par a) Accompany the combined library with a copy of the same work based\par on the Library, uncombined with any other library facilities,\par conveyed under the terms of this License.\par \par b) Give prominent notice with the combined library that part of it\par is a work based on the Library, and explaining where to find the\par accompanying uncombined form of the same work.\par \par 6. Revised Versions of the GNU Lesser General Public License.\par \par The Free Software Foundation may publish revised and/or new versions\par of the GNU Lesser General Public License from time to time. Such new\par versions will be similar in spirit to the present version, but may\par differ in detail to address new problems or concerns.\par \par Each version is given a distinguishing version number. If the\par Library as you received it specifies that a certain numbered version\par of the GNU Lesser General Public License "or any later version"\par applies to it, you have the option of following the terms and\par conditions either of that published version or of any later version\par published by the Free Software Foundation. If the Library as you\par received it does not specify a version number of the GNU Lesser\par General Public License, you may choose any version of the GNU Lesser\par General Public License ever published by the Free Software Foundation.\par \par If the Library as you received it specifies that a proxy can decide\par whether future versions of the GNU Lesser General Public License shall\par apply, that proxy's public statement of acceptance of any version is\par permanent authorization for you to choose that version for the\par Library.\par \par } knowthelist-2.3.0/dist/knowthelist.spec0000664000175000017500000001276112423536022017271 0ustar mariomario# # Copyright (C) 2014 Mario Stephan # %define name knowthelist %define qmake qmake-qt4 %if 0%{?suse_version} %define qmake /usr/bin/qmake %endif %if 0%{?suse_version} >=1310 %define qmake /usr/%_lib/qt5/bin/qmake %endif %if 0%{?fedora_version} >= 20 %define qmake /usr/bin/qmake-qt5 %endif Summary: awesome party music player Name: %{name} License: LGPL-3.0+ URL: https://github.com/knowthelist/knowthelist Version: 2.3.0 Release: 1 Group: Multimedia Source: %{name}_%{version}.orig.tar.gz Packager: Mario Stephan Distribution: %{distr} BuildRoot: %{_tmppath}/%{name}-%{version}-build %if 0%{?suse_version} && 0%{?suse_version} <1310 BuildRequires: libqt4-devel >= 4.8 qwt6-devel BuildRequires: pkgconfig(gstreamer-0.10) BuildRequires: update-desktop-files BuildRequires: libtag-devel Requires: libqt4-qtbase Requires: gstreamer-10-plugins-base Requires: gstreamer-10-plugins-ugly Requires: gstreamer-10-plugins-good Requires: gstreamer-10-plugins-bad Requires: libgstreamer-10-0 Requires: gstreamer-10 %endif %if 0%{?suse_version} >=1310 BuildRequires: taglib-devel BuildRequires: pkgconfig(gstreamer-1.0) BuildRequires: libqt5-qtbase-devel BuildRequires: update-desktop-files Requires: gstreamer-plugins-bad Requires: gstreamer-plugins-base Requires: gstreamer-plugins-ugly Requires: gstreamer-plugins-good Requires: gstreamer Requires: libqt5-qtbase %endif %if 0%{?fedora_version} >= 20 BuildRequires: taglib-devel BuildRequires: pkgconfig(gstreamer-1.0) BuildRequires: qt5-qtbase-devel BuildRequires: qt-devel >= 5.0 Requires: qt5-qtbase Requires: gstreamer1-plugins-base Requires: gstreamer1-plugins-ugly Requires: gstreamer1-plugins-good Requires: gstreamer1-plugins-bad-free Requires: gstreamer1 %endif BuildRequires: glib2-devel BuildRequires: gcc-c++ BuildRequires: alsa-devel Requires: taglib Requires: alsa %prep %setup %build %{qmake} -makefile %{name}.pro %{qmake} make %install %{__install} -Dm 755 -s %{name} %{buildroot}%{_bindir}/%{name} %{__install} -Dm 644 dist/%{name}.desktop %{buildroot}%{_datadir}/applications/%{name}.desktop %{__install} -Dm 644 dist/%{name}.png %{buildroot}%{_datadir}/pixmaps/%{name}.png %if 0%{?suse_version} > 0 %suse_update_desktop_file -r %{name} AudioVideo Player %endif %clean [ "%{buildroot}" != "/" ] && %{__rm} -rf %{buildroot} %files %defattr(-,root,root,-) %{_bindir}/* %{_datadir}/applications/%{name}.desktop %{_datadir}/pixmaps/%{name}.png %description Easy to use for all party guests Quick search for tracks in collection Two players with separate playlists Mixer with fader, 3 channel EQ and gain Auto fader and auto gain Trackanalyser search for song start/end and gain setting Auto DJ function with multiple filters for random play Monitor player for pre listen tracks (via 2nd sound card e.g. USB) %changelog * Sun Sep 19 2014 Mario Stephan - 2.3.0 - Made all compatible with Qt5 and Gstreamer-1.0. - Add an ALL node to filter results in case of a manageable number of tracks are found - Changed ModeSelector style and moved to tree header - Included 'year' tag into quick search * Sun Sep 14 2014 Mario Stephan - 2.2.4 - Fixed a bug which prevent correct monitoring of changes - Improved quick search in collection: added search in genre, multiple strings - Changed alignment of some display controls - Allow more audio file formates - Added a mutex to get more thread safety for database access * Tue Aug 26 2014 Mario Stephan - 2.2.3 - Get rid of dependency to Boost - Bugfix where adding a song caused a segmentation fault - Switched to Homebrew package installer for MacOS - Set CUE button to untranslatable - Translation updates * Wed Aug 06 2014 Mario Stephan - 2.2.0 - Added a new left side tab "Lists" to manage lists, dynamic and stored lists - Added a new feature to handle track ratings - Added a combo box for AutoDJ artist and genre filters to be able to select also from a list - Added a new way in how to add and remove items of AutoDj and lists - Added "Open File Location" at playlist context menu - Added a playlist info label (count,time) to player - Added French translation (thanks to Geiger David and Adrien D.) - Changed to a better way to summarise count and length of tracks for AutoDJ - Optimized for smaller screens - Fix to be more flexible for empty tags - Enhanced algorithm to fill playlist and simplified handling of current and next item - Fixed some size issues and cosmetical issues - Stabilized to avoid crashed in some cases * Thu Jul 03 2014 Mario Stephan - 2.1.3 - Added new widget ModeSelector to select collection tree mode - Added a counter for played songs - New: Generate a default cover image if the tag provides none - Optimized: gain dial moves smoothly now to avoid hard skips of volume - Optimized function to decouple database requests from GUI activities - Optimized for size scaling of form * Tue Jun 10 2014 Mario Stephan - 2.1.2 - Added translation for hu_HU (thanks to László Farkas) - AutoDJ panel rearrangements, new record case stack display added - AutoDJ names settings in settings dialog added * Tue Jun 03 2014 Mario Stephan - 2.1.1 - Add localization, cs_CZ (thanks to Pavel Fric), de_DE * Thu May 29 2014 Mario Stephan - 2.1.0 - First Releaseknowthelist-2.3.0/dist/knowthelist.wxs0000664000175000017500000001313112423536022017150 0ustar mariomario ""]]> knowthelist-2.3.0/dist/headset.icns0000775000175000017500000012402012423536022016330 0ustar mariomarioicnsh8mk A}q--qڨi5 'ghg!K7bcLq,^jDQ_j`[DmG #>GJG<. k616 KV6,~eNC>942x ?!fsL0&""',-+ ,Jfr=*4tN,"(0*$('  R^(4)Xt]1"AXL50%% %!$:sh+(idE$0WVWC0*# \uruU &.cV4FPL-*# &q|N"3WJ)I-%" M{{pn|zC#1J@!BA+% `|}|lYKPxtR+?7;:&()Lxy}waG83=soV"4/3+itwt^A2//7nV '&*+/ 'opp`B/,+E|n!!$! 'TklcI0)([v&"  ; gfdS6'&HXq\x! +)$E+a^YB(#&S)   '=I:A\VN3!`Z3y GVLC(PhיTLOB8 9ILG80'n0 "J@.))no>;" U$>: Y9 1< P65 j4$1 5 #  ¥ û÷ĹwrwƮ imbo܀ѹ oX\ |`Yl ֨zoaPhٺrm[ZѭnÀzf|ǿq_ľs}`m{}||~zshsuttvr imllo^XWYevr ]dcaG;e{hQ| S]Y67}o`N>6 JU6,~eNC>942x >!fsL0&""',-+ ,Jfr<*4tN,"(0*$('  Q^(3)Xt]1"AXL50%% %!$9sh+(idE$0WVWC0*# \uruT &.cV4FPL-*# &p{N"3WJ)HI-%" M{{pm{yB#1J@!BA+% `|}|lYKOwsQ+?7;:&()Lxx}waG83=so~V"4/323+itwt^A2//7mV '&*+/ 'opp`B/,+>w{n!!$! 'TklcI0))Nu$!   ; ffdS6'&@Wp[b  +)$E+a_YB(#%|S)   '=I:A\VN3!TZ3g  GVLC(IhיHLNB8  9A LG80%Жn, "J@.)'|mo>;" U$>: Y9 1; K+5 f2#0 3 # ¥ û÷ĹſwrwƮ imboۀѹoX\ |_YlըzoaPhغrm[ZЭn€¿zf{ƾq_~ýr|`mz|}yshrtur ilkko]WWYevr ]ccaG;e{hQ| S]Y67}o`N>6 JU6,~eNC>942x >!fsL0&""',-+ ,Jfr<*4tN,"(0*$('  Q](3)Xt]1"AWL50%% %!$9sh+(idE$0WVVC0*# [trtT &.cV4FPL-*# &p{N"3WJ)HI-%" M{{pm{yB#1J@!BAB+% `|||lYKOwsQ+?7;:&()Lxx}waG83=rn~V"4/323+iswt^A2//9mV '&*+/ 'opp`B/,,)+zn!!$! 'SkkcI0))%!rX  ; fedS6'&$Sp[ +)$E+a^YB(#" S)  '=I:A[VN3!Z3 GVLC(hי LNB8 8KG80n  "J@.)mp>;" U$>: Y9 1; 5  #0 #il32a ¼~ʾlo|϶lZ־YrӔskf\ٹq ­dzf{{|onnpa_cyw`aCZlNU7YuXI=3 <5`1""&+) &Hk ,]h2," mzzn(,W5;KKC&! ?r{|] )F(9??="Z{rTAlza 6!/442$.txjC2/ad$"))#"FojD-,  , ffP,&nvH! -.7!_X7"\@Nq    0UH&0}I 8I9>5 A<," 71 5 40 ^  3 6   ¼~ʾlo|϶lZ־YrӔsk f\ׁq ­dzfzz{onnpa_cyw`aCZlNU7YuXI=3 <5`1""&+) &Gk ,]h2," mzzn(,W5;KKC&! ?rz{] )F(9??="Z{rTAlz` 6!/442$.txjC2/`c$"))#"FojD-,k  , ffP,&hv> ..7!_X7"P;N_    0UH&0}> 7I97/ A<,  71 5 4/ P  3 3   ¼~ʾlo|϶lZսYrҔske\عq dzfzz{ommoa^cyw`aCZlNT7YuXI=3 <5`1""&+) &Gk ,]h2;H3&$Ru  -(gJ ,UU>," mzzn(,W5;KKC&! ?~rz{] )F(9@@="Z{rTAkz` 6!/442$.txjC2/ac$"))#"FojD-+"c , efP,'Du; ..7!_X7"N   0UH&0}  7I9 A<, 71 5 4/   3    is32} hع hqƣw esugeuWMyd? 6`82+ '~4 +O(P57{{r !1$:(HwOOt % `KF%  %U'^2  ;U.#~'H' hع hqƣw esugeuWMyd? 6`82+ '}4 +O(P57{{r !1$:(HwOOs $ `K?!  %U'^*  ;yU.#p'H% hع hpƣw estgetWMyd? 6`82+ '}4 +O(P57{zq !1$:(HwOOs $ `K'8x  %U']  : U.# 'Hit32AO Ȼ Կ ж;ѳ԰о¤Ϳr㣚 ŴÙ ׽Ȁ rä׉  bǵ}} ߓòt} t߷s St}|a~V{~qspbj|mzf}flcX5ziXۀ܁҈לZztlNՄ_drOׁ8tlu0DpV%؀kvpqbf`> }~CjJEdIt6QxN^%eU3Yh` ZU3a[ |xJw~D[LVX߀̀΀ {c~mdJMN܀݀ހ 훠r{V;c`KjĀރބ߃㵣o~rCNbl ހ߀ـ؀y{SfDdž˶nnohf ɰa~{Dɦ?pfǙxn"ÉvpmUZk_9hb; yfeWai`} Bjg2|z~ rdnWxvzWsfvswxuprptYoxFompGAwT}glj{98301687_sigjkO48715Keu|{zz{woy~zfcg_<3823Xzsle_tGc`eT.%20G|vpib[TQeb_^bL)'((\}xsle^WQKFr`[ZZ_J%'( b~ytpkf`ZSLE@:x _YW[M&&'[}vpjea[XUPKE>965|+!`VWR+$'K~ulbZRLFB@?=<:64332~u9iTU4!&5xl`SG<620/0012112ϸVC #""z~tfWG80-+*)(*+-./ȣ"M* #U}qcR?1-+)%$"!!"#%(*+,-,-,z+!"/{qcQ>/,*'#!!%(**+6+! _{reT@/+)%"(-,$$') .."-~zrgXE1*($!+48:;94("&(''l --'R{ysj\K6*($ ?POD54789/!#&W}~~}+*)o|wslaR>,'$!L^``_T:35680#$&%opnqs\*$%BytrneYH2(%!Na\ZZ[^W81446,#%%$##ltmL)$Vvolg^Q=*&#?_YX\P123'$%$#!k\TSTZd{uy.('*dpkgaXI3&# $YXVW VZB-101-$%$# ^tvK'#4jifb\QA,%"AZT VQ0-../'$$" hst[%!>idb]VK9'"RSR QT;*-,-*$#"G}~yunf$ He`]YRF2# /UORE)*%""j {w|{{hi##"!N`\YTMA,!=PM K+'(()%"!{ ~zvqx~yxgj!! #Q[WTPI;' EMJ L1$&&'%" H|~zvrnir~|}scq %QUSPLD7$HHGJ5!$&#w~~~zupkgd_i}{|n`v&OPNLHA3!!GDG7!%'~}~|uohb]YUP_{y{maq'LLKHD=0"EA C6$+|{|}wph`XQLHD?Qzxzhco1&IGFEA:-"B> @5#0{{skaWNGA=973Ewwvvweds3%CBBA>7*"A< >4#4zy~}xqg\QH@;7532/>tuttudwer2'"> =:5( <9 ;0!7a|wxxw{~{voeYND=752/;rtsgliq1)9 61&96 8-#9zvwvvy}}yuncWKB:5321.9prrqk_bjp/'%45 3/$64 6)';rwt uzzxtmcVJ@9410-8nqojrhl.%&-001/,$10 2$0:2uts vxvsmcVJ?830../(,kpi͗b*$% '+,-,)#-.- 0=5etqr uurmdXK@72/-.,)Zpgw"##! &&''&!(,+ ,  I+ op rrqmf[NB82., --$ cqf#!   !#$#"*( )& *M [qn oqolf]QC82.,+ ,,4ml  )%& ' H@knl nnlg`TG;3.+* ++Jniq%$ & $X* KnkjgaXK>4.*) *Pza}B  % ! #QG aligc[PC7/*( )H]lzy %  !;\) 'hhgffb]TH;0+'(08jgjliqcWH  ) /e< Mhe dcb^WNA5,(%&#bDqljaD  (14jI \fca`^YRG:/'$ %jJ+?cGq   !4=/ PkL `baa`]]ZTL@3)%#.RZ<8  #*9JK8*2QkdE=a_\ZYVPG:.&"g,iV  #,4=IV`d^P9O`] XWVRKA4)" !0t r '/8@EHF=( U^\\ZTTRNF2'E= B̷>'WVMIJFB:/# { 4e3VTIFFC=5+ mǾW~9SRECB?:2'!/iŸ Zw ?RQRN@@?<7/$7"]]EPOPK;94," M>w%T! INMNH67751* ^t[{`$K KLKLE2332.'dWj|M@ IKIKC-0/.+%dElwv7NIGJA)+("Z> enl lHEHA%%''% DB Wg}I HDEA#!##"'S Cex HCDC! p #uxu볉 IAAC" K$ PA@D'  @ m B>B/  I ?>>9  B=<> N;;=* )<:9 @?9;"CK<97FdT' ;:*6:C::U Ȼ Կ ж;ѳ԰о¤Ϳr㣚 ŴÙ ׽Ȁ rä׉  bǵ}} ߓòt} t߷s St}|a~V{~qspbj|mzf}flcX5ziXۀ܁҈לZztlNՄ_drOׁ8tlu0DpV%؀kvpqbf`> }~CjJEdIt6QxN^%eU3Yh` ZU3a[ |xJw~D[LVX ̀΀ {c~mdJMN܀݀ހڀ훠r{V;c`Kjǁބރ߃㵣o~rDNbl ހہ؀y{SfDǀāÀ˶nnohf €ɱa~{Dɥ?pfǙxn"ÊvpmUZk_9hb; yfeWai`~| Bjg2{y} rdnWxvyWsfvtwxuprptYoxFompGAwT}glj{98301687_shfijO48715Keu|{zz{woy~zecg^<2823Xzsle_tGda`eT.%20G|vpib[TQeb^]bK)'((\}xsle^WQKFr`[ZZ^J&'( b~ytpkf`ZSLE@:x _XW[M&&'[}vpjea[XUPKE>965}+!_UVR+$'K~ulbZRLFB@?=<:64332u9iSU4!&5xl`SG<620/0012112ϸUC #""z~tfWG80-+*)(*+-./ȣ"L) #U}qcR?1-+)%$"!!"#%(*+,-,-, z+!"/{qcQ>/,*'#!!%(**+6+! _{reT@/+)%"(-,$$') .."-~zrgXE1*($!+48:;94("&(''~k --'R{ysj\K6*($ ?POD54789/!#&W|}~~}~|+*)o|wslaR>,'$!L^``_T:35680#$&%nompr\*$%BytrneYH2(%!Na\ZZ[^W81446,#%%$##ltmK)$Vvolg^Q=*&#?_YX\P123'$%$#!k\TSTZd{uy.('*dpkgaXI3&# $YXVW VZB-101-$%$# ^tvK'#4jifb\QA,%"AZT VQ0-../'$$" hstZ%!>idb]VK9'"RSR QT;*-,-*$#"E}~yune$ He`]YRF2# /UORE)*%""j {w|{{hi##"!N`\YTMA,!=PM K+'(()%"!{ ~zvqx~}~xxgi!! #Q[WTPI;' ELJ L1$&&'%" H|~zvrniq}|}rcp %QUSPLD7$HHGJ5!$&#w~zupkgd_i|z|m`v&OPNLHA3!!GDG6!%'~}~|uohb]YUP^{xzlao'LLKHD=0"DA C6$+|{|}wph`XQLHD?Qywyhco1&IGFEA:-"B> @5#0zz{{skaWNGA=973Dvvuuvdcr3%CBBA>7*"A< >4#4zxy~}xqg\QH@;7532/>tuttudvdr2'"> =:5( <9 ;0!7a|wxxw{~{voeYND=752/;qsrflip1)9 61&96 8-#9zvwvvy}}yuncWKB:5321.8nqppj`bio/'%45 3/$53 5)';qwt uzzxtmcVJ@9410-7mpnhrgk.%&-001/,$10 2$0:2uts vxvsmcVJ?830../)/koh͖a*$% '+,-,)#-.- /=5etq ruurmdXK@72/-.,#)Ongv"##! &&''&!(,* +,  I+ opo rrqmf[NB82., --&#Tng#!   !#$#!*( )& *M [qn oqolf]QC82.,+ ,,!2jl! )& ( H@knl nnlg`TG;3.+* ++Bki^%$$# $% $X* KmkjgaXK>4.*)*Frb~9  %! #QG akigc[PC7/*(@]kyxxwy $  !;\) 'hhgffb]TH;0+' .7hfikhpcS>  ( /e< Mge dcb^WNA5,(%&$_Cpjj`?w (14jI \fca`^YRG:/'$ %[·G+?cGeС   !4=/ PkL `baa`]]ZTL@3)%#,NZ< 1  #*9JK8*2QkdE2'>ÿ7 A̷>p&WVMIJFB:/#kݨ 4Wx3VTIFFC=5+ bǾKn 9TRRQECB?:2' )iŸ"Nh >QPQN@@?<7/$2ծ$PREONOK;94," E؆>w%I INMNH67751* Ud[{`#B KLKLE2332.'[Kj|O9 HJIKC-0/.+%Z:lwv8MJHJB)+("S4 dml mHEH@%%''% @7 Wf}I GDEA#!##"&D C~ex GBCB! [ #sxu볉 IAAC"{ J$ QA?C&  <١  m B=A/   8 >==9   ?ႋ<;> :;:<* <98 ;?9;#?G;86C_P% ::)6:B99R Ȼ Կ ж;ѳ԰о¤Ϳr㣚 ŴÙ ׽Ȁ rä׉  bǵ}} ߓòt} t߷s St}|a~V{~qspbj|mzf}flcX5ziXڄӈלZztlNԄ_drOց8tlu0DpV%׀kvpqbf`> }~CjJEdI t6Qx N^%eU 4Yh`ZU3a[ ߀ހ }xJw~D[LVX ́΀ {c~mdJMN܃݀ 웠r{V;c`KiÀށ߄ބⴣo~rDNal ހ فܿy{SfDąʶnnohf Ȱa~{DȤ?pfřxn"‰vpmUZk_9hb; yfeWai`~| Bjg2{y} rdnWxvyWsfurvxuprpsXoxFoloGAwT}gkij{98301687_shfijO48715Keu|{zz{woy~zecg^<2823Xzsle_uGc`eS.%20G|vpib[TQeb^]bK)'((\}xsle^WQKF~r_[ZZ^J&'( b~ytpkf`ZSLE@:x ^XW[M&&'[}vpjea[XUPKE>965}+!_UVR+$'K~ulbZRLFB@?=<:64332u9iSU4!&5xl`SG<620/0012112ηUC #""z~tfWG80-+*)(*+-./ǣ"L) #U}qcR?1-+)%$"!!"#%(*+,-,-,y+!"/{qcQ>/,*'#!!%(**+6+! _{reT@/+)%"(-,$$') .."-~zrgXE1*($!+48:;94("&(''~k --'R{ysj\K6*($ ?PND54789/!#&V|}~~}~|+*)o|wslaR>,'$!L^__^S:35680#$&%~nompr[*$%BytrneYH2(%!N`[YYZ]W71446,#%%$##~ltmK)$Vvolg^Q=*&#?_X\P123'$%$#!k\TSTZczty.('*dpkgaXI3&# $YXV ZB-101-$%$# ]~tvK'#4jifb\QA,%"AYST UQ0-../'$$" h~stZ%!>idb]VK9'"RSR QT;*-,-*$#"F}~yune$ He`]YRF2# /TORE)*%""i {w|{{hi##"!N`\YTMA,!=PL MK+'(()%"!z~zvqx}~xxgi!! #Q[WTPI;' ELJ L1$&&'%" G{~~zvrnir}{|rcp %QUSPLD7$HHGJ5!$&#x~zupkgd_i|z{l`v&OPNLHA3!!GDG6!%'~|}|uohb]YUP^zxzlao'LLKHD=0"DA C6$+|{|}wph`XQLHD?Qywygcn1&IGFEA:-"C? A5#0z{{skaWNGA=973Dvvuuvdcr3%CBBA>7*!@< >3#4y~}xqg\QH@;7532/>stsstcvdq2'"> =:5( <8 :/!7a|w {~{voeYND=752/;psrflhp1)9 61&96 8-#9zvux}}yuncWKB:5321.8nqqpj`bio/'%45 3/$53 5)';qwt uzzxtmcVJ@9410-7mpnirgk.%&-001/,$10 2$0:2ussrsvxvsmcVJ?830../,7lnh̖a*$% '+,-,)#-.- /=5etq ruurmdXK@72/-./+0igv!##! &&''&!(,* +,  I+ opo rrqmf[NB82.,-.'!fj!"!   !#$#!*( )& *M [pm oqolf]QC82.,+ -*"do& )& ( H@jml mnlg`TG;3.+* +' bm! %$$# $% $X* Kmj kkjgaXK>4.*) *&\i~c  %! #QG akh iigc[PC7/*( )%Mkkyx}. $  !;\) (ggfb]TH;0+'(&#nfikhpm-  ( /e< Mge dcb^WNA5,(%&Bpjj` (14jI  \eccba`^YRG:/'$%+?cG    !4=/ PkL `baa`]]ZTL@3)%#"Z<  #*9JK8*2QkdE2' A˶? &WVMIJFB:/# 4 3VTIFFC=5+  Ž# 9TRRQECB?:2'hķ- >QPQN@@?<7/$- DONOK;94,">x% IMLMH67751*  [{d KLKLE2332.' j|R HJIKC-0/.+%lwv:MJHJB)+(" dmm lHEG@%%''%  Vf}J GDEA#!##" C~ex GBCB! #swu볉 IAAC" J$ QA?C&    m B=A.   >==8   <;>  ;:<*<98 ?9;" ;86 ::)79@99Rl8mk5^Z_iS1ǛygMY;Sr<\zPS i.I@;XthʬFF=D;k 7vHyK) W;T8^s]4ElN@M|hNyi(   E  , -D! ["  >JI>0-(3I.22-D10,22#03502,f23f00>33.12&_21.232"MC,'g32- e21)i+  5ʡ;s8mk%./rgD=7*)P2FlhWU&.sPB6 EcKl7BmaH1  c  TJ. w2n*-OV},9p*Z\1 +,7[t8mk@$1:AB:4+ :nɝn6.u経eM9,+7H\uq('BUf*2dsAƝwH"aBsL_{ÃB UW u9lF !T)kS%`-z7(QDL] _'V|^0$g ;y!*3)lS$k" mr zyB&Lb8 .FT`elqspqk`SD<. % Wtb+j{Q.Dmcڮf,zⵁE|:@he$6QqT3Y G.Iބ?$?2W+SHw\ڈ74Ylb;Ԓ %S*fvM Byl[O&Gm)=X͐FqN6} pbL9$O`EXӜ]BYAtWA,SE^ iJ?4{϶CSJ¯C֞g$Q}?9Z::+5gb*3t=Ο MJޣ.3~NSH }C: b  NX  |3 K  5 %   1   k  Q  d   ;DFF>_=    ,uK  2 KZ  b= !! ! 7w  m%(('$!k  +,*(%!  !   !-,)$  %(('%$"     (*(" *-.-,*)'&$"    *#   P&2100/-,*('%$! ( (0321110/.-+*(&" #z!333222110/.-+)&     T2-2333221110/.-,'!   u0122333221110/-(!     +/1223333322210-(   YB*-0123333332210,%  $'**))('&$! x"(,/12333333321/)   #.000//..,*)&+/12233333320,% `"1222211100(8&+.1233333321.' 1}"3333332322. %*/123333322/)!  Z&333333333.4L %,0123333320,%9-333333333"sk &-013333321-(!e%1333333331%  )/12333320/+% ! 233333333*I&-123333210-'  L)333333333"$,013333210-(  U&0333333331'$+02332210.*$ u"333333333-:'-013321/,(# `3-333333333&` $*/123210,&  !3333333332"'&%&'+.113320-' K3,3333333331&w /---./022321/)!x!333333333300b%222111233310-%%03333333333-=J*333333333320+# 7>)33333333333*K4/33333333333/*! K]"333333333222%['133333333333/+" Qz 2333333322110!a"3333333333320*! 8y!133333222110.,b[&333333333321/)  f1332222100.-+'#]8.333333333311-&9B#33211000/-+)&"R#333333333322/*! &mb$(210//.--+)&#Cp$33333333321/+$NܻN$-.--,+*)&$" 59.3333333221/,&  %' %'&&&%#"   "3333333211/,&   X'333332210/+%   '133332110-)" e%3332211.,'! H'132220/,)$ V&3210/-*%  !210/-*&! C1+0.,)%! Z .+'$ M)&!   ## N' h$ ]3 dn|&1?6ޱq$175& knowthelist-2.3.0/dist/headset.ico0000775000175000017500000030736612423536022016166 0ustar mariomario (f@@ (B00 %J  ^p  h( 175& 6q$1?RRU|&99:dn@BC399: 766]9::::;h:::))*$ ;;>>  :NZ .+'$ >>?C==>==>899  ?B1+0.,)%! BBB==>AAB.//   8I!210/-*&! QQPAAA??@CCD&&'  <@  mmmV&3210/-*%  IIIHAAAAAACCC""" {JJK$$$'132220/,)$ GGHBBCCCDBBC!!!   [p###ssuwxxuuue%3332211.,'!   GGHDDDEEEAAA###!!!######"""&' DSCCC~~eeexxx '133332110-)"   lmlHHHEEEGHH@@A%%%%%%''''''%%% @D7BVWWffg}}}JII X'333332210/+%  %' %'&&&%#"  MMN JJIHHGJJJBBA)))+++++++++((("""SZ4>ddemmnmll "3333333211/,& NN$-.--,+*)&$" HHI5JJKIIIKKKCCC---000///...+++%%%Zd:Elllwwwvvv:879.3333333221/,& &mb$(210//.--+)&#KKKCLLLKKKLLLEEE222333333222...'''[d KWjjj|||ROM9@p$33333333321/+$9B#33211000/-+)&"IIIRMNNLMMMNNHHH666777777555111*** U^ dt[[[{{{d``#$BK#333333333322/*! f1332222100.-+'#DEE]OOPNNOOOPKKK;;;;;;;;;999444,,,""" EM>>>xww%%%IT!8.333333333311-&8y!133333222110.,>>?bQQRPPQQQRNNN@@@@@@???<<<777///$$$27-$"P] R][&333333333321/)  Qz 2333333322110!999aTTSRRSRRSQQREEECCCBBB???:::222''' !)/hii-" NZhw"3333333333320*! K]"333333333222%333[VVVTTTTTTTTTIIIFFFFFFCCC===555+++  bm#KWn~'133333333333/+" 7>)33333333333*&&'KWWWVVVVVVVVVMMMIIIJJJFFFBBB:::///### k{444 Wex4/33333333333/*!   %03333333333-=YYYXXXXXXYYYSSSMMMMMMJJJEEE>>>222'''>E7=AAB?>> pJ*333333333320+#  %%%+++///000,,,"""x!333333333300XXXZ[[YZZZ[[VWWQQQQQQNNNIIIBBB777+++!!!111111 b%222111233310-%K '''///888@@@EEEHHHFFF===(((3,3333333331&TUU]]^[[\[\\ZZZTTTTTTRRRNNNFFF<<H&-123333210-'  e %%%!! !!!!!!!!!!!!!!!!!!!!!###QQQGGG %1333333331%aaakklhiihiihiiiiiiiigggccc[[[PPPCCC777///***(((((((((((((())%@HMk]]kklyyzxxyxxyxwy}yy.  )/12333320/+% %%%$$$$$$##$##$##$##$##$##$##$$$$%%& $$$XXX*** 9-333333333"KKKsmmnjkkjkkjkkkkkkkkjjjgggaaaXXXKKK>>>444...***)))))))))))))***&FP\rziba~~}c9Bk &-013333321-(! )))&&%&&&&&&&&&&&&&&&&&&&&&&&&&&&((' HHH@@@Z&333333333.4jkkmnnlllllllllmnnnnnlllggg```TTTGGG;;;333...+++**********++*+++'BJ bknmii!^q L %,0123333320,%1 !!!###$$$###!!"***(((((((((((((((((((((((((((((()))&&& ***MMM }"3333332322[[[pqqmnnmnnmnnoooqqqooolllfff]]]QQQCCC888222...,,,++++++++++,,+,,-!*24"djmoll&!  . %*/123333322/)! ` &&&&&&''''''&&&!!!(((,,,**+**+**+**+**+**+**+**+**+**++++,,,  III+++ "1222211100(8ooopppoopoopooprrrrrrqqqmmmfff[[[NNNBBB888222...,,,,,,,,,,,,,--,---&$.# 'Tc!fnqjgf!"##!!! &+.1233333321.' '''+++,,,---,,,)))###---...---------------------------------//0===555#.000//..,*)eeetttqqqqqrqqrrrruuuuuurrrmmmdddXXXKKK@@@777222///----------------...,,/#+))0OZinpgggvvw!""######!!!&+/12233333320,% ---000000111///,,,$$$111000000000000000000000000000000000000222$$$000:::$'**))('&$!222 uuusttsssrsssssvvvxxxvvvsssmmmcccVVVJJJ???888333000......///////////////,)(7/,lkknophhiaab***$$$%%% x"(,/12333333321/)   444555555555333///$$$556334334334334334334334334334334334334556)))''';;; qqrYwwwtttttttttuuuzzzzzzxxxtttmmmcccVVVJJJ@@@999444111000000000000000000---778mmnppqnnoihjrrrgghkkl...%%%&&&B*-0123333332210,%   999999999999666111&&&999666666666666666666666666666666666666888---###999 zzzvvvvwwvvvuvvxyy}}}}}}yyyuuunnncccWWWKKKBBB:::555333222111111111111...889nnpqqrqprppqjjk``_bbbiijoop///'''%%% +/1223333322210-(  """>>>>>>>>>===:::555((( <<<899899899899899899899899899899899899:;;/00!!!777 aaa|||wwwwxxwxxwww{{{~~~{{{vvvoooeeeYYYNNNDDD===777555222222222222///;;;pqrsstrrsrrsrrsffglllhiippq111)))u0122333221110/-(!  %%%CCCBBBBBBAAA>>>777***!""@AA<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>344###444 Tyzzyxyyyyyyyyyy~~~}}}xxxqqqggg\\\QQQHHH@@@;;;777555333222///>>>stttuusttstttuucddvvwddeqrr222'''2-2333221110/.-,'!  &&&IIIGGGFFFEEEAAA:::---"""CBB?>>?>>?>>?>>?>>?>>?>>?>>?>>?>>?>>?>>A@@555###000#zz{zz{z{{z{{{{{{{{ssskkkaaaWWWNNNGGGAAA===999777333DDEvvwvvwuuvuuvvvwddeccdrrs333z!333222110/.-+)&    '''LLLLLLKKKHHHDDD===000"""DDEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACCC666$$$+++( |||{{{{{{{{{|||}}}wwwppphhh```XXXQQQLLLHHHDDD???QQQyyzwwxwwxwwxyyzghhcccnoo111(0321110/.-+*(&" &&&OOOPPPNNNLLLHHHAAA333!!!!!!GGGDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDGGG667!!!!!!!!!%%%'''*#   ~~~|}}|}}|}}}~~|||uuuooohhhbbb]]]YYYUUUPPP^^_z{{xxyxxyxxyzz{llmaaaooqP&2100/-,*('%$!  %%%QQQUUUSSSPPPLLLDDD777$$$HHHHHHGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGJJJ555!!!$$$$$$$$$&&&###(*(" xww~~~~~~~~~~~zzzuuupppkkkgggddd___iii||}zz{zz{zz{{||lmn```vvv*-.-,*)'&$"    !!!!!! ###QQQ[[[WWWTTTPPPIII;;;''' EEELLMJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJLLL111$$$&&&&&&'''%%%""" !-,)$  GHH{||~~~~zzzvvvrrrnnniiirqr}}~{||{||{|||}}rrscccppq%(('%$"    ######"""!!!NNN```\\\YYYTTTMMMAAA,,,!!!===PPPLMMLMMLMMLMMLMMLMMLMMLMMLMMLMMMMMKKK+++'''(((((()))%%%"""!!!+,*(%!  z{{~~~zzzvvvqqqxxx~}}~}}~}}~~~xxyxxxgggiij!   $$$$$$$$$ HHHeee```]]]YYYRRRFFF222### ///TUUOOOOOOOOOOOOOOOOOOOOOOOOOOOOOORRREEE)))************%%%""""""m%(('$!ijjk넅{{{www|||{{{{{{hhhiii  %%%b%%%%%%!!!>>>iiidddbbb]]]VVVKKK999'''"""RRRSSSRRRRRRRRRRRRRRRRRRRRRRRRQQQTTT;;;***---,,,---***$$$###"""= !! ! FEG7}}}~~~yyyuuunnneefw  '''2''''''###444jjjiiifffbbb\\\QQQAAA,,,%%%"""AAAYZZSTTTTTTTTTTTTTTTTTTTTTTTUVVQQQ000---......///'''$$$$$$"""  hhhK~ssstttZZ[Z  ((((((((('''***dddpppkkkgggaaaXXXIII333&&&### $$$YYYXXXVVVVWWVWWVWWVWWVWWVVVZZZBBB---111000111---$$$%%%$$$###   ]^^,~u뇈҅tttvvvKKKK  )))))))))$$$VVVvvvooolllggg^^^QQQ===***&&&###???___XYYXXXXXXXXXXXXXXX\\\PPP111222222222333'''$$$%%%$$$###!!!d  kkk \\\;TTTDSSSFTTTFZZZ>cddz{{_tuuyyy...=  ***k******%%%BBByyytttrrrnnneeeYYYHHH222(((%%%!!!NNN`aa[\\YZZYZZZ[[]^^WWW788111444444666,,,###%%%%%%$$$######  ~llltttmmmKKLQ  +++%++++++***)))ooo|||wwwssslllaaaRRR>>>,,,'''$$$!!!LLL^^^_``_``^__STT:::333555666888000###$$$&&&&&&&&&%%%    Ѝ~nnooopmmnppqrrs[\\1   ------'''RRR{{{yyysssjjj\\\KKK666***((($$$ ???PPPNOODDD555444777888999///!!!###&&&&&&&&&&&&&&&K  VWW5||}}}~~~~~}}~~~||} ...X..."""---~~~zzzrrrgggXXXEEE111***((($$$!!!+++444888:::;;;999444((("""&&&(((((((((''''''  ~~|kkl3 666 +++!!! ___{{{rrreeeTTT@@@///+++)))%%%"""(((---,,,$$$$$$''')))))))))))))))b  ͒N+++}!!!"""///{{{qqqcccQQQ>>>///,,,***'''###!!!!!!%%%(((******++++++++++++C:LLM))* ###UUU}}}qqqcccRRR???111---+++)))%%%$$$"""!!!!!!"""###%%%(((***+++,,,---,,,---,,,Hyzz UUVCCC ###""""""zzz~~~tttfffWWWGGG888000---+++***)))(((((((((***+++---...///////////////NSiiiSSTUUU444!!!&&&555xxxlll```SSSGGG<<<666222000/////////000000111222222222111111222ߙ~__`UUVVVWRRR+++$$$'''KKK~~~uuulllbbbZZZRRRLLLFFFBBB@@@???===<<<:::666444333333222.~uuu9993^__XXYWWW[[[MMM&&&&&&'''[[[}}}vvvpppjjjeeeaaa[[[XXXUUUPPPKKKEEE>>>999666555Jއ}}|+++_`` [[[ZZZZZZ^^_JJJ&&%'''((( bbb~~~yyytttpppkkkfff```ZZZSSSLLLEEE@@@:::Mxxxbbb*^^_]]^]]^]]^bbbKKL)))'''((((((\\\}}}xxxsssllleee^^^WWWQQQKKKFFF3t~=rrrcdc5`a`````````````eeeSTT...%%%222000GGG|||vvvpppiiibbb[[[TTTQQQgeeebeef?ccccccccccccccccccggg^^_<<<223888222333XXXzzzsssllleee___9Z:utt:GGG+hhiCffgffgffgffgffgffgffgiijjjkOOO444888777111555KKKeeeuuu|||{{{zzzzzz{{{wwwgooo$Qyyy~~~}zzzkllJijjijjijjijjijjijjijjijjjjj{{{?9994999{999888333000111666888777CS___JsssoooSlmmlmmlmmlmmlmmlmmlmmlmmlmmoppEGGGAAA^wwwTTT }}}gggirrrYpppppppppppppppppppppppppppsttAtXYYWoooAxxxFFF,uvv]rtsrtsrtsrtsrtsrtsrtsrtsrtsvwwBxxxuuupppxxx`vvvvvvvvvvvvvvvvvvvvvvvvvvvyyzEWWWXsssfff{{|byyzyyzyyzyyzyyzyyzyyzyyzyyz}}~L9ղrrrddd$nnnWWWO~~a||}||}||}||}||}||}||}||}||}XpBBB>jjjpggg222]f'aaaiii```Xtl뷹yyyfff#eeeWWW[MCǺ999Mhhh}bbb;;;B-ZZZkkk___&ա*vvv pppCmmmUUUSϒ$8&xxxnnn""" zc [???Ippp(fffhhhfff<ݚaaad~~~{{{DDD*fffqDDDN6鶶󳳳nnn}nnn oooDDC=NNNabblll柠XŗͿ꿿yyy{{{SSSF;;;&ccc```KKKijjGł㧴m꽽ooo)~~~rrr dddJJJMMMNNNByͷl[񸸸rrr{{{VVVO[[[LLLVVVXXX %S̆м*{{{fvcccM~~~mmmZZZwUUU333\aaa[[[ڼҡ̏74YςѮl}||xxxbJJJwww~~~DDD;NNN2^^^%%%WeeeUUU+S´܍433YYYHhhh```jjjJJJEEE.dddIIIIҳބttt?楥666$QQQ?xxxqqqbbbfff```>>>T3͒Y}}} ~~~ܐCCCGlll:uuu000@DDDpppVVV%%%hҽe$6ŜkkkQvvvpppq___dddfrrrOOO,zE|888ttttzzztttlllNNNb+j֩{Q.DϜ򀀀mccccXXX555zzziiiXXX8 .FT`elqspqk`SD<. %ZZZ WzzzfffB}}}ffflll&ЎLbppp$bbbjjjk|||mmmڀ" m餤뢢r zy~~~VVV3{{{~~~qqqړ)lߣsssSSSSttt}}}|||瘘;y娨aaa!Ϛ֖*ttt|󛛛^0񮮮$sssg뗗 ʆ _任ttt'}}}睝Vbbb(嗗ٺQѺDL]}}}}}}昘rrr)ˮkSޤ%`뵵-z♙7 絵u9l״ǔF !嚚ѰT΂ؾsL_{˱򵵵ɃBrrr U򟟟˱WA݀׷⾾ʝwH"a񡡡B'BUf檪*2dת̹s.u訨硡eM9,+7H\uۯ󱱱𸸸q(:nǭ⫫쿿ɿn6$1:AB:4+ ?@???x?   0?p ?@@?@?O#'GGG???<|??`???A ???(@ B/sg%!3 %%& !!!445 (((99: kp47 555556 *-  000<<=''' a-)"@@?f@@A u}k(((WWW31/+" DDEBBB 5BRST444/21/)  (((FFFCCC###%%%!!!%&&&sst53321-#W\,&)(%" 888IIIFFF,,,,,,&&&-0 444LKK z13321.%p/10/.*%777%LLLIII444444,,,/3+2111~}-2+33332."H:22210.) !9OOPNNN===;;;111$' NZ8>9333331*f4333221@TTTRRSEEEBBB777###z{{49 5=c233332-I ,333337WWWWWWMMMIII???*** 2: >I/33332----999777 k13333-XYYZ[[UUUQQQGGG333 MX nw {||OOO LY>> -3333+RRS^^^\\\XXXPPP==='''!!!!!!!!666UUU*2 ")021,  +++(((;;;GGG `23331333bccaaa^^^YYYIII111$$$####""R_ ???ooo $   .220,#r !!!333444 +3333EfggeffdeebbbUUU>>>+++&&&&&&&"  13a`ajjkoop+23  .2320*"""""""""""""""""" EEE /3333*aaaijjijjiiiaaaMMM666***((((((())5ojj~~->>777222Z[[tuutuu~~oooRRRk12210.+& {:::MMMHHH888333BBBBBBBBBBBBBBBBBB===&&& fgg/}}}{||~~~xxxkkk\\\RRRJJJhhiwwxxxy||}wwwJJJ,10.+)%  $$$i:::VVVPPP???"""000IIIHHHHHHHHHHHHHHH???###%%%$$$ r*" ***)))___7~~wwwnnnfffutuz{{{{|z{{999z*)&"  +++L###555```XXXIII((($$$OPPMNNMNNMNNMNNNNN999((()))### K)("3|||Ձ~~~vvv||}~~~~yyy444X ---%&&&---hhhaaaSSS333"""OPPRSSSSSSSSSSSRSS000---+++### ZZZ郄~~~zz{SST4  222((('''hhhkkk___BBB&&&333YYYWWWWWWXXXGGG000111'''$$$!!! GHH fffLuuukllnnn{||~~~FFG"  ***)))TTTvvvlllUUU111$$$FFF\]]\]]PPP444555---$$$%%%"""o    ,,,444+++222666__`\qrroop\\]Y 667D))),,,yyygggGGG+++$$$555???777777+++###'''&&&"""  999 ||}]^^  @@@&&&hhhzzzccc???+++&&&### $$$)))****** ))) 333 ZZZ򒑓|}}"XXXBCC CCD!!!,,,|||cccCCC000)))&&&$$$%%%))),,,---------WWWsstOOOTTU444$$$KKKoooZZZGGG===888666555333222111D4xyy,VWW YYYXXX//.%%%```tttjjjaaaWWWKKK???777c!垝܀sss[\[^__^^_\\\444)))[[[|||qqqcccUUUHHHHܢvvvaab ddeddeddeeeeIIJ555<<~; JкȍK  ???  <?''G??x <???(0` %3& .x ### 5##$001 35 A 555  fj24=111;;< KP+62) >>>j::: YYY99910*  >>>;;;""" UUU$$$321/% 7xa,*($ """ JJJ@@@...)))')|mmnpoor2320)bM10/,%KLLGGG888000%'nnn ,013220# K32210LLLNNOBBB888  899AI 93232) 32222GGGVVVLLLCCC(((IPhhh HTO2222*9 '''===III:::1230AAA[\\VVVNNN333!!!T`ZZZ333gy ](*/2.   +++)))$$$EEE7222+++taaa^_^YYYBBB(((###"%& |SSS)))[ (11-!*  ;;; b233;ffgeffdddSSS666'''&&&$@HSWXppq[[\bx !U (121+k!!!$$$$$$$$$!!! '''032/STTkkkkllcccIII000)))))(%N[!ruvX$&!"B  .220%'''&&&************+++/// -10/'''Yooopppppp```BBB///,,,,++)>E+wz{|nnn!!!)-222."""444///333223223223333+++iiisttwwwttt^^^AAA222//////977mmnVVV '.2221' +++???777;;;::::::::::::&&&((()))LLLxxxxxy}}}wwwaaaGGG888333===rssnoo~~VVV/220/) ###111JJJ@@@!!!BBBAAAAAAAAABAA+++%%% ```?||||}}|||lllYYYKKKOOPwwxsstQQR31/,)# """333WWWJJJ)))HHIIIIIIIIIIIII---%%%"""(" MMMK{{{{{{pppmmn{{|yyzBBC'$  &&&...cccVVV444FFFPPPPPPPPPLLL---***####&&&BppqÂ{{|NNNt  +++v(((iiidddEEE$$$000WWWVVVVWWCCC000***###\ [\\ItuurrrtuuօTTU[  3341)))XXXttt]]]111"""AAAWXXLLL555000%%%%%%  %%%!!!$$$99: ˊssshhh<<=***444tttNNN,,,"""(((000***$$$((('''    QQR1󏏐]^^(((>>?!!!fffsssLLL000&&&""""""''',,,---+++,,,JJJfffrrrJJKUUV666,,,~~~eeeNNNCCC>>>999444222YCxxxYSSS]]]YYY666777}}}ooo```NNN>>>f6667栠.]]^cddcccaabGGG;;;eee{{{hhhQQQ/+०||| iii lmmkllkllooo]^^WXXDWWWOYYY3eee0媫vvvWrrrrss tuuttttttuvvI毰Ҁ0rrr[z{{ |}}||}||}}~~yzzQsssghhh%~ ҅Cʹrss|}}```mmm{||􊊊 ;qqq0___lVRo懇,zzzfff[[[ZZZࣤ#Eφ­ǜ91nnnPPPhhh۞ҠѰ:1YԋẺ7rrrmmm#_``|YYYlll@Uunzzz!ooobaaaooooGJG<. k61rrrQwww_j`[DmwwwLq,^jDߴg!K7bc-qɷڷi5 'ghA}Ŋq-?0@p?? 1? `( @  5; 333  36 444//0  P^ i+  777e111 55521)MC,' AAA<<<,,, "g32-_21.778III9997>/5232"  >33000UUUHHH&&&000}}} >I.12& f ..-...77723!!!f___XXX777"""P\;@NNN_q 00 ,,, 035efffffPPP,,,'&&Dhnuvv;>H!02,$$$"""))))))###"""D10FFFooojjjDDD---+,,"kc ,22#3 666!!!///444444222$$$I...tttxxxjjjCCC222///a`accd.22- >)))FFF(((999@??@??==="""JZZZI{{{rrrTTTAAAkllzzz``a>0-((((-,,,WWW555;;;KKKKKKCCC&&&!!!D!  ???[~􄄄rrrzz{{{|]]]"  --- (((gggJJJ ,,,UUUUUU>>>,,,""" ,mmmzzzzzz˄nnn ,,,]]]hhh222;< "with-mad" depends_on "taglib" depends_on 'qt' def install system "qmake" system "make" bin.install buildpath/"knowthelist.app" system "cp -R #{bin}/knowthelist.app /Applications" end test do system "false" end end knowthelist-2.3.0/debian/0000775000175000017500000000000012423536022014312 5ustar mariomarioknowthelist-2.3.0/debian/watch0000664000175000017500000000023112423536022015337 0ustar mariomarioversion=3 opts=filenamemangle=s/.+\/v?(\d\S*)\.tar\.gz/knowthelist-$1\.tar\.gz/ \ https://github.com/knowthelist/knowthelist/tags .*/v?(\d\S*)\.tar\.gzknowthelist-2.3.0/debian/source/0000775000175000017500000000000012423536022015612 5ustar mariomarioknowthelist-2.3.0/debian/source/format0000664000175000017500000000001312423536022017017 0ustar mariomario3.0 (quilt)knowthelist-2.3.0/debian/docs0000664000175000017500000000001212423536022015156 0ustar mariomarioREADME.md knowthelist-2.3.0/debian/compat0000664000175000017500000000000212423536022015510 0ustar mariomario8 knowthelist-2.3.0/debian/copyright0000664000175000017500000000365312423536022016254 0ustar mariomarioFormat: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: knowthelist Source: https://github.com/knowthelist/knowthelist Files: * Copyright: 2014 Mario Stephan License: LGPL-2.1+ Files: * Copyright: 2014 Mario Stephan License: LGPL-3.0+ License: LGPL-3.0+ This package is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. . This package is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. . You should have received a copy of the GNU General Public License along with this program. If not, see . . On Debian systems, the complete text of the GNU Lesser General Public License can be found in "/usr/share/common-licenses/LGPL-3". License: LGPL-2.1+ This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser Public License as published by the Free Software Foundation; either version 2.1, or (at your option) any later version. . This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser Public License for more details. . You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA X-Comment: On Debian systems, the complete text of the GNU Lesser General Public License can be found in `/usr/share/common-licenses/LGPL-2.1'.knowthelist-2.3.0/debian/README0000664000175000017500000000076212423536022015177 0ustar mariomarioknowthelist =========== Knowthelist - the awesome party music player - Easy to use for all party guests - Quick search for tracks in collection - Two players with separate playlists - Mixer with fader, 3 channel EQ and gain - Auto fader and auto gain - Trackanalyser search for song start/end and gain setting - Auto DJ function with multiple filters for random play - Monitor player for pre listen tracks (via 2nd sound card e.g. USB) - ... more https://github.com/knowthelist/knowthelist/wikiknowthelist-2.3.0/debian/rules0000775000175000017500000000050712423536022015374 0ustar mariomario#!/usr/bin/make -f # Uncomment this to turn on verbose mode. #export DH_VERBOSE=1 include /usr/share/cdbs/1/rules/debhelper.mk include /usr/share/cdbs/1/class/qmake.mk HASQT5=$(shell qmake -qt5 -v > /dev/null 2>&1 && echo yes) ifeq ($(HASQT5),yes) QMAKE=qmake -qt5 else QMAKE=qmake-qt4 endif CFLAGS=-O3 CXXFLAGS=-O3knowthelist-2.3.0/debian/changelog0000664000175000017500000000160412423536022016165 0ustar mariomarioknowthelist (2.3.0-1) unstable; urgency=medium * Made all compatible with Qt5 and Gstreamer-1.0. * Add an ALL node to filter results * Changed ModeSelector style and moved to tree header * Included 'year' tag into quick search -- Mario Stephan Fri, 19 Sep 2014 23:08:00 +0200 knowthelist (2.2.4-1) unstable; urgency=medium * Fixed a bug which prevent correct monitoring of changes * Improved quick search in collection: added search in genre, multiple strings * Changed alignment of some display controls * Allow more audio file formates * Added a mutex to get more thread safety for database access -- Mario Stephan Sun, 14 Sep 2014 01:18:00 +0200 knowthelist (2.2.3-1) unstable; urgency=medium * Initial Release (Closes: #751350). -- Mario Stephan Tue, 26 Aug 2014 07:06:00 +0200knowthelist-2.3.0/debian/control0000664000175000017500000000256312423536022015723 0ustar mariomarioSource: knowthelist Section: sound Priority: optional Maintainer: Mario Stephan Build-Depends: cdbs, qt5-qmake|qt4-qmake, qtbase5-dev|libqt4-dev, debhelper (>= 8), qttools5-dev-tools|qt4-linguist-tools, libc6 (>= 2.2), libgcc1 (>= 1:4.1.1), libglib2.0-0 (>= 2.12.0), libgstreamer1.0-0 | libgstreamer0.10-0 (>= 0.10.0), libgstreamer1.0-dev | libgstreamer0.10-dev, libqt5sql5|libqt4-sql (>= 4:4.5.3), libqt5xml5|libqt4-xml (>= 4:4.5.3), libqt5gui5|libqtgui4 (>= 4:4.7.0~beta1), libqt5core5a|libqtcore4 (>= 4:4.7.0~beta2), libstdc++6, libtag1-vanilla|libtag1c2a (>= 1.5), libtag1-dev, libasound2, libasound2-dev Standards-Version: 3.9.6 Homepage: http://knowthelist.github.io/knowthelist Vcs-Git: git://github.com/knowthelist/knowthelist.git Vcs-Browser: https://github.com/knowthelist/knowthelist Package: knowthelist Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, libqt4-sql-sqlite | libqt5sql5-sqlite Description: awesome party music player Easy to use for all party guests. . Featuring: - Quick search for tracks in collection. - Two players with separate playlists. - Mixer with fader, 3 channel EQ and gain. - Auto fader and auto gain. - Track analyser search for song start/end and gain setting. - Auto DJ function with multiple filters for random play. - Monitor player for pre listen tracks (via 2nd sound card e.g. USB).knowthelist-2.3.0/knowthelist.pro0000664000175000017500000000007212423536022016164 0ustar mariomarioTEMPLATE = subdirs win32:SUBDIRS += gst SUBDIRS += src knowthelist-2.3.0/src/0000775000175000017500000000000012423536022013657 5ustar mariomarioknowthelist-2.3.0/src/collectiondb.h0000775000175000017500000000704612423536022016503 0ustar mariomario/* Copyright (C) 2005-2014 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #ifndef COLLECTIONDB_H #define COLLECTIONDB_H #include #include #include #include #include "progressbar.h" //class sqlite; class CollectionDB : public QObject { Q_OBJECT public: CollectionDB(); ~CollectionDB(); bool isDbValid(); bool isEmpty(); void incSongCounter( const QString url ); void setSongRate( const QString url, int rate ); void updateDirStats( QString path, const long datetime ); void removeSongsInDir( QString path ); bool isDirInCollection( QString path ); void removeDirFromCollection( QString path ); void removePlaylist( QString name ); void setFilterString( QString string ); bool executeSql(const QString& statement); QList selectSql( const QString& statement); long selectSqlNumber( const QString& statement ); int sqlInsertID(); QString escapeString( QString string ); ulong getValueID( QString name, QString value, bool autocreate = true, bool useTempTables = false ); ulong getCount(); uint getCount(QString path, QString genre, QString artist); QPair getCount(QStringList paths, QStringList genres, QStringList artists); long lastLengthSum(); uint lastMaxCount(); QList selectRandomEntry( QString rownum, QString path="", QString genre="", QString artist=""); QStringList getRandomEntry(); QStringList getRandomEntry(QString path, QString genre,QString artist); void createTables( const bool temporary = false ); void dropTables( const bool temporary = false ); void moveTempTables(); void createStatsTable(); void dropStatsTable(); void resetSongCounter(); void purgeDirCache(); void scanModifiedDirs( bool recursively ); void scan( const QStringList& folders, bool recursively ); QList selectTracks(QString year, QString genre, QString artist, QString album ); QList selectAlbums(QString year, QString genre, QString artist); QList selectArtists(QString year="", QString genre=""); QList selectYears(); QList selectGenres(); QList selectHotTracks(); QList selectLastTracks(); QList selectFavoritesTracks(); QList selectPlaylistData(); QList selectPlaylistTracks(QString name); signals: void scanDone( bool changed ); private slots: private: struct CollectionDbPrivate * p; QSqlDatabase db; ProgressBar* m_progress; bool m_monitor; int m_lastInsertId; }; #endif /* COLLECTIONDB_H */ knowthelist-2.3.0/src/djbrowser.cpp0000775000175000017500000003026312423536022016373 0ustar mariomario/* Copyright (C) 2005-2014 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #include "djbrowser.h" #include "dj.h" #include "djwidget.h" #include "djfilterwidget.h" #include "collectiondb.h" #include #include #include #include class DjBrowserPrivate { public: QSplitter* splitter; QListWidget* listDjs; QListWidget* listDjFilters; Dj* currentDj; DjWidget* currentDjw; QStringList allGenres; QStringList allArtists; CollectionDB* database; }; DjBrowser::DjBrowser(QWidget *parent) : QWidget(parent) { p = new DjBrowserPrivate; p->database = new CollectionDB(); QList tags = p->database->selectArtists(); p->allArtists.append( QString::null ); foreach ( QStringList tag, tags) p->allArtists.append( tag[0] ); tags = p->database->selectGenres(); p->allGenres.append( QString::null ); foreach ( QStringList tag, tags) p->allGenres.append( tag[0] ); QPushButton* pushAddDj =new QPushButton(); pushAddDj->setGeometry(QRect(1,1,60,25)); pushAddDj->setMaximumWidth(60); pushAddDj->setMinimumWidth(60); pushAddDj->setText("+"); QFont pushFont = pushAddDj->font(); pushFont.setBold(true); pushFont.setPointSize(pushFont.pointSize()+4); pushAddDj->setFont(pushFont); pushAddDj->setStyleSheet("QPushButton { border: none; padding-top: -3px; margin-left:8px;max-height: 20px; margin-right: 28px;}"); pushAddDj->setToolTip(tr( "Add a new AutoDj" )); connect( pushAddDj,SIGNAL(clicked()),this, SLOT(addDj())); QPushButton* pushAddFilter =new QPushButton(); pushAddFilter->setGeometry(QRect(1,1,60,25)); pushAddFilter->setMaximumWidth(60); pushAddFilter->setMinimumWidth(60); pushAddFilter->setText("+"); pushAddFilter->setFont(pushFont); pushAddFilter->setStyleSheet("QPushButton { border: none; padding-top: -3px; margin-left: 8px;max-height: 20px; margin-right: 28px;}"); pushAddFilter->setToolTip(tr( "Add a new record case for current AutoDj" )); connect( pushAddFilter,SIGNAL(clicked()),this, SLOT(addFilter())); p->listDjFilters = new QListWidget(); p->listDjs = new QListWidget(); p->listDjFilters->setAttribute(Qt::WA_MacShowFocusRect, false); p->listDjs->setAttribute(Qt::WA_MacShowFocusRect, false); p->listDjs->setItemSelected(p->listDjs->currentItem(),false); QVBoxLayout *mainLayout = new QVBoxLayout; QVBoxLayout *headWidgetLeftLayout = new QVBoxLayout; headWidgetLeftLayout->setMargin(0); headWidgetLeftLayout->setSpacing(1); headWidgetLeftLayout->setAlignment(Qt::AlignRight); headWidgetLeftLayout->addWidget(pushAddDj); QWidget *headWidgetLeft = new QWidget(this); headWidgetLeft->setMaximumHeight(20); headWidgetLeft->setMinimumHeight(20); headWidgetLeft->setLayout(headWidgetLeftLayout); QVBoxLayout *headWidgetRightLayout = new QVBoxLayout; headWidgetRightLayout->setMargin(0); headWidgetRightLayout->setSpacing(1); headWidgetRightLayout->setAlignment(Qt::AlignRight); headWidgetRightLayout->addWidget(pushAddFilter); QWidget *headWidgetRight = new QWidget(this); headWidgetRight->setMaximumHeight(20); headWidgetRight->setMinimumHeight(20); headWidgetRight->setLayout(headWidgetRightLayout); QVBoxLayout *widgetLeftLayout = new QVBoxLayout; widgetLeftLayout->setMargin(0); widgetLeftLayout->setSpacing(1); widgetLeftLayout->setAlignment(Qt::AlignRight); widgetLeftLayout->addWidget(headWidgetLeft); widgetLeftLayout->addWidget(p->listDjs); QVBoxLayout *widgetRightLayout = new QVBoxLayout; widgetRightLayout->setMargin(0); widgetRightLayout->setSpacing(1); widgetRightLayout->setAlignment(Qt::AlignRight); widgetRightLayout->addWidget(headWidgetRight); widgetRightLayout->addWidget(p->listDjFilters); QWidget *widgetLeft = new QWidget(this); widgetLeft->setLayout(widgetLeftLayout); QWidget *widgetRight = new QWidget(this); widgetRight->setLayout(widgetRightLayout); p->splitter = new QSplitter(); p->splitter->addWidget(widgetLeft); p->splitter->addWidget(widgetRight); mainLayout->addWidget(p->splitter); mainLayout->setMargin(0); mainLayout->setSpacing(0); setLayout(mainLayout); QSettings settings; p->splitter->setStretchFactor(0, 5); p->splitter->setStretchFactor(1, 9); p->splitter->restoreState(settings.value("SplitterDjBrowser").toByteArray()); //ToDo: restore last DJ from settings } DjBrowser::~DjBrowser() { saveSettings(); delete p; } void DjBrowser::saveSettings() { QSettings settings; settings.setValue("SplitterDjBrowser",p->splitter->saveState()); settings.setValue("countDJ",p->listDjs->count()); settings.remove("AutoDJ"); settings.beginGroup("AutoDJ"); for (int d=0;dlistDjs->count();d++) { settings.beginGroup(QString::number(d)); Dj* dj = ((DjWidget*)p->listDjs->itemWidget(p->listDjs->item(d)))->dj(); settings.setValue("Name", dj->name ); settings.setValue("FilterCount", dj->filters().count() ); QList f=dj->filters(); settings.beginGroup("Filter"); for (int i=0; ipath()); settings.setValue("Genre",f.at(i)->genre()); settings.setValue("Artist",f.at(i)->artist()); settings.setValue("Value",QString::number(f.at(i)->maxUsage())); settings.endGroup(); } settings.endGroup(); settings.endGroup(); } settings.endGroup(); } void DjBrowser::updateList() { QSettings settings; //Dj Widget List p->listDjs->clear(); p->listDjs->setSelectionMode(QAbstractItemView::ExtendedSelection); DjWidget* djw; QListWidgetItem* itm; Dj* dj; int maxDj=settings.value("countDJ","3").toInt(); if (maxDj==0) maxDj=1; settings.beginGroup("AutoDJ"); // DJs for (int d=0;dname = settings.value("Name","Dj%1").toString().arg(d+1); djw = new DjWidget(p->listDjs); connect(djw,SIGNAL(activated()),this,SLOT(loadDj())); connect(djw,SIGNAL(deleted()),this,SLOT(removeDj())); connect(djw,SIGNAL(started()),this,SLOT(startDj())); itm = new QListWidgetItem(p->listDjs); itm->setSizeHint(QSize(0,75)); p->listDjs->addItem(itm); p->listDjs->setItemWidget(itm,djw); // Filters int countFilter = settings.value("FilterCount","2").toInt(); if (countFilter==0) countFilter=1; settings.beginGroup("Filter"); for (int i=0;iaddFilter(f); f->setPath(settings.value("Path","").toString()); f->setGenre(settings.value("Genre","").toString()); f->setArtist(settings.value("Artist","").toString()); f->setMaxUsage(settings.value("Value","4").toInt()); settings.endGroup(); f->setUsage(0); } djw->setDj(dj); // force sum update djw->clicked(); settings.endGroup(); dj->setActiveFilterIdx(settings.value("currentDjActiveFilter","0").toInt()); settings.endGroup(); } settings.endGroup(); p->listDjs->setCurrentRow(0); DjWidget* djWidget = (DjWidget*)p->listDjs->itemWidget(p->listDjs->currentItem()); djWidget->activateDJ(); djWidget->clicked(); p->listDjs->setItemSelected(p->listDjs->currentItem(),false); p->listDjs->setSelectionMode(QAbstractItemView::NoSelection); } void DjBrowser::addDj() { QSettings settings; settings.setValue("countDJ",p->listDjs->count()+1); updateList(); } void DjBrowser::removeDj() { if(DjWidget* djWidget = qobject_cast(QObject::sender())){ // search the Dj which to remove for (int d=0;dlistDjs->count();d++){ if ((DjWidget*)p->listDjs->itemWidget(p->listDjs->item(d)) == djWidget){ p->listDjs->removeItemWidget(p->listDjs->item(d)); delete p->listDjs->item(d); //delete djWidget; } } saveSettings(); updateList(); Dj* dj=((DjWidget*)p->listDjs->itemWidget(p->listDjs->item(0)))->dj(); Q_EMIT selectionChanged(dj); } } void DjBrowser::startDj() { qDebug() << Q_FUNC_INFO ; loadDj(); Q_EMIT selectionStarted(); } void DjBrowser::loadDj() { //Fill Filter Widget List qDebug() << Q_FUNC_INFO ; p->listDjFilters->clear(); DjFilterWidget *djfw; QListWidgetItem * itm; // deactivate all Djs for (int d=0;dlistDjs->count();d++) ((DjWidget*)p->listDjs->itemWidget(p->listDjs->item(d)))->deactivateDJ(); // Activate current selected DJ if(DjWidget* djWidget = qobject_cast(QObject::sender())){ djWidget->activateDJ(); Dj* dj = djWidget->dj(); Q_EMIT selectionChanged(dj); // Filters if (dj->filters().count()==0) { //last filter has been removed Filter* f = new Filter(); f->setMaxUsage(4); dj->addFilter(f); } qDebug() << Q_FUNC_INFO<< "name="<name << "filters="<< dj->filters().count(); for (int i=0;ifilters().count();i++) { djfw = new DjFilterWidget(p->listDjFilters); djfw->setID(QString::number(i+1)); djfw->setAllGenres( p->allGenres ); djfw->setAllArtists( p->allArtists ); djfw->setFilter( dj->filters().at(i) ); itm = new QListWidgetItem(p->listDjFilters); itm->setSizeHint(QSize(0,75)); p->listDjFilters->addItem(itm); p->listDjFilters->setItemWidget(itm,djfw); dj->filters().at(i)->update(); connect(djfw,SIGNAL(deleted()),this,SLOT(removeFilter())); } dj->setActiveFilterIdx(0); p->currentDj=dj; p->currentDjw=djWidget; } // give a chance to update the labels qApp->processEvents(); } void DjBrowser::addFilter() { Filter* f = new Filter(); f->setMaxUsage(4); p->currentDj->addFilter(f); p->currentDjw->clicked(); } void DjBrowser::removeFilter() { if( DjFilterWidget* fw = qobject_cast(QObject::sender()) ){ // search the Filter which to remove for (int d=0;dlistDjFilters->count();d++){ if ((DjFilterWidget*)p->listDjFilters->itemWidget(p->listDjFilters->item(d)) == fw ){ p->currentDj->removeFilter(fw->filter()); p->listDjFilters->removeItemWidget(p->listDjFilters->item(d)); delete p->listDjFilters->item(d); } } saveSettings(); p->currentDjw->clicked(); } } knowthelist-2.3.0/src/collectiontreeitem.cpp0000664000175000017500000000506712423536022020265 0ustar mariomario/* Copyright (C) 2005-2014 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #include "collectiontreeitem.h" struct CollectionTreeItemPrivate { QString artist; QString album; QString year; QString genre; }; CollectionTreeItem::CollectionTreeItem(QTreeWidget* parent, int type) : QTreeWidgetItem(parent,type) ,p(new CollectionTreeItemPrivate) { setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator); } CollectionTreeItem::CollectionTreeItem(QTreeWidgetItem* parent, int type) : QTreeWidgetItem(parent,type) ,p(new CollectionTreeItemPrivate) { } CollectionTreeItem::~CollectionTreeItem() { delete p; } QString CollectionTreeItem::artist() { return p->artist; } QString CollectionTreeItem::album() { return p->album; } QString CollectionTreeItem::year() { return p->year; } QString CollectionTreeItem::genre() { return p->genre; } void CollectionTreeItem::setArtist(QString value) { p->artist=value; setTextString(value); QTreeWidgetItem::setIcon( 0, QIcon( style()->standardIcon(QStyle::SP_DirHomeIcon).pixmap(12)) ); } void CollectionTreeItem::setAlbum(QString value) { p->album=value; setTextString(value); QTreeWidgetItem::setIcon( 0, QIcon(style()->standardIcon(QStyle::SP_DriveCDIcon).pixmap(12)) ); } void CollectionTreeItem::setYear(QString value) { p->year=value; setTextString(value); QTreeWidgetItem::setIcon( 0, QIcon(style()->standardIcon(QStyle::SP_FileIcon).pixmap(12)) ); } void CollectionTreeItem::setGenre(QString value) { p->genre=value; setTextString(value); QTreeWidgetItem::setIcon( 0, QIcon(style()->standardIcon(QStyle::SP_DirIcon).pixmap(12)) ); } void CollectionTreeItem::setTextString(QString value) { if ( value == QString::null ){ setText(0,QString("( %1 )").arg(tr("All"))); setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicator); } else setText(0,value); } knowthelist-2.3.0/src/collectiondb.cpp0000775000175000017500000005715212423536022017041 0ustar mariomario/* Copyright (c) 2004 Mark Kretschmann Copyright (c) 2004 Christian Muehlhaeuser Copyright (C) 2005-2014 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #include "collectiondb.h" #include #include #include #include class CollectionDbPrivate { public: uint genreCount; QString lastPath; QString lastArtist; QString lastGenre; QString lastFilterString; QString filterString; ulong resultCount; ulong resultLength; QString sqlQuickFilter; QString sqlFromString; QString sqlFromStringPL; QSqlDatabase *db; QSqlQuery *query; QMutex mutex; QString selectionFilter(QString year="", QString genre="", QString artist="", QString album="") { QString ret = ""; if ( !year.isEmpty() ) ret += "AND year.name = '" + year.replace( "'", "''" ) + "' "; if ( !genre.isEmpty() ) ret += "AND genre.name = '" + genre.replace( "'", "''" ) + "' "; if ( !artist.isEmpty() ) ret += "AND artist.name = '" + artist.replace( "'", "''" ) + "' "; if ( !album.isEmpty() ) ret += "AND album.name = '" + album.replace( "'", "''" ) + "' "; return ret; } QString selectionFilterForRandom(QString path="", QString genre="", QString artist="") { QString ret = ""; if ( !path.isEmpty() ) ret += "AND lower(tags.url) like lower('%" + path.replace( "'", "''" ) + "%') "; if ( !genre.isEmpty() ) ret += "AND lower(genre.name) like lower('%" + genre.replace( "'", "''" ) + "%') "; if ( !artist.isEmpty() ) ret += "AND lower(artist.name) like lower('%" + artist.replace( "'", "''" ) + "%') "; return ret; } QString selectionFilterForRandom(QStringList paths, QStringList genres, QStringList artists) { QString ret = ""; if ( !paths.isEmpty() ){ ret += "AND ( "; foreach (QString path, paths) ret += " lower(tags.url) like lower('%" + path.replace( "'", "''" ) + "%') OR "; ret += " 1=2) "; } if ( !genres.isEmpty() ){ ret += "AND ( "; foreach (QString genre, genres) ret += " lower(genre.name) like lower('%" + genre.replace( "'", "''" ) + "%') OR "; ret += " 1=2) "; } if ( !artists.isEmpty() ){ ret += "AND ( "; foreach (QString artist, artists) ret += " lower(artist.name) like lower('%" + artist.replace( "'", "''" ) + "%') OR "; ret += " 1=2) "; } return ret; } }; CollectionDB::CollectionDB() { p = new CollectionDbPrivate; db = QSqlDatabase::database(); p->db = &db; p->query = new QSqlQuery(*(p->db)); p->genreCount=0; p->resultCount=0; p->sqlQuickFilter = QString(""); p->sqlFromString = "FROM tags " " INNER JOIN artist ON tags.artist = artist.id " " INNER JOIN album ON tags.album = album.id " " INNER JOIN year ON tags.year = year.id " " INNER JOIN genre ON tags.genre = genre.id " " LEFT OUTER JOIN statistics ON tags.url = statistics.url " " LEFT OUTER JOIN favorites ON tags.url = favorites.url WHERE 1=1 "; p->sqlFromStringPL = "FROM tags " " INNER JOIN artist ON tags.artist = artist.id " " INNER JOIN album ON tags.album = album.id " " INNER JOIN year ON tags.year = year.id " " INNER JOIN genre ON tags.genre = genre.id " " INNER JOIN playlists ON tags.url = playlists.url " " LEFT OUTER JOIN statistics ON tags.url = statistics.url " " LEFT OUTER JOIN favorites ON tags.url = favorites.url WHERE 1=1 "; } CollectionDB::~CollectionDB() { db.close(); delete p; p=0; } QString CollectionDB::escapeString( QString string ) { string.replace( "'", "''" ); return string; } void CollectionDB::setFilterString( QString string ) { string = escapeString( string ); p->filterString = string; p->sqlQuickFilter = ""; foreach (QString token, string.split(" ")) { p->sqlQuickFilter += QString( " AND ( lower(artist.name) LIKE lower('%%1%') OR " "lower(album.name) LIKE lower('%%1%') OR " "lower(tags.title) LIKE lower('%%1%') OR " "lower(genre.name) LIKE lower('%%1%') OR " "lower(year.name) LIKE lower('%%1%') OR " "lower(tags.url) LIKE lower('%%1%') )") .arg(token); } } bool CollectionDB::isDbValid() { if ( ( !executeSql( "SELECT COUNT( url ) FROM tags;" ) ) || ( !executeSql( "SELECT COUNT( url ) FROM statistics;" ) ) || ( !executeSql( "SELECT COUNT( url ) FROM favorites;" ) ) || ( !executeSql( "SELECT COUNT( url ) FROM playlists;" ) ) ) return false; else return true; } bool CollectionDB::isEmpty() { return ( selectSqlNumber("SELECT COUNT( url ) FROM tags;" ) < 1 ); } void CollectionDB::incSongCounter( const QString url ) { QList entries; entries = selectSql( QString( "SELECT playcounter, createdate FROM statistics WHERE url = '%1';" ) .arg( escapeString( url ) ) ); if ( !entries.isEmpty() ) { // entry exists, increment playcounter and update accesstime executeSql( QString( "REPLACE INTO statistics ( url, createdate, accessdate, playcounter ) VALUES ( '%1', '%2', strftime('%s', 'now'), %3 );" ) .arg( escapeString( url ) ) .arg( entries.at(0)[1] ) .arg( entries.at(0)[0] + " + 1" ) ); } else { // entry didnt exist yet, create a new one executeSql( QString( "INSERT INTO statistics ( url, createdate, accessdate, playcounter ) VALUES ( '%1', strftime('%s', 'now'), strftime('%s', 'now'), 1 );" ) .arg( escapeString( url ) ) ); } } void CollectionDB::setSongRate( const QString url, int rate ) { // insert or update increment favorites executeSql( QString( "INSERT OR REPLACE INTO favorites ( url, changedate, rate ) VALUES ( '%1', strftime('%s', 'now'), %2 );" ) .arg( escapeString( url ) ) .arg( rate ) ); } void CollectionDB::resetSongCounter() { executeSql( QString( "DELETE FROM statistics;")); //executeSql( QString( "VACUUM;")); } void CollectionDB::updateDirStats( QString path, const long datetime ) { if ( path.endsWith( "/" ) ) path = path.left( path.length() - 1 ); executeSql( QString( "REPLACE INTO directories ( dir, changedate ) VALUES ( '%1', %2 );" ) .arg( escapeString( path ) ) .arg( datetime ) ); } void CollectionDB::removeSongsInDir( QString path ) { if ( path.endsWith( "/" ) ) path = path.left( path.length() - 1 ); executeSql( QString( "DELETE FROM tags WHERE dir = '%1';" ) .arg( escapeString( path ) ) ); } bool CollectionDB::isDirInCollection( QString path ) { if ( path.endsWith( "/" ) ) path = path.left( path.length() - 1 ); QList entries = selectSql( QString( "SELECT changedate FROM directories WHERE dir = '%1';" ) .arg( escapeString( path ) ) ); return !entries.isEmpty(); } void CollectionDB::removeDirFromCollection( QString path ) { if ( path.endsWith( "/" ) ) path = path.left( path.length() - 1 ); executeSql( QString( "DELETE FROM directories WHERE dir = '%1';" ) .arg( escapeString( path ) ) ); } void CollectionDB::removePlaylist( QString name ) { executeSql( QString( "DELETE FROM playlists WHERE name = '%1';" ) .arg( escapeString( name ) ) ); } long CollectionDB::selectSqlNumber( const QString& statement ) { p->mutex.lock(); if (p->query->exec(statement)) { while (p->query->next()) { p->mutex.unlock(); return p->query->value(0).toInt(); } } else qDebug() << p->query->lastError(); p->mutex.unlock(); return -1; } bool CollectionDB::executeSql( const QString& statement ) { p->mutex.lock(); if (p->query->exec(statement)){ p->mutex.unlock(); return true; } else { qDebug() << p->query->lastError(); qDebug() << "Statement: " << statement; p->mutex.unlock(); return false; } } QList CollectionDB::selectSql( const QString& statement) { QList tags; p->mutex.lock(); tags.clear(); int count; if (p->query->exec(statement)) { while (p->query->next()) { QStringList tag; count = p->query->record().count(); for ( int i = 0; i < count; i++ ) { tag << p->query->value(i).toString() ; } tags << tag; } } else{ qDebug() << p->db->lastError() << "\n" << p->query->lastError(); qDebug() << "SQL-query: " << statement; } p->mutex.unlock(); return tags; } void CollectionDB::createTables( bool temporary ) { qDebug() << Q_FUNC_INFO; //create tag table executeSql( QString( "CREATE %1 TABLE tags%2 (" "%3" "url VARCHAR(120)," "dir VARCHAR(100)," "artist INTEGER," "title VARCHAR(100)," "album INTEGER," "genre INTEGER," "year INTEGER," "length INTEGER," "track NUMBER(4) );" ) .arg( temporary ? "TEMPORARY" : "" ) .arg( temporary ? "_temp" : "" ) .arg( temporary ? "id INTEGER," : "id INTEGER PRIMARY KEY," )); //create album table executeSql( QString( "CREATE %1 TABLE album%2 (" "id INTEGER PRIMARY KEY," "name VARCHAR(100) );" ) .arg( temporary ? "TEMPORARY" : "" ) .arg( temporary ? "_temp" : "" ) ); //create artist table executeSql( QString( "CREATE %1 TABLE artist%2 (" "id INTEGER PRIMARY KEY," "name VARCHAR(100) );" ) .arg( temporary ? "TEMPORARY" : "" ) .arg( temporary ? "_temp" : "" ) ); //create genre table executeSql( QString( "CREATE %1 TABLE genre%2 (" "id INTEGER PRIMARY KEY," "name VARCHAR(100) );" ) .arg( temporary ? "TEMPORARY" : "" ) .arg( temporary ? "_temp" : "" ) ); //create year table executeSql( QString( "CREATE %1 TABLE year%2 (" "id INTEGER PRIMARY KEY," "name VARCHAR(100) );" ) .arg( temporary ? "TEMPORARY" : "" ) .arg( temporary ? "_temp" : "" ) ); //create indexes executeSql( QString( "CREATE INDEX album_idx%1 ON album%2( name );" ) .arg( temporary ? "_temp" : "" ).arg( temporary ? "_temp" : "" ) ); executeSql( QString( "CREATE INDEX artist_idx%1 ON artist%2( name );" ) .arg( temporary ? "_temp" : "" ).arg( temporary ? "_temp" : "" ) ); executeSql( QString( "CREATE INDEX genre_idx%1 ON genre%2( name );" ) .arg( temporary ? "_temp" : "" ).arg( temporary ? "_temp" : "" ) ); executeSql( QString( "CREATE INDEX year_idx%1 ON year%2( name );" ) .arg( temporary ? "_temp" : "" ).arg( temporary ? "_temp" : "" ) ); executeSql( QString( "CREATE INDEX url_idx%1 ON tags%2( url );" ) .arg( temporary ? "_temp" : "" ).arg( temporary ? "_temp" : "" ) ); if ( !temporary ) { executeSql( "CREATE INDEX album_tag ON tags( album );" ); executeSql( "CREATE INDEX artist_tag ON tags( artist );" ); executeSql( "CREATE INDEX genre_tag ON tags( genre );" ); executeSql( "CREATE INDEX year_tag ON tags( year );" ); executeSql( "CREATE INDEX url_tag ON tags( url );" ); // create directory statistics database executeSql( QString( "CREATE TABLE IF NOT EXISTS directories (" "dir VARCHAR(100) UNIQUE," "changedate INTEGER );" ) ); } } void CollectionDB::dropTables( bool temporary ) { qDebug() << Q_FUNC_INFO; executeSql( QString( "DROP TABLE tags%1;" ).arg( temporary ? "_temp" : "" ) ); executeSql( QString( "DROP TABLE album%1;" ).arg( temporary ? "_temp" : "" ) ); executeSql( QString( "DROP TABLE artist%1;" ).arg( temporary ? "_temp" : "" ) ); executeSql( QString( "DROP TABLE genre%1;" ).arg( temporary ? "_temp" : "" ) ); executeSql( QString( "DROP TABLE year%1;" ).arg( temporary ? "_temp" : "" ) ); // force to re-read over all count for random entry p->resultCount=0; } void CollectionDB::moveTempTables() { executeSql( "INSERT INTO tags SELECT * FROM tags_temp;" ); executeSql( "INSERT INTO album SELECT * FROM album_temp;" ); executeSql( "INSERT INTO artist SELECT * FROM artist_temp;" ); executeSql( "INSERT INTO genre SELECT * FROM genre_temp;" ); executeSql( "INSERT INTO year SELECT * FROM year_temp;" ); // Re-create index to be fast as possible executeSql( QString( "REINDEX album_idx;" )); executeSql( QString( "REINDEX artist_idx;" )); executeSql( QString( "REINDEX genre_idx;" )); executeSql( QString( "REINDEX year_idx;" )); executeSql( QString( "REINDEX url_idx;" )); executeSql( QString( "REINDEX album_tag;" )); executeSql( QString( "REINDEX artist_tag;" )); executeSql( QString( "REINDEX genre_tag;" )); executeSql( QString( "REINDEX year_tag;" )); executeSql( QString( "REINDEX url_tag;" )); } void CollectionDB::createStatsTable() { qDebug() << Q_FUNC_INFO; // create music statistics database executeSql( QString( "CREATE TABLE statistics (" "url VARCHAR(120) UNIQUE," "createdate INTEGER," "accessdate INTEGER," "playcounter INTEGER );" ) ); // create music favorites database executeSql( QString( "CREATE TABLE favorites (" "url VARCHAR(120) UNIQUE," "changedate INTEGER," "rate INTEGER );" ) ); // create playlist database executeSql( QString( "CREATE TABLE playlists (" "url VARCHAR(120)," "name VARCHAR(60)," "length INTEGER," "changedate INTEGER," "flags INTEGER," "norder INTEGER," "UNIQUE(url, name) ON CONFLICT REPLACE);" ) ); } void CollectionDB::dropStatsTable() { qDebug() << Q_FUNC_INFO; executeSql( "DROP TABLE statistics;" ); executeSql( "DROP TABLE favorites;" ); executeSql( "DROP TABLE playlists;" ); } void CollectionDB::purgeDirCache() { executeSql( QString( "DELETE FROM directories;") ); } ulong CollectionDB::getValueID( QString name, QString value, bool autocreate, bool useTempTables ) { if ( useTempTables ) name.append( "_temp" ); QString command = QString( "SELECT id FROM %1 WHERE name LIKE '%2';" ) .arg( name ) .arg( escapeString( value ) ); long id = selectSqlNumber( command ); //check if item exists. if not, should we autocreate it? if ( id < 0 && autocreate ) { command = QString( "INSERT INTO %1 ( name ) VALUES ( '%2' );" ) .arg( name ) .arg( escapeString( value ) ); executeSql( command ); return p->query->lastInsertId().toInt(); } return id; } QStringList CollectionDB::getRandomEntry(QString path, QString genre, QString artist) { // retrieve Max_Count if ( genre != p->lastGenre || artist != p->lastArtist || path != p->lastPath || p->resultCount == 0 ) { //new filter > get new count p->lastGenre = genre; p->lastArtist = artist; p->lastPath = path; p->resultCount = getCount(path, genre, artist); } if (p->resultCount >0 ) { long randomID = (qrand() % p->resultCount); //qebug() << QString::number(randomID); QList entries = selectRandomEntry(QString::number(randomID), path, genre, artist ); if (!entries.isEmpty()) return entries.at(0); else return QStringList(); } else { qDebug() << Q_FUNC_INFO << " No Track found matching filter"; return QStringList(); } } QStringList CollectionDB::getRandomEntry() { double randMax; randMax=RAND_MAX; if (p->filterString != p->lastFilterString || p->resultCount == 0) { //new genre > get new count p->lastFilterString = p->filterString; p->resultCount=getCount(); } long randomID = (qrand() / randMax) * p->resultCount; //qDebug() << QString::number(randomID); QList entries = selectRandomEntry(QString::number(randomID) ); if (!entries.isEmpty()) return entries.at(0); else return QStringList(); } ulong CollectionDB::getCount() { QString command = "SELECT count(distinct tags.url) " + p->sqlFromString + p->sqlQuickFilter; return selectSqlNumber( command ); } QPair CollectionDB::getCount(QStringList paths, QStringList genres, QStringList artists) { QString command = "SELECT count(distinct tags.url), sum(tags.length) FROM tags, artist, genre " " WHERE tags.artist = artist.id " " AND tags.artist = artist.id " " AND tags.genre = genre.id " + p->selectionFilterForRandom(paths, genres, artists) + ";"; QStringList result = selectSql(command).at(0); QPair pair; pair.first = result[0].toInt(); pair.second = result[1].toInt(); return pair; } uint CollectionDB::getCount(QString path, QString genre, QString artist) { QString command = "SELECT count(distinct tags.url), sum(tags.length) FROM tags, artist, genre " " WHERE tags.artist = artist.id " " AND tags.artist = artist.id " " AND tags.genre = genre.id " + p->selectionFilterForRandom(path, genre, artist) + ";"; QStringList result = selectSql(command).at(0); p->resultLength = result[1].toLong(); return result[0].toLong(); } long CollectionDB::lastLengthSum() { return p->resultLength; } uint CollectionDB::lastMaxCount() { return p->resultCount; } QList CollectionDB::selectRandomEntry( QString rownum, QString path, QString genre, QString artist) { QString command = "SELECT tags.url, artist.name, tags.title, album.name, year.name, genre.name, tags.track, tags.length, statistics.playcounter, favorites.rate " + p->sqlFromString + p->sqlQuickFilter + p->selectionFilterForRandom(path, genre, artist) + " LIMIT 1 OFFSET " + rownum +";"; return selectSql(command); } QList CollectionDB::selectYears() { QString command = "SELECT DISTINCT year.name " + p->sqlFromString + p->sqlQuickFilter + "AND year.name <> '' " "ORDER BY year.name DESC;"; return selectSql(command); } QList CollectionDB::selectGenres() { QString command = "SELECT DISTINCT genre.name " + p->sqlFromString + p->sqlQuickFilter + "AND genre.name <> '' " "ORDER BY genre.name;"; return selectSql(command); } QList CollectionDB::selectArtists(QString year, QString genre) { QString command = "SELECT DISTINCT artist.name " + p->sqlFromString + p->sqlQuickFilter + p->selectionFilter(year,genre) + "AND artist.name <> '' " "ORDER BY artist.name;"; return selectSql(command); } QList CollectionDB::selectAlbums(QString year, QString genre, QString artist) { QString command = "SELECT DISTINCT album.name " + p->sqlFromString + p->sqlQuickFilter + p->selectionFilter(year,genre,artist) + "AND album.name <> '' " "ORDER BY album.name;"; return selectSql(command); } QList CollectionDB::selectTracks(QString year, QString genre, QString artist, QString album) { QString command = "SELECT DISTINCT tags.url, artist.name, tags.title, album.name, year.name, genre.name, tags.track, tags.length, statistics.playcounter, favorites.rate " + p->sqlFromString + p->sqlQuickFilter + p->selectionFilter(year,genre,artist,album) + "ORDER BY artist.name DESC, album.name DESC, tags.track;"; return selectSql(command); } QList CollectionDB::selectHotTracks() { QString command = "SELECT DISTINCT tags.url, artist.name, tags.title, album.name, year.name, genre.name, tags.track, tags.length, statistics.playcounter, favorites.rate " + p->sqlFromString + "AND statistics.playcounter>0 " "ORDER BY statistics.playcounter DESC " "LIMIT 20 OFFSET 0;"; return selectSql(command); } QList CollectionDB::selectLastTracks() { QString command = "SELECT DISTINCT tags.url, artist.name, tags.title, album.name, year.name, genre.name, tags.track, tags.length, statistics.playcounter, favorites.rate " + p->sqlFromString + "AND statistics.playcounter>0 " "ORDER BY statistics.accessdate DESC " "LIMIT 20 OFFSET 0;"; return selectSql(command); } QList CollectionDB::selectFavoritesTracks() { QString command = "SELECT DISTINCT tags.url, artist.name, tags.title, album.name, year.name, genre.name, tags.track, tags.length, statistics.playcounter, favorites.rate " + p->sqlFromString + "AND favorites.rate>0 " "ORDER BY favorites.rate DESC "; return selectSql(command); } QList CollectionDB::selectPlaylistData() { QString command = "SELECT name, COUNT(name), SUM(length), changedate " "from playlists " "WHERE name <> 'defaultKnowthelist' " "GROUP BY name, changedate " "ORDER BY changedate DESC;"; return selectSql(command); } QList CollectionDB::selectPlaylistTracks(QString name) { QString command = "SELECT tags.url, artist.name, tags.title, album.name, year.name, genre.name, tags.track, tags.length, statistics.playcounter, favorites.rate, playlists.flags " + p->sqlFromStringPL + "AND playlists.name ='" + escapeString(name) + "' " "ORDER BY playlists.norder"; return selectSql(command); } knowthelist-2.3.0/src/stackdisplay.cpp0000775000175000017500000000547512423536022017074 0ustar mariomario/* Copyright (C) 2014 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #include "stackdisplay.h" #include #include #include class StackDisplayPrivate { public: int height; int width; int margin; int count; int indexSelected; int barHeight; QColor colorBars; }; StackDisplay::StackDisplay(QWidget *parent) : QWidget(parent) { p = new StackDisplayPrivate; p->colorBars.setRgb ( 200,200,200 ); p->count = 6; p->indexSelected = 1; p->barHeight = 3; p->margin = 8; } StackDisplay::~StackDisplay() { delete p; } void StackDisplay::resizeEvent( QResizeEvent* e ) { Q_UNUSED(e); p->width = width(); p->height = height(); } void StackDisplay::setBarColor ( QColor color ) { p->colorBars = color; update(); } void StackDisplay::setCount ( int value ) { p->count = value; update(); } void StackDisplay::setSelected( int value ) { p->indexSelected = value; update(); } void StackDisplay::setMargin( int value) { p->margin = value; } void StackDisplay::paintEvent(QPaintEvent *) { drawBars(); QStyleOption opt; opt.init(this); QPainter p(this); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); } void StackDisplay::drawBars() { QPainter painter(this); painter.setPen ( p->colorBars ); if (p->count==0) return; int space = (int)(p->height/p->count); int posY = 0; for ( int i=0;icount;i++ ) { posY = posY + space; for ( int j=0;jbarHeight;j++ ) { //draw bars painter.drawLine (p->margin*2, posY+j-p->barHeight, p->width-p->margin, posY+j-p->barHeight); } if (i==p->indexSelected){ //draw triancle for ( int j=p->margin;jmargin+5;j++ ) { painter.drawLine (j, posY-(p->margin+5-j)+1-p->barHeight, j, posY+(p->margin+5-j)-1-p->barHeight); } } } } knowthelist-2.3.0/src/collectionsetupmodel.h0000775000175000017500000000266312423536022020277 0ustar mariomario/* Copyright (C) 2005-2014 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #ifndef COLLECTIONSETUPMODEL_H #define COLLECTIONSETUPMODEL_H #include #include class CollectionSetupModel : public QDirModel { Q_OBJECT public: CollectionSetupModel(); QStringList dirsChecked(); void setDirsChecked(QStringList list); private: QSet checked; QSet checkedPartially; virtual Qt::ItemFlags flags(const QModelIndex& index) const; virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const; bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole); }; #endif // COLLECTIONSETUPMODEL_H knowthelist-2.3.0/src/modeselector.cpp0000664000175000017500000000570412423536022017056 0ustar mariomario/* Copyright (C) 2014 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #include "modeselector.h" #include "ui_modeselector.h" ModeSelector::ModeSelector(QWidget *parent) : QFrame(parent), ui(new Ui::ModeSelector) { ui->setupUi(this); ui->led1->setLook(QLed::Flat); ui->led1->setShape(QLed::Rectangular); ui->led1->setColor(QColor(35,119,246)); ui->led2->setLook(QLed::Flat); ui->led2->setShape(QLed::Rectangular); ui->led2->setColor(QColor(35,119,246)); ui->led3->setLook(QLed::Flat); ui->led3->setShape(QLed::Rectangular); ui->led3->setColor(QColor(35,119,246)); ui->led2->off(); ui->led3->off(); selMode = ModeSelector::MODENONE; } ModeSelector::~ModeSelector() { delete ui; } void ModeSelector::on_push1_clicked() { //ui->led1->on(); //ui->led2->off(); //ui->led3->off(); selMode = ModeSelector::MODENONE; ui->push1->setStyleSheet("QPushButton { border: 1px solid #3399ff;}"); ui->push2->setStyleSheet("QPushButton { border: 1px solid #aaaaaa;}"); ui->push3->setStyleSheet("QPushButton { border: 1px solid #aaaaaa;}"); Q_EMIT modeChanged(selMode); } void ModeSelector::on_push2_clicked() { //ui->led1->off(); //ui->led2->on(); //ui->led3->off(); selMode = ModeSelector::MODEYEAR; ui->push1->setStyleSheet("QPushButton { border: 1px solid #aaaaaa;}"); ui->push2->setStyleSheet("QPushButton { border: 1px solid #3399ff;}"); ui->push3->setStyleSheet("QPushButton { border: 1px solid #aaaaaa;}"); Q_EMIT modeChanged(selMode); } void ModeSelector::on_push3_clicked() { //ui->led1->off(); //ui->led2->off(); //ui->led3->on(); selMode = ModeSelector::MODEGENRE; ui->push1->setStyleSheet("QPushButton { border: 1px solid #aaaaaa;}"); ui->push2->setStyleSheet("QPushButton { border: 1px solid #aaaaaa;}"); ui->push3->setStyleSheet("QPushButton { border: 1px solid #3399ff;}"); Q_EMIT modeChanged(selMode); } void ModeSelector::setMode(ModeSelector::modeType value) { switch (value) { case MODEGENRE: on_push3_clicked(); break; case MODEYEAR: on_push2_clicked(); break; default: on_push1_clicked(); break; } } ModeSelector::modeType ModeSelector::mode() { return selMode; } knowthelist-2.3.0/src/djbrowser.h0000664000175000017500000000242212423536022016031 0ustar mariomario/* Copyright (C) 2005-2014 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #ifndef DJBROWSER_H #define DJBROWSER_H #include "dj.h" #include #include class DjBrowser : public QWidget { Q_OBJECT public: explicit DjBrowser(QWidget *parent = 0); ~DjBrowser(); void updateList(); void saveSettings(); signals: void selectionChanged(Dj*); void selectionStarted(); public slots: void addDj(); void loadDj(); void removeDj(); void startDj(); void addFilter(); void removeFilter(); private: class DjBrowserPrivate *p; }; #endif // DJBROWSER_H knowthelist-2.3.0/src/playerwidget.h0000775000175000017500000000717512423536022016545 0ustar mariomario/* Copyright (C) 2005-2014 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #ifndef PLAYERWIDGET_H #define PLAYERWIDGET_H #include #include #include #include #include #include #include "player.h" #include "vumeter.h" #include "playlistitem.h" #include "trackanalyser.h" namespace Ui { class PlayerWidget; } class PlayerWidget : public QWidget { Q_OBJECT public: explicit PlayerWidget(QWidget *parent = 0); ~PlayerWidget(); enum EqBand { EQ_Low = 0, EQ_Mid = 1, EQ_High = 2 }; float currentLevelLeft(); float currentLevelRight(); void loadFile(QUrl); void play(); void stop(); void pause(); bool isStarted(){ return m_isStarted;} void setTrackFinishEmitTime( const int sec ); int TrackFinishEmitTime() { return mTrackFinishEmitTime;} void setVolume(double volume); void setGain(double gain); void setSkipSilentEnd(bool checked) {m_skipSilentEnd=checked; setPositionMarkers();} void setSkipSilentBegin(bool checked) {m_skipSilentBegin=checked; setPositionMarkers();} public Q_SLOTS: void loadTrack( Track* ); void analyseFinished(); void setEqualizer(EqBand, int); void setInfo(QPair info); Q_SIGNALS: void trackFinished(); void aboutFinished(); void trackDropped( Track* ); void trackPlayed( Track* ); void forwardPressed(); void rewindPressed(); void statusChanged(bool); void gainChanged(double); void levelChanged(double, double); private Q_SLOTS: void on_butCue_clicked(); void on_sliPosition_actionTriggered(int action); void updateTimeAndPositionDisplay(bool isPassive=true); void playerFinished(); void playerError(); void playerLoaded(); void timerLevel_timeOut(); void timerPosition_timeOut(); void on_sliPosition_sliderMoved(int); void on_butPlay_clicked(); void on_butRew_clicked(); void on_butFwd_clicked(); protected: //void mouseMoveEvent(QMouseEvent *event); VUMeter* vuMeter; long songTime; private: //ToDo: move privates to struct Private Ui::PlayerWidget *ui; QToolButton *initButton(QStyle::StandardPixmap icon, const QString & tip, QObject *dstobj, const char *slot_method, QLayout *layout); void createUI(QBoxLayout *appLayout); void resizeEvent( QResizeEvent* e ); void drawTitle(); Player *player; TrackAnalyser *trackanalyser; float m_level; QLabel *m_positionLabel; QLabel *m_volumeLabel; QTimer* timerLevel; QTimer* timerPosition; void dropEvent( QDropEvent* ); void dragEnterEvent(QDragEnterEvent*); void setPositionMarkers(); int mTrackFinishEmitTime; Track* m_CurrentTrack; long remainCueTime; bool m_isStarted; bool m_isHanging; bool m_skipSilentEnd; bool m_skipSilentBegin; struct PlayerWidgetPrivate *p; }; #endif // PLAYERWIDGET_H knowthelist-2.3.0/src/knowthelist.h0000775000175000017500000001041612423536022016410 0ustar mariomario/* Copyright (C) 2005-2014 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #ifndef KNOWTHELIST_H #define KNOWTHELIST_H #include "playerwidget.h" #include "vumeter.h" #include "qvumeter.h" #include "playlist.h" #include "collectionwidget.h" #include "monitorplayer.h" #include "djsession.h" #include "djbrowser.h" #include "filebrowser.h" #include "playlistbrowser.h" #include "settingsdialog.h" #include #include namespace Ui { class Knowthelist; } class Knowthelist : public QMainWindow { Q_OBJECT public: explicit Knowthelist(QWidget *parent = 0); ~Knowthelist(); private Q_SLOTS: //Auto connect slots void on_potHigh_1_valueChanged(int value); void on_potMid_1_valueChanged(int value); void on_potLow_1_valueChanged(int value); void on_potHigh_2_valueChanged(int value); void on_potMid_2_valueChanged(int value); void on_potLow_2_valueChanged(int value); void on_toggleAutoFade_toggled(bool checked); void on_toggleAutoDJ_toggled(bool checked); void on_toggleAGC_toggled(bool checked); void on_potGain_2_valueChanged(int value); void on_potGain_1_valueChanged(int value); void on_sliMonitor_sliderMoved(int position); void on_cmdMonitorPlay_clicked(); void on_cmdMonitorStop_clicked(); void on_cmdFade_clicked(); void timerMonitor_timeOut(); void timerAutoFader_timerOut(); void player_aboutTrackFinished(); void player1_gainChanged(double newGain); void player2_gainChanged(double gainValue); void player1_trackFinished(); void player2_trackFinished(); void player1_levelChanged(double left, double right); void player2_levelChanged(double left, double right); void slider1_valueChanged(int); void slider2_valueChanged(int); void sliFader_valueChanged(int); void savePlaylists(); void monitorPlayer_trackTimeChanged(qint64, qint64); void timerMonitor_loadFinished(); void startAutoDj(); void timerGain1_timeOut(); void timerGain2_timeOut(); void Track_doubleClicked( Track* ); void trackList_wantLoad(Track*,QString target); void Track_selectionChanged(Track*); bool initMonitorPlayer(); void editSettings(); void on_cmdOptions_clicked(); void showCollectionSetup(); void onWantLoad(QList,QString); void on_lblSoundcard_linkActivated(const QString &link); void on_sliMonitor_actionTriggered(int action); void on_sliMonitorVolume_valueChanged(int value); private: Ui::Knowthelist *ui; void createUI(); void fadeNow(); void setFaderModeToPlayer(); QTimer* timerAutoFader; int m_xfadeDir; int gain1Target; int gain2Target; bool isFading; QVUMeter* vuMeter1; QVUMeter* vuMeter2; QTimer* timerMeter; QTimer* timerMonitor; QTimer* timerGain1; QTimer* timerGain2; Playlist* playList1; Playlist* playList2; Playlist* trackList; Playlist* trackList2; QSplitter* splitter; QSplitter* splitterPlaylist; CollectionWidget* collectionBrowser; MonitorPlayer* monitorPlayer; DjSession* djSession; DjBrowser* djBrowser; PlayerWidget* player1; PlayerWidget* player2; FileBrowser* filetree; PlaylistBrowser* playlistBrowser; SettingsDialog *preferences; bool autoFadeOn; QString m_AutoDJGenre; int mAutofadeLength; int mAboutFinishTime; int mMinTracks; bool wantSeek; Track* m_MonitorTrack; protected: virtual void closeEvent(QCloseEvent*); void changeVolumes(); void loadStartSettings(); void loadCurrentSettings(); }; #endif // KNOWTHELIST_H knowthelist-2.3.0/src/knowthelist.cpp0000775000175000017500000007536112423536022016755 0ustar mariomario/* Copyright (C) 2005-2014 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #include "knowthelist.h" #include "ui_knowthelist.h" #include "playerwidget.h" #include "playlistbrowser.h" #include "qled.h" #include "dj.h" #include "djwidget.h" #include "djfilterwidget.h" #include #include #if QT_VERSION >= 0x050000 #include #else #include #endif #include Knowthelist::Knowthelist(QWidget *parent) : QMainWindow(parent), ui(new Ui::Knowthelist), monitorPlayer(0) { ui->setupUi(this); //create the UI createUI(); } Knowthelist::~Knowthelist() { player1->stop(); delete player1; player1 = 0; delete playList1; player2->stop(); delete player2; player2 = 0; delete playList2; delete vuMeter1; delete vuMeter2; delete monitorPlayer; delete djSession; djSession=0; monitorPlayer=0; delete trackList; trackList=0; delete collectionBrowser; delete ui; qDebug() << "The end" << Q_FUNC_INFO ; } void Knowthelist::createUI() { //hide place holders ui->phVU1->setVisible(false); ui->phVU2->setVisible(false); ui->slider1->setMinimum(0.0); ui->slider2->setMinimum(0.0); ui->slider1->setMaximum(100.0); ui->slider2->setMaximum(100.0); connect(ui->slider1,SIGNAL(valueChanged(int)),this,SLOT(slider1_valueChanged(int))); connect(ui->slider2,SIGNAL(valueChanged(int)),this,SLOT(slider2_valueChanged(int))); connect(ui->sliFader,SIGNAL(valueChanged(int)),this,SLOT(sliFader_valueChanged(int))); //Add player player1 = ui->player_L; player2 = ui->player_R; timerAutoFader = new QTimer(this); connect( timerAutoFader, SIGNAL(timeout()), SLOT(timerAutoFader_timerOut()) ); vuMeter1 = new QVUMeter(ui->frameMixer); vuMeter2 = new QVUMeter(ui->frameMixer); vuMeter1->setGeometry(ui->phVU1->geometry()); vuMeter2->setGeometry( ui->phVU2->geometry()); timerMonitor = new QTimer(this); timerMonitor->setInterval(50); connect( timerMonitor, SIGNAL(timeout()), SLOT(timerMonitor_timeOut()) ); timerGain1 = new QTimer(this); timerGain2 = new QTimer(this); timerGain1->setInterval(100); timerGain2->setInterval(100); connect( timerGain1, SIGNAL(timeout()), SLOT(timerGain1_timeOut()) ); connect( timerGain2, SIGNAL(timeout()), SLOT(timerGain2_timeOut()) ); qRegisterMetaType > ("QList"); //Add DJ djSession = new DjSession(); playList1=ui->playlist_L; playList1->setIsCurrentList(true); playList2 = ui->playlist_R; playList2->setIsCurrentList(false); connect( playList1, SIGNAL(currentTrackChanged(Track*)),player1,SLOT(loadTrack(Track*))); connect( playList2, SIGNAL(currentTrackChanged(Track*)),player2,SLOT(loadTrack(Track*))); connect( player1, SIGNAL(forwardPressed()),playList1,SLOT( skipForward())); connect( player2, SIGNAL(forwardPressed()),playList2,SLOT( skipForward())); connect( player1, SIGNAL(rewindPressed()),playList1,SLOT(skipRewind())); connect( player2, SIGNAL(rewindPressed()),playList2,SLOT(skipRewind())); connect( player1, SIGNAL(aboutFinished()),SLOT( player_aboutTrackFinished())); connect( player2, SIGNAL(aboutFinished()),SLOT( player_aboutTrackFinished())); connect( player1, SIGNAL(gainChanged(double)),SLOT( player1_gainChanged(double))); connect( player2, SIGNAL(gainChanged(double)),SLOT( player2_gainChanged(double))); connect( player1, SIGNAL(levelChanged(double,double)),SLOT( player1_levelChanged(double,double))); connect( player2, SIGNAL(levelChanged(double,double)),SLOT( player2_levelChanged(double,double))); //ToDo: try to avoid this connect( player1, SIGNAL(statusChanged( bool )),playList1,SLOT(setPlaying( bool ))); connect( player2, SIGNAL(statusChanged( bool )),playList2,SLOT(setPlaying( bool ))); connect( player1, SIGNAL(trackFinished()),SLOT( player1_trackFinished())); connect( player2, SIGNAL(trackFinished()),SLOT( player2_trackFinished())); connect( player1, SIGNAL(trackPlayed(Track*)),djSession, SLOT(onTrackFinished(Track*))); connect( player2, SIGNAL(trackPlayed(Track*)),djSession, SLOT(onTrackFinished(Track*))); connect( player1, SIGNAL(trackDropped( Track* )),playList1,SLOT(addCurrentTrack(Track*))); connect( player2, SIGNAL(trackDropped( Track* )),playList2,SLOT(addCurrentTrack(Track*))); //alternateMax connect( playList1, SIGNAL(countChanged(int)),playList2, SLOT(setAlternateMax(int))); connect( playList2, SIGNAL(countChanged(int)),playList1, SLOT(setAlternateMax(int))); connect( playList1, SIGNAL(countChanged(QList)),djSession, SLOT(onTracksChanged_Playlist1(QList))); connect( playList2, SIGNAL(countChanged(QList)),djSession, SLOT(onTracksChanged_Playlist2(QList))); connect( djSession, SIGNAL(foundTracks_Playlist1(QList)),playList1, SLOT(appendTracks(QList))); connect( djSession, SIGNAL(foundTracks_Playlist2(QList)),playList2, SLOT(appendTracks(QList))); connect( djSession, SIGNAL(changed_Playlist1(QPair)),player1,SLOT(setInfo(QPair))); connect( djSession, SIGNAL(changed_Playlist2(QPair)),player2,SLOT(setInfo(QPair))); //Add Tracklist for Collection trackList = new Playlist(); trackList->setObjectName("tracklist"); trackList->setAcceptDrops( false ); trackList->setPlaylistMode(Playlist::Tracklist); collectionBrowser=new CollectionWidget(this); splitter= new QSplitter(); splitter->addWidget(this->collectionBrowser); splitter->addWidget(trackList); QPixmap pixmap1(":database.png"); ui->sideTab->AddTab(splitter,QIcon(pixmap1),tr("Collection")); connect( collectionBrowser, SIGNAL(selectionChanged(QList)),trackList,SLOT(changeTracks(QList))); connect( collectionBrowser,SIGNAL(setupDirs()),this,SLOT(showCollectionSetup())); connect( collectionBrowser,SIGNAL(wantLoad(QList,QString)),this,SLOT(onWantLoad(QList,QString))); connect( trackList, SIGNAL(wantSearch( QString )),collectionBrowser,SLOT(setFilterText(QString))); connect( playList1, SIGNAL(wantSearch( QString )),collectionBrowser,SLOT(setFilterText(QString))); connect( playList2, SIGNAL(wantSearch( QString )),collectionBrowser,SLOT(setFilterText(QString))); connect( trackList, SIGNAL(trackDoubleClicked(Track*)),SLOT(Track_doubleClicked(Track*))); connect( trackList, SIGNAL(wantLoad(Track*,QString)),SLOT(trackList_wantLoad(Track*, QString))); connect( trackList, SIGNAL(trackSelected(Track*)),SLOT(Track_selectionChanged(Track* ))); connect( trackList, SIGNAL(trackPropertyChanged(Track*)),djSession, SLOT(onTrackPropertyChanged(Track* ))); connect( playList1, SIGNAL(trackDoubleClicked(Track*)),SLOT(Track_doubleClicked(Track*))); connect( playList2, SIGNAL(trackDoubleClicked(Track*)),SLOT(Track_doubleClicked(Track*))); connect( playList1, SIGNAL(trackSelected(Track*)),SLOT(Track_selectionChanged(Track* ))); connect( playList2, SIGNAL(trackSelected(Track*)),SLOT(Track_selectionChanged(Track* ))); //AutoFade ui->ledFade->setLook(QLed::Flat); ui->ledFadeRight->setLook(QLed::Flat); ui->ledFadeLeft->setLook(QLed::Flat); ui->ledDJ->setLook(QLed::Flat); ui->ledAGC->setLook(QLed::Flat); ui->ledFadeRight->setShape(QLed::Rectangular); ui->ledFadeLeft->setShape(QLed::Rectangular); ui->ledFade->setShape(QLed::Rectangular); ui->ledDJ->setShape(QLed::Rectangular); ui->ledAGC->setShape(QLed::Rectangular); ui->ledFadeRight->setColor(QColor(35,119,246)); ui->ledFadeLeft->setColor(QColor(35,119,246)); ui->ledFade->setColor(QColor(35,119,246)); ui->ledDJ->setColor(QColor(35,119,246)); ui->ledAGC->setColor(QColor(35,119,246)); ui->ledFade->off(); ui->ledFadeRight->off(); ui->ledFadeLeft->off(); ui->ledAGC->off(); ui->ledDJ->off(); //MonitorPlayer initMonitorPlayer(); //change slider style for linux #if defined(Q_OS_LINUX) QString sliderStyle = QString( "QSlider::sub-page:vertical { background: qlineargradient(x1: 0, y1: 0, x2:1, y2: 0," " stop: 0.4 #666, stop: 0 #111111 ); border: 1px solid #444; border-radius: 2px;}" "QSlider::add-page:vertical {background: qlineargradient(x1: 0, y1: 0, x2:1, y2: 0," " stop: 0 #111,stop: 0.4 #666); border: 1px solid #333; border-radius: 2px;}" "QSlider::sub-page:horizontal,QSlider::add-page:horizontal {" " background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1," " stop: 0 #111, stop: 0.6 #666 ); border: 1px solid #222; border-radius: 2px;}"); ui->frameMixer->setStyleSheet(sliderStyle); ui->MonitorPlayer->setStyleSheet(sliderStyle); #endif //Add the AutoDJ Browser djBrowser = new DjBrowser(); QPixmap pixmap2(":DJ.png"); ui->sideTab->AddTab(djBrowser,QIcon(pixmap2),tr("AutoDJ")); ui->sideTab->setContextMenuPolicy(Qt::NoContextMenu); connect(djBrowser, SIGNAL(selectionChanged(Dj*)),djSession,SLOT(setCurrentDj(Dj*))); connect(djBrowser, SIGNAL(selectionStarted()),this,SLOT(startAutoDj())); //Add the FileBrowser filetree = new FileBrowser(this); QPixmap pixmap3(":folder.png"); ui->sideTab->AddTab(filetree,QIcon(pixmap3),tr("Folder")); //Add PlaylistBrowser playlistBrowser = new PlaylistBrowser(); splitterPlaylist = new QSplitter(); splitterPlaylist->addWidget(playlistBrowser); trackList2 = new Playlist(); trackList2->setObjectName("tracklist2"); trackList2->setAcceptDrops( false ); trackList2->setPlaylistMode(Playlist::Tracklist); connect(playlistBrowser,SIGNAL(selectionChanged(QList)), trackList2, SLOT(changeTracks(QList))); connect(playlistBrowser,SIGNAL(selectionStarted(QList)), djSession, SLOT(forceTracks(QList))); //connect(playlistBrowser,SIGNAL(savePlaylists(QString)),djSession, SLOT(savePlaylists(QString))); connect(playlistBrowser,SIGNAL(storePlaylists(QString)),djSession, SLOT(storePlaylists(QString))); connect(djSession,SIGNAL(savedPlaylists()),playlistBrowser, SLOT(updateLists())); connect( trackList2, SIGNAL(trackDoubleClicked(Track*)),SLOT(Track_doubleClicked(Track*))); connect( trackList2, SIGNAL(wantLoad(Track*,QString)),SLOT(trackList_wantLoad(Track*, QString))); connect( trackList2, SIGNAL(trackSelected(Track*)),SLOT(Track_selectionChanged(Track* ))); connect( trackList2, SIGNAL(trackPropertyChanged(Track*)),djSession, SLOT(onTrackPropertyChanged(Track* ))); splitterPlaylist->addWidget(trackList2); QPixmap pixmap4(":list.png"); ui->sideTab->AddTab(splitterPlaylist,QIcon(pixmap4),tr("Lists")); //Add SettingsDialog preferences = new SettingsDialog(this); connect(preferences,SIGNAL(scanNowPressed()), collectionBrowser,SLOT(scan())); connect(preferences, SIGNAL(resetStatsPressed()), djSession, SLOT(onResetStats())); loadStartSettings(); ui->sideTab->SetCurrentIndex(0); ui->sideTab->SetMode(FancyTabWidget::Mode_LargeSidebar); //Collection ready? if ( !collectionBrowser->hasItems() ) { this->show(); showCollectionSetup(); } } void Knowthelist::loadStartSettings() { QSettings settings; ui->slider1->setValue( settings.value("Volume1","80").toDouble()); ui->slider2->setValue( settings.value("Volume2","80").toDouble()); ui->sliFader->setValue( 70 ); changeVolumes(); splitter->restoreState(settings.value("Splitter").toByteArray()); splitterPlaylist->restoreState(settings.value("SplitterPlaylist").toByteArray()); restoreGeometry(settings.value("mainWindowGeometry").toByteArray()); restoreState(settings.value("mainWindowState").toByteArray()); // Workaround to force correct geometry hide(); show(); if ( settings.value("loadPlaylists","true" )=="true") { djSession->playDefaultList(); // playList1->loadXML( playList1->defaultPlaylistPath() ); // playList2->loadXML( playList2->defaultPlaylistPath() ); } //AutoFade, AGC ... ui->toggleAutoFade->setChecked(settings.value("checkAutoFade",true).toBool()); ui->toggleAGC->setChecked(settings.value("checkAGC",true).toBool()); //EQ values ui->potHigh_1->setValue( settings.value("EQ_gains/High1").toInt() ); ui->potMid_1->setValue( settings.value("EQ_gains/Mid1").toInt() ); ui->potLow_1->setValue( settings.value("EQ_gains/Low1").toInt() ); ui->potHigh_2->setValue( settings.value("EQ_gains/High2").toInt() ); ui->potMid_2->setValue( settings.value("EQ_gains/Mid2").toInt() ); ui->potLow_2->setValue( settings.value("EQ_gains/Low2").toInt() ); loadCurrentSettings(); //now monitorplayer is initialized, restore monitor volume with effect ui->sliMonitorVolume->setValue( settings.value("VolumeMonitor").toDouble()); } void Knowthelist::loadCurrentSettings() { QSettings settings; if (monitorPlayer){ on_cmdMonitorStop_clicked(); //ToDo: get the ID or Name of the default device monitorPlayer->setOutputDevice(settings.value("MonitorOutputDevice").toString()); QString outDev = monitorPlayer->outputDeviceName(); if ( monitorPlayer->outputDeviceID() == monitorPlayer->defaultDeviceID() || outDev.isEmpty()){ ui->lblSoundcard->show(); monitorPlayer->setVolume(0.0); } else { ui->lblSoundcard->hide(); monitorPlayer->setVolume(1.0); } } //Auto DJ Settings djSession->setMinCount(settings.value("minTracks","6").toInt()); djSession->setIsEnabledAutoDJCount(settings.value("isEnabledAutoDJCount",false).toBool()); djBrowser->updateList(); playList1->setAutoClearOn(settings.value("checkAutoRemove",true).toBool()); playList2->setAutoClearOn(settings.value("checkAutoRemove",true).toBool()); playlistBrowser->updateLists(); //Skip Silents Settings player1->setSkipSilentEnd(settings.value("checkSkipSilentEnd",true).toBool()); player1->setSkipSilentBegin(settings.value("checkAutoCue",true).toBool()); player2->setSkipSilentEnd(settings.value("checkSkipSilentEnd",true).toBool()); player2->setSkipSilentBegin(settings.value("checkAutoCue",true).toBool()); //Fader Settings mAutofadeLength=settings.value("faderTimeSlider","12").toInt(); mAboutFinishTime=settings.value("faderEndSlider","12").toInt(); setFaderModeToPlayer(); isFading=false; //CollectionFolders Settings collectionBrowser->loadSettings(); //File Browser Settings filetree->setRootPath(settings.value("editBrowerRoot","").toString()); } void Knowthelist::closeEvent(QCloseEvent* event) { qDebug() << Q_FUNC_INFO << "for Knowthelist" ; QSettings settings; settings.setValue("Volume1", QString("%1").arg( ui->slider1->value() ) ); settings.setValue("Volume2", QString("%1").arg( ui->slider2->value() ) ); settings.setValue("VolumeMonitor", QString("%1").arg( ui->sliMonitorVolume->value() ) ); savePlaylists(); //Save splitter settings.setValue("Splitter",splitter->saveState()); settings.setValue("SplitterPlaylist",splitterPlaylist->saveState()); //Save AutoDJ settings.setValue("isEnabledAutoDJCount",djSession->isEnabledAutoDJCount()); Dj* dj = djSession->currentDj(); QList f = dj->filters(); settings.setValue("currentDjActiveFilter",QString("%1").arg(djSession->currentDj()->activeFilterIdx())); for (int i=0; ipath()); settings.setValue(QString("editAutoDJGenre%1").arg(i),f.at(i)->genre()); settings.setValue(QString("editAutoDJArtist%1").arg(i),f.at(i)->artist()); settings.setValue(QString("editAutoDJValue%1").arg(i),QString("%1").arg(f.at(i)->maxUsage())); } settings.setValue("checkAutoFade", ui->toggleAutoFade->isChecked()); settings.setValue("checkAGC", ui->toggleAGC->isChecked()); settings.setValue("EQ_gains/High1", ui->potHigh_1->value()); settings.setValue("EQ_gains/Mid1", ui->potMid_1->value()); settings.setValue("EQ_gains/Low1", ui->potLow_1->value()); settings.setValue("EQ_gains/High2", ui->potHigh_2->value()); settings.setValue("EQ_gains/Mid2", ui->potMid_2->value()); settings.setValue("EQ_gains/Low2", ui->potLow_2->value()); settings.setValue("mainWindowGeometry", saveGeometry()); settings.setValue("mainWindowState", saveState()); event->accept(); } void Knowthelist::showCollectionSetup() { preferences->setCurrentTab(SettingsDialog::TabCollection); if ( preferences->exec() != QDialog::Rejected ) loadCurrentSettings(); } void Knowthelist::player1_levelChanged(double left, double right) { vuMeter1->setLeftValue( left * 300.0 ); vuMeter1->setRightValue( right * 300.0 ); } void Knowthelist::player2_levelChanged(double left, double right) { vuMeter2->setLeftValue( left * 300.0 ); vuMeter2->setRightValue( right * 300.0 ); } void Knowthelist::player_aboutTrackFinished( ) { if ( ui->toggleAutoFade->isChecked() ) fadeNow(); } void Knowthelist::player1_trackFinished( ) { if ( isFading ) player1->stop(); playList1->skipForward(); } void Knowthelist::player2_trackFinished( ) { if ( isFading ) player2->stop(); playList2->skipForward(); } void Knowthelist::player1_gainChanged(double gainValue) { gain1Target = (int)(gainValue * 100.0); if ( ui->toggleAGC->isChecked()) timerGain1->start(); } void Knowthelist::player2_gainChanged(double gainValue) { gain2Target = (int)(gainValue * 100.0); if ( ui->toggleAGC->isChecked()) timerGain2->start(); } // Move gain1 dial smoothly void Knowthelist::timerGain1_timeOut() { int gain1 = ui->potGain_1->value(); if ( gain1Target > gain1 ) ui->potGain_1->setValue(gain1+1); else if ( gain1Target < gain1 ) ui->potGain_1->setValue(gain1-1); else timerGain1->stop(); } // Move gain2 dial smoothly void Knowthelist::timerGain2_timeOut() { int gain2 = ui->potGain_2->value(); if ( gain2Target > gain2 ) ui->potGain_2->setValue(gain2+1); else if ( gain2Target < gain2 ) ui->potGain_2->setValue(gain2-1); else timerGain2->stop(); } void Knowthelist::fadeNow() { //Fade now! if ( !isFading && (playList1->countTrack()>0 || playList2->countTrack()>0)) { if ( ui->sliFader->value() > 100 ) { m_xfadeDir=-1; if ( ! player1->isStarted() ) player1->play(); //Fader has 200 steps * 5 = 1000ms timerAutoFader->start( mAutofadeLength * 5 ); } else { m_xfadeDir=1; if ( ! player2->isStarted() ) player2->play(); timerAutoFader->start( mAutofadeLength * 5 ); } isFading=true; //ToDo: search for a right time to save savePlaylists(); } } void Knowthelist::changeVolumes() { float v1 = ui->slider1->value()/100.0; float v2 = ui->slider2->value()/100.0; float f1 = 2 - ui->sliFader->value()/100.0; float f2 = ui->sliFader->value()/100.0; f1 = ( f1<1 ) ? f1 : 1; f2 = ( f2<1 ) ? f2 : 1; player1->setVolume( v1 * f1 ); player2->setVolume( v2 * f2 ); } void Knowthelist::slider1_valueChanged(int) { changeVolumes(); } void Knowthelist::slider2_valueChanged(int) { changeVolumes(); } void Knowthelist::sliFader_valueChanged(int) { changeVolumes(); if ( ui->sliFader->value() == ui->sliFader->minimum() ) { playList1->setIsCurrentList(true); playList2->setIsCurrentList(false); } if ( ui->sliFader->value() == ui->sliFader->maximum() ) { playList2->setIsCurrentList(true); playList1->setIsCurrentList(false); } } void Knowthelist::timerAutoFader_timerOut( ) { //Auto-Fader moves ui->sliFader->setValue( ui->sliFader->value() + m_xfadeDir ); //Blinking if ( ui->sliFader->value()%3 == 0 ){ if ( m_xfadeDir < 0 ) ui->ledFadeLeft->toggle(); else ui->ledFadeRight->toggle(); } if ( ui->sliFader->value() <= ui->sliFader->minimum() ) { //Fade from 2 to 1 is done timerAutoFader->stop(); ui->ledFadeLeft->off(); isFading=false; //ToDo:handle AutoDJ from Playlist if ( player2->isStarted() ) { player2->stop(); playList2->skipForward(); } if ( ui->toggleAutoDJ->isChecked() ) djSession->updatePlaylists(); } if ( ui->sliFader->value() >= ui->sliFader->maximum() ) { //Fade from 1 to 2 is done timerAutoFader->stop(); isFading=false; ui->ledFadeRight->off(); //ToDo: handle AutoDJ from Playlist if ( player1->isStarted() ) { player1->stop(); playList1->skipForward(); } if ( ui->toggleAutoDJ->isChecked() ) djSession->updatePlaylists(); } changeVolumes(); } void Knowthelist::savePlaylists() { djSession->storePlaylists("defaultKnowthelist",true); // playList1->saveXML( playList1->defaultPlaylistPath() ); // playList2->saveXML( playList2->defaultPlaylistPath() ); } void Knowthelist::Track_selectionChanged( Track* track ) { if ( track ){ m_MonitorTrack = track; ui->lblMonitorArtist->setText( track->prettyArtist(20) ); ui->lblMonitorTrack->setText( track->prettyTitle(60) ); wantSeek=false; if ( monitorPlayer ) { on_cmdMonitorStop_clicked(); monitorPlayer->open(track->url() ); QPixmap pix = QPixmap::fromImage(track->coverImage()); if (!pix.isNull()) ui->pixMonitorCover->setPixmap(pix); timerMonitor_timeOut(); } } else{ ui->lblMonitorTrack->setText(""); ui->pixMonitorCover->setPixmap(QPixmap()); } } void Knowthelist::timerMonitor_loadFinished() { timerMonitor_timeOut(); if (wantSeek) { on_sliMonitor_sliderMoved(100); } } void Knowthelist::Track_doubleClicked(Track* track) { Track_selectionChanged(track ); if ( monitorPlayer ) { wantSeek=true; on_cmdMonitorPlay_clicked(); } } void Knowthelist::trackList_wantLoad(Track* track, QString target) { //ToDo: enable for multiple tracks like drag/drop qDebug() << Q_FUNC_INFO << "target=" << target; if ( target == "Right" ) playList2->appendSong( new Track(track->tagList()) ); else if ( target == "Left" ) playList1->appendSong( new Track(track->tagList()) ); } //ToDo: find a better name void Knowthelist::onWantLoad(QList trackList, QString target) { if ( target == "Right" ) playList2->appendTracks(trackList); else if ( target == "Left" ) playList1->appendTracks(trackList); } void Knowthelist::setFaderModeToPlayer() { if ( autoFadeOn ) { player1->setTrackFinishEmitTime( mAboutFinishTime ); player2->setTrackFinishEmitTime( mAboutFinishTime ); playList1->setPlaylistMode(Playlist::Playlist_Multi); playList2->setPlaylistMode(Playlist::Playlist_Multi); } else { player1->setTrackFinishEmitTime( 0 ); player2->setTrackFinishEmitTime( 0 ); playList1->setPlaylistMode(Playlist::Playlist_Single); playList2->setPlaylistMode(Playlist::Playlist_Single); } } void Knowthelist::editSettings() { // update hardware infos monitorPlayer->readDevices(); QSettings settings; settings.setValue("MonitorOutputDevices", monitorPlayer->outputDevices()); if ( preferences->exec() != QDialog::Rejected ) loadCurrentSettings(); } void Knowthelist::on_cmdFade_clicked() { fadeNow(); } bool Knowthelist::initMonitorPlayer() { //ToDo: spend a separate widget for Monitor player qDebug() << Q_FUNC_INFO << "BEGIN "; monitorPlayer= new MonitorPlayer(this); monitorPlayer->prepare(); monitorPlayer->setObjectName("monitorPlayer"); ui->cmdMonitorStop->setIcon(QIcon(":stop.png")); ui->cmdMonitorPlay->setIcon(QIcon(":play.png")); connect(monitorPlayer,SIGNAL(loadFinished()),this,SLOT(timerMonitor_loadFinished())); qDebug() << Q_FUNC_INFO << "END " ; return true; } void Knowthelist::startAutoDj() { ui->toggleAutoDJ->setChecked(true); } void Knowthelist::on_cmdMonitorStop_clicked() { monitorPlayer->stop(); timerMonitor->stop(); ui->cmdMonitorPlay->setIcon(QIcon(":play.png")); //ui->monitorMeter->reset(); ui->monitorMeter->setRightValue(0); ui->monitorMeter->setLeftValue(0); } void Knowthelist::on_cmdMonitorPlay_clicked() { if (monitorPlayer->isPlaying()) { ui->cmdMonitorPlay->setIcon(QIcon(":play.png")); monitorPlayer->pause(); timerMonitor->stop(); //ui->monitorMeter->reset(); ui->monitorMeter->setRightValue(0); ui->monitorMeter->setLeftValue(0); } else { ui->cmdMonitorPlay->setIcon(QIcon(":pause.png")); monitorPlayer->play(); timerMonitor->start(); } } void Knowthelist::monitorPlayer_trackTimeChanged(qint64 time, qint64 totalTime) { //ToDo: delete this function: Why? if ( ui->sliMonitor->maximum() !=totalTime ) { if (totalTime==0) ui->sliMonitor->setMaximum(100); else ui->sliMonitor->setMaximum(totalTime); } ui->sliMonitor->setValue(time); QTime displayTime(0, (time / 60000) % 60, (time / 1000) % 60); QTime displayTotalTime(0, (totalTime / 60000) % 60, (totalTime / 1000) % 60); ui->lblMonitorPosition->setText(displayTime.toString("mm:ss")); ui->lblMonitorLength->setText(displayTotalTime.toString("mm:ss")); } void Knowthelist::timerMonitor_timeOut() { QTime length = monitorPlayer->length(); QTime curpos = monitorPlayer->position(); QTime remain(0,0); long remainMs; //Some tracks deliver no length in state pause if ( length == QTime(0,0) ) length = QTime(0,0,0).addSecs(m_MonitorTrack->length()); remainMs=curpos.msecsTo(length); remain = QTime(0,0).addMSecs(remainMs); ui->lblMonitorPosition->setText(curpos.toString("mm:ss.zzz").left(7)); ui->lblMonitorLength->setText(length.toString("mm:ss")); //update position slider if (length != QTime(0,0)) ui->sliMonitor->setValue(curpos.msecsTo(QTime(0,0,0)) * 1000 / length.msecsTo(QTime(0,0,0))); else ui->sliMonitor->setValue(0); ui->monitorMeter->setLeftValue( monitorPlayer->levelLeft() * 100.0 ); ui->monitorMeter->setRightValue( monitorPlayer->levelRight() * 100.0); } void Knowthelist::on_sliMonitor_sliderMoved(int value) { uint length = -monitorPlayer->length().msecsTo(QTime(0,0,0)); //Some tracks deliver no length in state pause if ( length == 0 ) length = m_MonitorTrack->length() * 1000; if (length != 0 && value > 0) { QTime pos = QTime(0,0,0); pos = pos.addMSecs(length * (value / 1000.0)); qDebug()<<"pos:"<setPosition(pos); } } void Knowthelist::on_cmdOptions_clicked() { preferences->setCurrentTab(SettingsDialog::TabFader); editSettings(); } void Knowthelist::on_potGain_1_valueChanged(int value) { player1->setGain(value / 100.0); } void Knowthelist::on_potGain_2_valueChanged(int value) { player2->setGain(value / 100.0); } void Knowthelist::on_toggleAGC_toggled(bool checked) { Q_UNUSED(checked); ui->ledAGC->toggle(); } void Knowthelist::on_toggleAutoDJ_toggled(bool checked) { if ( checked ) { //AutoDJ on //For an empty list if ( playList1->isEmpty() ) playList1->addCurrentTrack(djSession->getRandomTrack()); if ( playList2->isEmpty() ) playList2->addCurrentTrack(djSession->getRandomTrack()); //Fill both playlists djSession->updatePlaylists(); //Start playing if ( !player1->isStarted() && !player2->isStarted() ) fadeNow(); //Activate Autofade ui->toggleAutoFade->setChecked( true ); } else{ m_AutoDJGenre=collectionBrowser->filterText(); } ui->ledDJ->toggle(); } void Knowthelist::on_toggleAutoFade_toggled(bool checked) { ui->ledFade->setState(checked ? QLed::On : QLed::Off); autoFadeOn = checked; setFaderModeToPlayer(); } void Knowthelist::on_potHigh_1_valueChanged(int value) { player1->setEqualizer(PlayerWidget::EQ_High, value); } void Knowthelist::on_potMid_1_valueChanged(int value) { player1->setEqualizer(PlayerWidget::EQ_Mid, value); } void Knowthelist::on_potLow_1_valueChanged(int value) { player1->setEqualizer(PlayerWidget::EQ_Low, value); } void Knowthelist::on_potHigh_2_valueChanged(int value) { player2->setEqualizer(PlayerWidget::EQ_High, value); } void Knowthelist::on_potMid_2_valueChanged(int value) { player2->setEqualizer(PlayerWidget::EQ_Mid, value); } void Knowthelist::on_potLow_2_valueChanged(int value) { player2->setEqualizer(PlayerWidget::EQ_Low, value); } void Knowthelist::on_lblSoundcard_linkActivated(const QString &link) { Q_UNUSED(link); preferences->setCurrentTab(SettingsDialog::TabMonitor); editSettings(); } void Knowthelist::on_sliMonitor_actionTriggered(int action) { //a workaround for page moving int posi; switch (action) { case 3: posi=ui->sliMonitor->value()+100; break; case 4: posi=ui->sliMonitor->value()-100; if (posi<100) posi=1; break; case 1: posi=ui->sliMonitor->value()+10; break; case 2: posi=ui->sliMonitor->value()-10; break; default: return; break; } this->on_sliMonitor_sliderMoved(posi); } void Knowthelist::on_sliMonitorVolume_valueChanged(int value) { monitorPlayer->setVolume( value/100.0 ); } knowthelist-2.3.0/src/trackanalyser.h0000775000175000017500000000402512423536022016677 0ustar mariomario/* Copyright (C) 2011 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #ifndef TRACKANALYSER_H #define TRACKANALYSER_H #include #include #define GST_DISABLE_LOADSAVE 1 #define GST_DISABLE_REGISTRY 1 #define GST_DISABLE_DEPRECATED 1 #include class TrackAnalyser : public QWidget { Q_OBJECT public: TrackAnalyser(QWidget *parent = 0); ~TrackAnalyser(); bool prepare(); void open(QUrl url); void start(); bool close(); double gainDB(); double gainFactor(); QTime startPosition(); QTime endPosition(); bool finished() {return m_finished;} QTime length(); static const int GAIN_INVALID=-99; void need_finish(); void newpad (GstElement *decodebin, GstPad *pad, gpointer data); static GstBusSyncReply bus_cb (GstBus *bus, GstMessage *msg, gpointer data); Q_SIGNALS: void finish(); private slots: void messageReceived(GstMessage* message); void loadThreadFinished(); private: struct Private; Private * p; GstElement *pipeline; GstBus *bus; double m_GainDB; QTime m_StartPosition; QTime m_EndPosition; QTime m_MaxPosition; bool m_finished; void cleanup(); void asyncOpen(QUrl url); void sync_set_state(GstElement*, GstState); }; #endif // TRACKANALYSER_H knowthelist-2.3.0/src/dj.cpp0000775000175000017500000001111512423536022014762 0ustar mariomario/* Copyright (C) 2005-2014 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #include "dj.h" #include "filter.h" #include #include #include struct DjPrivate { int rotation; QList filters; Filter* filter; long countTracks; long lengthTracks; QString description; }; Dj::Dj() :p(new DjPrivate) { p->rotation=0; p->filter=0; p->description=QString::null; p->countTracks=0; p->lengthTracks=0; } Dj::~Dj() { delete p; } void Dj::addFilter(Filter* filter) { p->filters.append(filter); connect(filter,SIGNAL(activated()), this,SLOT(on_filter_activated())); connect(filter,SIGNAL(filterChanged()), this,SLOT(on_filter_filterChanged())); connect(filter,SIGNAL(maxUsageChanged()), this,SLOT(on_filter_maxUsageChanged())); } void Dj::removeFilter(Filter* filter) { p->filters.removeOne(filter); } QList Dj::filters() { return p->filters; } void Dj::setActiveFilterIdx(int idx) { p->rotation = idx; if ( p->rotation >= p->filters.count() ) p->rotation = 0; p->filters[p->rotation]->setActive(true); } int Dj::activeFilterIdx() { return p->rotation; } void Dj::on_filter_filterChanged() { //qDebug() << Q_FUNC_INFO ; Filter* f = qobject_cast(QObject::sender()); Q_EMIT filterChanged(f); } void Dj::on_filter_countChanged() { //qDebug() << Q_FUNC_INFO ; //Filter* f = qobject_cast(QObject::sender()); //Q_EMIT countChanged(); } void Dj::on_filter_activated() { Filter* f = qobject_cast(QObject::sender()); QList::iterator i; for (i = p->filters.begin(); i != p->filters.end(); ++i) { if ( (*i) != f ) (*i)->setActive(false); else { p->rotation = p->filters.indexOf((*i)); } } //p->wc.wakeAll(); } void Dj::on_filter_maxUsageChanged() { Filter* f = qobject_cast(QObject::sender()); if ( p->filter == f ) checkSequence(); } void Dj::checkSequence() { qDebug() << Q_FUNC_INFO << "rotation=" << p->rotation << "/" << p->filters.count() << " repeat=" << p->filter->usage() << "/" << p->filter->maxUsage() ; if ( p->filter->usage() >= p->filter->maxUsage() ) { int i = p->filters.count(); do { p->rotation++; i--; if ( p->rotation >= p->filters.count() ) p->rotation = 0; } while (p->filters.at(p->rotation)->maxUsage() == 0 && i>0); p->filters.at(p->rotation)->setActive(true); // setActive goes twice through SIGNAL/SLOT and back here, // therefore a waitcondition is necessary to avoid race condition /*p->mutex.lock(); p->wc.wait(&p->mutex); p->mutex.unlock();*/ } } //ToDo: - Switch LED before add the Track // - Allow 0 filter (skip) // - DJwidget: Playbutton für start Filter* Dj::requestFilter() { p->filter = p->filters.at(p->rotation); p->filter->setUsage(p->filter->usage() +1); checkSequence(); qDebug() << Q_FUNC_INFO << "rotation=" << p->rotation << "/" << p->filters.count() << " repeat=" << p->filter->usage() << "/" << p->filter->maxUsage() ; qDebug() << Q_FUNC_INFO << "return filter=" << p->filters.at(p->rotation)->path() << "/" << p->filters.at(p->rotation)->genre() << "/" << p->filters.at(p->rotation)->artist(); return p->filter; } QString Dj::description() { return p->description; } void Dj::setDescription(QString value) { p->description = value; } int Dj::countTracks() { return p->countTracks; } void Dj::setCountTracks(int value) { p->countTracks = value; Q_EMIT countChanged(); } int Dj::lengthTracks() { return p->lengthTracks; } void Dj::setLengthTracks(int value) { p->lengthTracks = value; } knowthelist-2.3.0/src/playlistwidget.h0000664000175000017500000000171012423536022017074 0ustar mariomario#ifndef PLAYLISTWIDGET_H #define PLAYLISTWIDGET_H #include namespace Ui { class PlaylistWidget; } class PlaylistWidget : public QWidget { Q_OBJECT public: explicit PlaylistWidget(QWidget *parent = 0); ~PlaylistWidget(); QString name(); void setName(QString value); QString description(); void setDescription(QString value); void updateView(); void activate(); void deactivate(); void slideCloseWidget(bool open); bool isRemovable(); void setRemovable(bool value); Q_SIGNALS: void activated(); void started(); void deleted(); private: Ui::PlaylistWidget *ui; void mousePressEvent(QMouseEvent* event); void keyPressEvent(QKeyEvent *e); class PlaylistWidgetPrivate *p; private slots: void on_lblName_linkActivated(const QString &link); void on_butPlayWidget_pressed(); void timerSlide_timeOut(); void on_pushClose_clicked(); }; #endif // PLAYLISTWIDGET_H knowthelist-2.3.0/src/settingsdialog.cpp0000775000175000017500000002420012423536022017404 0ustar mariomario/* Copyright (C) 2005-2014 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #include "collectionsetupmodel.h" #include "settingsdialog.h" #include "djsettings.h" #include "ui_settingsdialog.h" #include #include #include #include #include class SettingsDialogPrivate { public: Ui::SettingsDialog ui; QWidget *parent; CollectionSetupModel *model; }; SettingsDialog::SettingsDialog(QWidget * parent) : QDialog(parent) { p = new SettingsDialogPrivate; p->ui.setupUi(this); p->parent=parent; // set icons in the settings list QTableWidgetItem * item; p->ui.settingsGroupsTable->setIconSize(QSize(32,32)); item = p->ui.settingsGroupsTable->item(0, 0); item->setIcon(QIcon(":slider.png")); item->setTextAlignment(Qt::AlignCenter); item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); item = p->ui.settingsGroupsTable->item(1, 0); item->setIcon(QIcon(":database.png")); item->setTextAlignment(Qt::AlignCenter); item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); item = p->ui.settingsGroupsTable->item(2, 0); item->setIcon(QIcon(":volume.png")); item->setTextAlignment(Qt::AlignCenter); item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); item = p->ui.settingsGroupsTable->item(3, 0); item->setIcon(QIcon(":DJ.png")); item->setTextAlignment(Qt::AlignCenter); item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); item = p->ui.settingsGroupsTable->item(4, 0); item->setIcon(QIcon(":list.png")); item->setTextAlignment(Qt::AlignCenter); item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); item = p->ui.settingsGroupsTable->item(5, 0); item->setIcon(QIcon(":folder.png")); item->setTextAlignment(Qt::AlignCenter); item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); item = p->ui.settingsGroupsTable->item(6, 0); item->setIcon(QIcon(":settings.png")); item->setTextAlignment(Qt::AlignCenter); item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); int w = p->ui.settingsGroupsTable->width(); p->ui.settingsGroupsTable->setColumnWidth(0, w); // select first item p->ui.settingsGroupsTable->setCurrentCell(0, 0); // select first page p->ui.pages->setCurrentIndex(0); //Collection folder setup p->model = new CollectionSetupModel(); p->ui.collectionsTreeView->setModel(p->model); p->ui.collectionsTreeView->setColumnHidden(1, true); p->ui.collectionsTreeView->setColumnHidden(2, true); p->ui.collectionsTreeView->setColumnHidden(3, true); p->ui.collectionsTreeView->expandToDepth(0); connect(p->ui.settingsGroupsTable, SIGNAL(itemSelectionChanged()), this, SLOT(tableSelectionChanged())); connect(p->ui.faderEndSlider, SIGNAL(sliderMoved(int)), this, SLOT(on_faderEndSlider_sliderMoved(int))); connect(p->ui.faderTimeSlider, SIGNAL(sliderMoved(int)), this, SLOT(on_faderTimeSlider_sliderMoved(int))); connect(p->ui.pushScanNow,SIGNAL(clicked()),this, SLOT(onScanNow())); connect(p->ui.pushResetStats,SIGNAL(clicked()),this, SIGNAL(resetStatsPressed()) ); connect(p->ui.countDJ,SIGNAL(valueChanged(int)),this,SLOT(loadDjList(int))); } SettingsDialog::~SettingsDialog() { delete p; } void SettingsDialog::setCurrentTab(SettingsDialog::Tab tab) { p->ui.settingsGroupsTable->setCurrentCell(tab, 0); p->ui.pages->setCurrentIndex(tab); } int SettingsDialog::exec() { // load settings if (!loadSettings()) { return QDialog::Rejected; } return QDialog::exec(); } void SettingsDialog::accept() { QSettings settings; settings.setValue("MonitorOutputDevice",p->ui.monitorOutputDevice->currentText()); //Common settings.setValue("language",p->ui.comboLanguage->currentIndex()); //save fade slider settings.setValue("faderTimeSlider",p->ui.faderTimeSlider->value()); settings.setValue("faderEndSlider",p->ui.faderEndSlider->value()); //Playlist settings settings.setValue("checkAutoRemove",p->ui.checkAutoRemove->isChecked()); //Silent settings settings.setValue("checkAutoCue",p->ui.checkAutoCue->isChecked()); settings.setValue("checkSkipSilentEnd",p->ui.checkSkipSilentEnd->isChecked()); //AutoDJ settings.setValue("minTracks",p->ui.minTracks->value()); settings.setValue("countDJ",p->ui.countDJ->value()); settings.setValue("isEnabledAutoDJCount",p->ui.checkAutoDjCountPlayed->isChecked()); settings.beginGroup("AutoDJ"); int maxDj=p->ui.countDJ->value(); for (int d=0;dui.listDjNames->item(d); if (DjSettings *djs = dynamic_cast(p->ui.listDjNames->itemWidget(item))) { settings.setValue("Name", djs->name() ); settings.setValue("FilterCount", djs->filterCount() ); } settings.endGroup(); } settings.endGroup(); //CollectionFolders settings.setValue("Dirs",p->model->dirsChecked()); settings.setValue("Monitor", p->ui.chkMonitor->isChecked() ); //File Browser settings.setValue("editBrowerRoot",p->ui.txtBrowserRoot->text()); QDialog::accept(); } bool SettingsDialog::loadSettings() { QSettings settings; p->ui.monitorOutputDevice->clear(); p->ui.monitorOutputDevice->addItems(settings.value("MonitorOutputDevices").toStringList()); int index = p->ui.monitorOutputDevice->findText(settings.value("MonitorOutputDevice").toString()); p->ui.monitorOutputDevice->setCurrentIndex(index); //Common p->ui.comboLanguage->setCurrentIndex( settings.value("language",0 ).toInt()); //fade slider p->ui.faderTimeSlider->setValue(settings.value("faderTimeSlider","12").toInt()); p->ui.faderTimeLabel->setText(settings.value("faderTimeSlider","12").toString() + "s"); p->ui.faderEndSlider->setValue(settings.value("faderEndSlider","12").toInt()); p->ui.faderEndLabel->setText(settings.value("faderEndSlider","12").toString() + "s"); //Playlist setting p->ui.checkAutoRemove->setChecked(settings.value("checkAutoRemove",true).toBool()); //Silent setting p->ui.checkSkipSilentEnd->setChecked(settings.value("checkSkipSilentEnd",true).toBool()); p->ui.checkAutoCue->setChecked(settings.value("checkAutoCue",true).toBool()); //AutoDJ p->ui.minTracks->setValue(settings.value("minTracks","6").toInt()); p->ui.countDJ->setValue(settings.value("countDJ","3").toInt()); p->ui.checkAutoDjCountPlayed->setChecked(settings.value("isEnabledAutoDJCount",false).toBool()); //CollectionFolders p->model->setDirsChecked(settings.value("Dirs").toStringList()); p->ui.chkMonitor->setChecked(settings.value("Monitor").toBool()); //File Browser p->ui.txtBrowserRoot->setText(settings.value("editBrowerRoot","").toString()); //Load Dj list loadDjList(p->ui.countDJ->value()); return true; } void SettingsDialog::loadDjList(int count) { QSettings settings; QListWidgetItem *itm; DjSettings *djs; p->ui.listDjNames->clear(); settings.beginGroup("AutoDJ"); for (int d=0;dui.listDjNames); p->ui.listDjNames->addItem(itm); djs = new DjSettings(p->ui.listDjNames); djs->setID(d+1); djs->setName(settings.value("Name","Dj%1").toString().arg(d+1)); djs->setFilterCount(settings.value("FilterCount","2").toInt()); p->ui.listDjNames->setItemWidget(itm,djs); settings.endGroup(); } settings.endGroup(); } void SettingsDialog::on_pushButton_clicked() { QFileDialog dialog(this); dialog.setFileMode(QFileDialog::DirectoryOnly); if (dialog.exec()) p->ui.txtBrowserRoot->setText(dialog.selectedFiles().first()); } void SettingsDialog::on_pushAbout_clicked() { QMessageBox msgBox; msgBox.setIconPixmap(QIcon(":knowthelist.png").pixmap(65,65)); msgBox.setText(QString("%1").arg("

Knowthelist

" " Version " + QApplication::applicationVersion() + "
Copyright (C) 2005-2014 Mario Stephan " "
mstephan@shared-files.de" "

" "http://knowthelist.github.io/knowthelist" "

Thanks to :" "
* Heiko Fischer (for testing and new ideas)" "
* David Geiger and Adrien Daugabel (for French translation and issue reports)" "
* Pavel Fric (for Czech translation)" "
* László Farkas (for Hungarian translation)
" )); msgBox.setWindowTitle(tr("About Knowthelist")); msgBox.exec(); } void SettingsDialog::onScanNow() { QSettings settings; settings.setValue("Dirs",p->model->dirsChecked()); Q_EMIT scanNowPressed(); } void SettingsDialog::on_faderEndSlider_sliderMoved(int position) { p->ui.faderEndLabel->setText(QString::number(position)+"s"); } void SettingsDialog::on_faderTimeSlider_sliderMoved(int position) { p->ui.faderTimeLabel->setText(QString::number(position)+"s"); } void SettingsDialog::tableSelectionChanged() { QTableWidgetItem * item = p->ui.settingsGroupsTable->selectedItems().first(); p->ui.pages->setCurrentIndex(item->row()); } knowthelist-2.3.0/src/playerwidget.cpp0000775000175000017500000003237412423536022017077 0ustar mariomario/* Copyright (C) 2011 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #include "playerwidget.h" #include "ui_playerwidget.h" #include "player.h" #include "trackanalyser.h" #include "vumeter.h" #include struct PlayerWidgetPrivate { bool isEndAnnounced; }; PlayerWidget::PlayerWidget(QWidget *parent) : QWidget(parent), ui(new Ui::PlayerWidget), songTime(0), mTrackFinishEmitTime(12000), m_CurrentTrack(0), remainCueTime(0), m_isStarted(false), m_isHanging(false), p(new PlayerWidgetPrivate) { ui->setupUi(this); p->isEndAnnounced = false; //create the player player = new Player(this); player->prepare(); ui->butFwd->setIcon(QIcon(":forward.png")); ui->butRew->setIcon(QIcon(":backward.png")); ui->butPlay->setIcon(QIcon(":play.png")); ui->butPlay->setChecked(false); ui->butFwd->setIconSize(QSize(26, 26)); ui->butRew->setIconSize(QSize(26, 26)); ui->butPlay->setIconSize(QSize(26, 26)); ui->butCue->setChecked(false); vuMeter = ui->vuMeter; vuMeter->setOrientation( Qt::Horizontal ); vuMeter->LevelColorNormal.setRgb( 112,146,190 ); vuMeter->LevelColorHigh.setRgb( 218,59,9 ); vuMeter->LevelColorOff.setRgb( 31,45,65 ); vuMeter->setSpacesBetweenSegments( 1 ); vuMeter->setLinesPerSegment( 2 ); vuMeter->setLinesPerPeak( 2 ); vuMeter->setSpacesInSegments( 1 ); vuMeter->setSpacesInPeak( 1 ); timerLevel = new QTimer(this); connect( timerLevel, SIGNAL(timeout()), SLOT(timerLevel_timeOut()) ); timerPosition = new QTimer(this); connect( timerPosition, SIGNAL(timeout()), SLOT(timerPosition_timeOut()) ); connect(player, SIGNAL(finish()), this, SLOT(playerFinished())); connect(player, SIGNAL(error()), this, SLOT(playerError())); connect(player, SIGNAL(loadFinished()), this, SLOT(playerLoaded())); ui->lblTitle->setText( "" ); ui->lblInfo->setText( "" ); QFont font = ui->lblInfo->font(); QFont fonttime = ui->lblTime->font(); #if defined(Q_OS_DARWIN) int newSize = font.pointSize()-4; fonttime.setPointSize(fonttime.pointSize()+2); #else int newSize = font.pointSize()-1; #endif font.setPointSize(newSize); ui->lblInfo->setFont(font); ui->lblTime->setFont(fonttime); ui->lblTimeRemain->setFont(fonttime); m_isStarted = false; setAcceptDrops( true ); this->stop(); trackanalyser = new TrackAnalyser(this); connect(trackanalyser, SIGNAL(finish()),this,SLOT(analyseFinished())); } PlayerWidget::~PlayerWidget() { delete player; delete timerPosition; delete timerLevel; delete trackanalyser; delete p; } void PlayerWidget::setVolume(double volume) { player->setVolume(volume); } void PlayerWidget::setGain(double gain) { player->setGain(gain); } void PlayerWidget::setInfo(QPair info) { QString strTrack = (info.first > 1) ? tr("Tracks") : tr("Track"); ui->lblInfo->setText(QString("%1 %2 %3 %4") .arg(info.first) .arg(strTrack) .arg(Track::prettyTime( info.second)) .arg(tr("Hours"))); } void PlayerWidget::setEqualizer(EqBand band, int value) { //ranging from -24.0 to +12.0. player->setEqualizer("band"+QString::number(band), value / 10.0); } void PlayerWidget::setPositionMarkers() { if ( trackanalyser->finished()) { if (m_skipSilentEnd){ qDebug() << Q_FUNC_INFO <<"endPosition:"<endPosition(); qDebug() << Q_FUNC_INFO <<"length:"<length(); remainCueTime=trackanalyser->endPosition().msecsTo(trackanalyser->length()); } else remainCueTime = 0; ui->txtCue->setText("-" + QString::number(remainCueTime/1000)); } if ( !m_isStarted && m_skipSilentBegin && trackanalyser->finished()) { player->setPosition(trackanalyser->startPosition()); ui->butCue->setChecked(true); } } void PlayerWidget::play() { m_isStarted = true; if (m_CurrentTrack){ ui->butPlay->setIcon(QIcon(":pause.png")); ui->butPlay->setChecked(true); player->play(); ui->butCue->setChecked(false); timerLevel->start( 50 ); timerPosition->start( 100 ); Q_EMIT statusChanged(m_isStarted); } else m_isHanging=true; } void PlayerWidget::pause() { ui->butPlay->setIcon(QIcon(":play.png")); ui->butPlay->setChecked(false); m_isStarted = false; player->pause(); timerLevel->stop(); timerPosition->stop(); vuMeter->reset(); Q_EMIT statusChanged(m_isStarted); Q_EMIT levelChanged(0,0); } void PlayerWidget::stop() { ui->butPlay->setIcon(QIcon(":play.png")); ui->butPlay->setChecked(false); m_isStarted = false; m_isHanging = false; player->stop(); timerLevel->stop(); timerPosition->stop(); vuMeter->reset(); Q_EMIT statusChanged(m_isStarted); Q_EMIT levelChanged(0,0); } void PlayerWidget::on_butPlay_clicked() { if ( m_isStarted ) { this->pause(); } else { this->play(); } } void PlayerWidget::analyseFinished() { qDebug() << Q_FUNC_INFO <<":"< emit if (trackanalyser->gainDB()!=TrackAnalyser::GAIN_INVALID){ Q_EMIT gainChanged(trackanalyser->gainFactor()); } if ( m_CurrentTrack ){ setPositionMarkers(); updateTimeAndPositionDisplay(); } } void PlayerWidget::timerLevel_timeOut() { vuMeter->setValueLeft(player->levelLeft()); vuMeter->setValueRight(player->levelRight()); Q_EMIT levelChanged(player->levelOutLeft(),player->levelOutRight()); } void PlayerWidget::timerPosition_timeOut() { updateTimeAndPositionDisplay(); } void PlayerWidget::dragEnterEvent(QDragEnterEvent* event) { //ToDo: remove forein classname tracklist" //qDebug() << "PlayerWidget: dragEnterEvent: "<source()->objectName() ; if ( !event->source() ) return; event->setDropAction(Qt::CopyAction); QString sourceSite = event->source()->objectName(); QString dropSite = this->objectName(); if ( sourceSite.left(4) == dropSite.left(4) || sourceSite.left(9) == "tracklist" ) event->accept(); } void PlayerWidget::dropEvent( QDropEvent *event ) { if (event->mimeData()->hasUrls()) { QList urlList = event->mimeData()->urls(); // returns list of QUrls event->ignore(); if ( urlList.size() > 0) // if at least one QUrl is present in list { //load first loadFile(urlList.at(1)); } } else if (event->mimeData()->hasFormat("text/playlistitem")) { //decode playlistitem QByteArray itemData = event->mimeData()->data("text/playlistitem"); QDataStream stream(&itemData, QIODevice::ReadOnly); QVector tags; stream >> tags; event->setDropAction(Qt::MoveAction); event->accept(); //publish dropped Tracks to connected playlist foreach ( QStringList tag, tags) { Track *track = new Track(tag); Q_EMIT trackDropped( track ); } } else event->ignore(); } void PlayerWidget::loadFile( QUrl file) { qDebug() << Q_FUNC_INFO << "url=" << file; loadTrack( new Track(file)); } void PlayerWidget::loadTrack( Track *track) { if ( track ) qDebug() << Q_FUNC_INFO <<":"<lblTitle->setText( player->lastError ); else ui->lblTitle->setText( "no track" ); ui->lblTime->setText("-:-"); ui->lblTimeMs->setText(".-"); ui->lblTimeRemain->setText("-:-"); ui->lblTimeRemainMs->setText(".-"); stop(); } remainCueTime=0; ui->sliPosition->setValue( 0 ); ui->txtCue->setText("?"); ui->butCue->setChecked(false); } void PlayerWidget::resizeEvent( QResizeEvent* e ) { QWidget::resizeEvent(e); drawTitle(); } void PlayerWidget::drawTitle() { int width = ui->lblTitle->width() - 2; if ( width < 300) ui->lblTitle->setStyleSheet("* { font-size: 13pt; }"); else if ( width < 400) ui->lblTitle->setStyleSheet("* { font-size: 14pt; }"); else ui->lblTitle->setStyleSheet("* { font-size: 16pt; }"); QFontMetrics metrix(ui->lblTitle->font()); QString clippedText = tr("No track"); if ( m_CurrentTrack ) clippedText = metrix.elidedText(m_CurrentTrack->prettyTitle(), Qt::ElideRight, width); ui->lblTitle->setText( clippedText ); } float PlayerWidget::currentLevelLeft() { return player->levelOutLeft(); } float PlayerWidget::currentLevelRight() { return player->levelOutRight(); } void PlayerWidget::updateTimeAndPositionDisplay(bool isPassive) { QTime length = player->length(); QTime curpos = player->position(); QTime remain(0,0,0); long remainMs; //Some tracks deliver no length in state pause if ( length == QTime(0,0) ) length = QTime(0,0,0).addSecs(m_CurrentTrack->length()); remainMs=curpos.msecsTo(length); remain = QTime(0,0,0).addMSecs(remainMs); //qDebug()<lblTime->setText(curpos.toString("mm:ss")); ui->lblTimeMs->setText("." + curpos.toString("zzz").left(1)); ui->lblTimeRemain->setText("-" + remain.toString("mm:ss")); ui->lblTimeRemainMs->setText("." + remain.toString("zzz").left(1)); //Signal end of track or media error //ToDo: better recognition of media error (play pressed but player is not running) if ( (remainMs-remainCueTime-mTrackFinishEmitTime <=0 && 0 < remainMs ) || m_isHanging ) { if (!p->isEndAnnounced ) { qDebug() << Q_FUNC_INFO <<":"<isEndAnnounced = true; Q_EMIT aboutFinished(); Q_EMIT trackPlayed(m_CurrentTrack); } } else p->isEndAnnounced = false; //update position slider only if triggerd by timer if (isPassive) { if (length != QTime(0,0,0)) ui->sliPosition->setValue(curpos.msecsTo(QTime(0,0,0)) * 1000 / length.msecsTo(QTime(0,0,0))); else ui->sliPosition->setValue(0); } } void PlayerWidget::playerError() { Q_EMIT trackFinished(); } void PlayerWidget::playerFinished() { Q_EMIT trackFinished(); } void PlayerWidget::playerLoaded() { updateTimeAndPositionDisplay(); } void PlayerWidget::on_butRew_clicked() { if (player->position()setPosition(QTime(0,0,0)); } void PlayerWidget::on_butFwd_clicked() { Q_EMIT forwardPressed(); } void PlayerWidget::setTrackFinishEmitTime( const int sec ) { if ( sec >= 0 && sec < 60 ) mTrackFinishEmitTime = sec*1000; } void PlayerWidget::on_sliPosition_sliderMoved(int value) { uint length = -player->length().msecsTo(QTime(0,0,0)); if (length != 0 && value > 0) { QTime pos = QTime(0, 0, 0); pos = pos.addMSecs(length * (value / 1000.0)); qDebug()<<"pos:"<setPosition(pos); } updateTimeAndPositionDisplay(false); } void PlayerWidget::on_sliPosition_actionTriggered(int action) { //a workaround for page moving int posi; switch (action) { case 3: posi=ui->sliPosition->value()+100; break; case 4: posi=ui->sliPosition->value()-100; if (posi<100) posi=1; break; case 1: posi=ui->sliPosition->value()+10; break; case 2: posi=ui->sliPosition->value()-10; break; default: return; break; } this->on_sliPosition_sliderMoved(posi); ui->butCue->setChecked(false); } void PlayerWidget::on_butCue_clicked() { //ToDo: Visualize skipped silent at start and at the end (color bar) this->pause(); player->setPosition(trackanalyser->startPosition()); updateTimeAndPositionDisplay(); } knowthelist-2.3.0/src/playlistbrowser.cpp0000775000175000017500000003506312423536022017642 0ustar mariomario/* Copyright (C) 2005-2014 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #include "playlistbrowser.h" #include "playlistwidget.h" #include "collectiondb.h" #include "track.h" #include #include #include #include #include class Track; class PlaylistBrowsertPrivate { public: QListWidget* listPlaylists; PlaylistWidget* currentPlaylist; CollectionDB* database; QString directory; }; PlaylistBrowser::PlaylistBrowser(QWidget *parent) : QWidget(parent) { p = new PlaylistBrowsertPrivate; QPushButton* pushSave =new QPushButton(); pushSave->setGeometry(QRect(1,1,60,25)); pushSave->setMaximumWidth(60); pushSave->setMinimumWidth(60); pushSave->setText("+"); QFont pushFont = pushSave->font(); pushFont.setBold(true); pushFont.setPointSize(pushFont.pointSize()+4); pushSave->setFont(pushFont); pushSave->setStyleSheet("QPushButton { border: none; padding-top: -3px; margin-left: 8px;max-height: 20px; margin-right: 28px;}"); pushSave->setToolTip(tr( "Add a new list and store current tracks" )); connect( pushSave,SIGNAL(clicked()),this, SLOT(onPushSave())); QVBoxLayout *mainLayout = new QVBoxLayout; QWidget *headWidget = new QWidget(this); headWidget->setMaximumHeight(35); headWidget->setMinimumHeight(25); QHBoxLayout *headWidgetLayout = new QHBoxLayout; headWidgetLayout->setMargin(0); headWidgetLayout->setSpacing(1); headWidgetLayout->setAlignment(Qt::AlignRight); headWidgetLayout->addWidget(pushSave); headWidget->setLayout(headWidgetLayout); p->listPlaylists = new QListWidget(); p->listPlaylists->setAttribute(Qt::WA_MacShowFocusRect, false); p->database = new CollectionDB(); p->database->executeSql( "PRAGMA synchronous = OFF;" ); updateLists(); headWidget->raise(); mainLayout->addWidget(headWidget); mainLayout->addWidget(p->listPlaylists); mainLayout->setMargin(0); mainLayout->setSpacing(0); setMaximumWidth(400); p->directory = ""; setLayout(mainLayout); } PlaylistBrowser::~PlaylistBrowser() { QSettings settings; //settings.setValue("",p->); delete p; } void PlaylistBrowser::updateLists() { // Read config values QSettings settings; p->directory = settings.value("editPlaylistRoot","").toString(); // Insert dynamic lists PlaylistWidget* list; QListWidgetItem* itm; p->listPlaylists->clear(); //Top Tracks List list = new PlaylistWidget(p->listPlaylists); list->setName(tr("Top Tracks")); list->setObjectName("TopTracks"); list->setDescription(tr("Most played tracks")); list->setRemovable(false); connect(list,SIGNAL(activated()),this,SLOT(loadDatabaseList())); connect(list,SIGNAL(started()),this,SLOT(playDatabaseList())); itm = new QListWidgetItem(p->listPlaylists); itm->setSizeHint(QSize(0,70)); p->listPlaylists->addItem(itm); p->listPlaylists->setItemWidget(itm,list); //Last Tracks List list = new PlaylistWidget(p->listPlaylists); list->setName(tr("Last Tracks")); list->setObjectName("LastTracks"); list->setDescription(tr("Recently played tracks")); list->setRemovable(false); connect(list,SIGNAL(activated()),this,SLOT(loadDatabaseList())); connect(list,SIGNAL(started()),this,SLOT(playDatabaseList())); itm = new QListWidgetItem(p->listPlaylists); itm->setSizeHint(QSize(0,70)); p->listPlaylists->addItem(itm); p->listPlaylists->setItemWidget(itm,list); //Favorites Tracks List list = new PlaylistWidget(p->listPlaylists); list->setName(tr("Favorites Tracks")); list->setObjectName("FavoritesTracks"); list->setDescription(tr("High rated tracks")); list->setRemovable(false); connect(list,SIGNAL(activated()),this,SLOT(loadDatabaseList())); connect(list,SIGNAL(started()),this,SLOT(playDatabaseList())); itm = new QListWidgetItem(p->listPlaylists); itm->setSizeHint(QSize(0,70)); p->listPlaylists->addItem(itm); p->listPlaylists->setItemWidget(itm,list); // read stored lists QList listData = p->database->selectPlaylistData(); foreach ( QStringList data, listData) { QString name = data[0]; int count = data[1].toInt(); int sum = data[2].toInt(); QDateTime date(QDateTime::fromTime_t( data[3].toInt() )); qDebug() << Q_FUNC_INFO << "add playlist: " << name; list = new PlaylistWidget(p->listPlaylists); list->setName( name ); list->setObjectName( name ); list->setDescription( date.toString("yyyy-MM-dd") + " " + QString::number(count) + " " + tr("tracks") + " " + Track::prettyTime( sum ,true) + " " + tr("hours")); connect(list,SIGNAL(activated()),this,SLOT(loadDatabaseList())); connect(list,SIGNAL(started()),this,SLOT(playDatabaseList())); connect(list,SIGNAL(deleted()),this,SLOT(removeDatabaseList())); itm = new QListWidgetItem(p->listPlaylists); itm->setSizeHint(QSize(0,70)); p->listPlaylists->addItem(itm); p->listPlaylists->setItemWidget(itm,list); } //// read saved lists //QDir rDir( p->directory ); //rDir.setFilter(QDir::Files | QDir::NoDotDot | QDir::NoDot | QDir::Readable); //QStringList filters; // filters << "*.xspf"; //rDir.setNameFilters(filters); //QFileInfoList filelist = rDir.entryInfoList(); //Q_FOREACH (const QFileInfo fi, filelist) { // if ( fi.isFile() ) { // qDebug() << Q_FUNC_INFO << "add playlist: " << fi.fileName(); // list = new PlaylistWidget(p->listPlaylists); // list->setName(fi.fileName().replace(".xspf","")); // list->setObjectName(fi.fileName()); // QPair count = readFileValues( p->directory+"/"+fi.fileName()); // list->setDescription( fi.lastModified().toString("yyyy-MM-dd") + " " // + QString::number(count.first) + " " + tr("tracks") + " " // + Track::prettyTime( count.second ,true) + " " + tr("hours")); // connect(list,SIGNAL(activated()),this,SLOT(loadFileList())); // connect(list,SIGNAL(started()),this,SLOT(playFileList())); // connect(list,SIGNAL(deleted()),this,SLOT(removeFileList())); // itm = new QListWidgetItem(p->listPlaylists); // itm->setSizeHint(QSize(0,70)); // p->listPlaylists->addItem(itm); // p->listPlaylists->setItemWidget(itm,list); // } //} } void PlaylistBrowser::playDatabaseList() { qDebug() << Q_FUNC_INFO ; if(PlaylistWidget* item = qobject_cast(QObject::sender())){ onSelectionChanged(item); emit selectionStarted(selectedTracks()); } } void PlaylistBrowser::loadDatabaseList() { qDebug() << Q_FUNC_INFO ; if(PlaylistWidget* item = qobject_cast(QObject::sender())){ onSelectionChanged(item); emit selectionChanged(selectedTracks()); } } void PlaylistBrowser::removeDatabaseList() { qDebug() << Q_FUNC_INFO ; if(PlaylistWidget* item = qobject_cast(QObject::sender())){ QString senderName = item->objectName(); p->database->removePlaylist(senderName); updateLists(); } } QList PlaylistBrowser::selectedTracks() { QString senderName = p->currentPlaylist->objectName(); QList selectedTags; //Retrieve songs from database if (senderName == "TopTracks") selectedTags = p->database->selectHotTracks(); else if (senderName == "FavoritesTracks") selectedTags = p->database->selectFavoritesTracks(); else if (senderName == "LastTracks") selectedTags = p->database->selectLastTracks(); else selectedTags = p->database->selectPlaylistTracks(senderName); QList tracks; tracks.clear(); qDebug() << Q_FUNC_INFO << "Song count: " << selectedTags.count(); //add tags to this track list foreach ( QStringList tag, selectedTags) { tracks.append( new Track(tag)); } return tracks ; } void PlaylistBrowser::onSelectionChanged(PlaylistWidget* item) { p->currentPlaylist = item; for (int d=0;dlistPlaylists->count();d++) ((PlaylistWidget*)p->listPlaylists->itemWidget(p->listPlaylists->item(d)))->deactivate(); item->activate(); } void PlaylistBrowser::onPushSave() { // QFileDialog dialog(this); // dialog.setDefaultSuffix("xspf"); // QString fileName = dialog.getSaveFileName(this, // tr("Save Play List"), p->directory, // tr("Playlists (*.xspf);;All Files (*)")); // // Bad workaround for Linux (Mac and Windows work with defaultSuffix) // if (!fileName.endsWith(".xspf")) // fileName += ".xspf"; // emit savePlaylists(fileName); QInputDialog* dialog = new QInputDialog(this, Qt::Dialog); dialog->setWindowTitle( tr("Save Play List") ); dialog->setLabelText( tr("Enter a name for the new list") ); dialog->resize(350,100); dialog->exec(); QString listName = dialog->textValue(); if ( !listName.isEmpty() ) emit storePlaylists(listName); } // obsolate: save list into files QList PlaylistBrowser::readFileList(QString filename) { QFile file( filename ); QList tracks; tracks.clear(); if( file.open( QFile::ReadOnly ) ) { QTextStream stream( &file ); stream.setCodec( QTextCodec::codecForName("utf8") ); QDomDocument d; if( !d.setContent(stream.readAll()) ) { qDebug() << "Could not load XML\n"; return tracks; } QDomNode n = d.namedItem( "playlist" ).namedItem( "trackList" ).firstChild(); const QString TRACK( "track" ); //so we don't construct the QStrings all the time const QString URL( "url" ); const QString CURRENT( "current" ); const QString NEXT( "next" ); while( !n.isNull() ) { if( n.nodeName() == TRACK ) { const QDomElement e = n.toElement(); if( e.isNull() ) { qDebug() << "Element '" << n.nodeName() << "' is null, skipping."; continue; } //qDebug() << "Add from xml url='" << e.attribute( URL ); Track *track = new Track(); track->setUrl( QUrl::fromLocalFile(e.namedItem("location").firstChild().nodeValue())); track->setArtist( e.namedItem("creator").firstChild().nodeValue()); track->setTitle( e.namedItem("title").firstChild().nodeValue()); track->setAlbum( e.namedItem("album").firstChild().nodeValue()); track->setTracknumber( e.namedItem("trackNum").firstChild().nodeValue()); track->setGenre( e.namedItem("extension").toElement().attribute( "genre" )); track->setYear( e.namedItem("extension").toElement().attribute( "year" )); track->setLength( e.namedItem("duration").firstChild().nodeValue()); track->setCounter("0"); if ( e.namedItem("extension").toElement().attribute( "isAutoDjSelection" ) =="1" ) track->setFlags( track->flags() | Track::isAutoDjSelection ); if ( e.namedItem("extension").toElement().attribute( "isOnFirstPlayer" ) =="1" ) track->setFlags( track->flags() | Track::isOnFirstPlayer ); if ( e.namedItem("extension").toElement().attribute( "isOnSecondPlayer" ) =="1" ) track->setFlags( track->flags() | Track::isOnSecondPlayer ); track->setRate( e.namedItem("extension").toElement().attribute("Rating").toInt() ); tracks.append(track); } n = n.nextSibling(); } } file.close(); qDebug() << "End " << Q_FUNC_INFO; return tracks; } QPair PlaylistBrowser::readFileValues(QString filename) { QFile file( filename ); QPair pair; int duration=0; int count=0; if( file.open( QFile::ReadOnly ) ) { QTextStream stream( &file ); stream.setCodec( QTextCodec::codecForName("utf8") ); QDomDocument d; if( !d.setContent(stream.readAll()) ) { qDebug() << "Could not load XML\n"; return pair; } QDomNode n = d.namedItem( "playlist" ).namedItem( "trackList" ).firstChild(); const QString TRACK( "track" ); while( !n.isNull() ) { if( n.nodeName() == TRACK ) { const QDomElement e = n.toElement(); if( e.isNull() ) { qDebug() << "Element '" << n.nodeName() << "' is null, skipping."; continue; } duration+= e.namedItem("duration").firstChild().nodeValue().toInt(); count++; } n = n.nextSibling(); } } file.close(); pair.first = count; pair.second = duration; qDebug() << "End " << Q_FUNC_INFO; return pair; } void PlaylistBrowser::playFileList() { qDebug() << Q_FUNC_INFO ; if(PlaylistWidget* item = qobject_cast(QObject::sender())){ onSelectionChanged(item); QString senderName = item->objectName(); emit selectionStarted( readFileList( p->directory+"/"+senderName) ); } } void PlaylistBrowser::loadFileList() { qDebug() << Q_FUNC_INFO ; if(PlaylistWidget* item = qobject_cast(QObject::sender())){ onSelectionChanged(item); QString senderName = item->objectName(); //Retrieve songs from file emit selectionChanged( readFileList( p->directory+"/"+senderName) ); } } void PlaylistBrowser::removeFileList() { qDebug() << Q_FUNC_INFO ; if(PlaylistWidget* item = qobject_cast(QObject::sender())){ QString senderName = item->objectName(); QFile::remove( p->directory+"/"+senderName ); updateLists(); } } knowthelist-2.3.0/src/playlistwidget.ui0000664000175000017500000002143112423536022017264 0ustar mariomario PlaylistWidget 0 0 436 85 Frame QPushButton#butPlay { color: white; border-style: inset; border: 1.5px solid #333333; border-radius: 4px; padding: 1px; background: qlineargradient( x1:0, y1:0, x2:0, y2:0.3, stop:0.1 white, stop:1 #666666 ); max-height: 19px; min-height: 19px; } QPushButton#butPlay:pressed { background: qlineargradient( x1:0, y1:0, x2:0, y2:0.3, stop:0.1 white, stop:1 #82df52 ); } QFrame#framePlaylistWidget{ background: qlineargradient( x1:0, y1:0, x2:0, y2:1, stop: 0.01 #202020, stop:0.11 #505050, stop:1 #505050 ); } QFrame#framePlaylistWidget::item:selected { border: 1px solid #6a6ea9; } QFrame#framePlaylistWidget::item:selected:!active { background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ABAFE5, stop: 1 #8588B2); } QFrame#framePlaylistWidget::item:selected:active { background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6a6ea9, stop: 1 #888dd9); } QFrame#framePlaylistWidget::item:hover { background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #FAFBFE, stop: 1 #DCDEF1); } 0 0 Qt::DefaultContextMenu QFrame::NoFrame QFrame::Raised 0 QFrame::NoFrame QFrame::Raised 0 2 0 2 Click here to show the content of this list <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="charts"><span style=" font-size:8pt; text-decoration: underline; color:#d0fff8;">Most Played</span></a></p></body></html> 0 0 16777215 60 TextLabel true lblDesciption lblName 0 0 80 0 80 16777215 QFrame::NoFrame QFrame::Raised 0 0 0 6 0 0 35 0 16777215 16777215 Load all tracks of this list directly into player playlists :/play.png:/play.png Qt::Horizontal 40 20 Remove this list x 0 0 18 16777215 <html><head/><body><p>Confirm the remove</p></body></html> background-color: rgb(255, 65, 87); Delete knowthelist-2.3.0/src/qled.h0000775000175000017500000000541112423536022014761 0ustar mariomario/* LED class adapted from KDE to use under QT * Copyright (C) 1998 Jörg Habenicht (j.habenicht@europemail.com) Copyright (C) 2010 Christoph Feck Copyright (C) 2011 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef QLed_H #define QLed_H #include #include class QColor; class QLed : public QWidget { Q_OBJECT Q_ENUMS( State Shape Look ) public: enum State { Off, On }; enum Shape { Rectangular, Circular }; enum Look { Flat, Raised, Sunken }; explicit QLed( QWidget *parent = 0 ); explicit QLed( const QColor &color, QWidget *parent = 0 ); QLed( const QColor& color, QLed::State state, QLed::Look look, QLed::Shape shape, QWidget *parent = 0 ); ~QLed(); QColor color() const; State state() const; Look look() const; Shape shape() const; int darkFactor() const; void setColor( const QColor& color ); void setState( State state ); void setLook( Look look ); void setShape( Shape shape ); void setDarkFactor( int darkFactor ); virtual QSize sizeHint() const; virtual QSize minimumSizeHint() const; public Q_SLOTS: void toggle(); void on(); void off(); protected: virtual int ledWidth() const; virtual void paintFlat(); virtual void paintRaised(); virtual void paintSunken(); virtual void paintRect(); virtual void paintRectFrame( bool raised ); void paintEvent( QPaintEvent* ); void resizeEvent( QResizeEvent* ); bool paintCachedPixmap(); void updateCachedPixmap(); void paintLed(Shape shape, Look look); private: class Private; Private * const d; QColor overlayColors(const QColor &base, const QColor &paint, QPainter::CompositionMode comp = QPainter::CompositionMode_SourceOver); }; #endif knowthelist-2.3.0/src/monitorplayer.h0000775000175000017500000000515512423536022016745 0ustar mariomario/* Copyright (C) 2005-2014 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #ifndef MONITORPLAYER_H #define MONITORPLAYER_H #include #include #if defined(Q_OS_WIN32) #include #include #endif #define GST_DISABLE_LOADSAVE 1 #define GST_DISABLE_REGISTRY 1 #define GST_DISABLE_DEPRECATED 1 #include typedef QPair dsDevice; class MonitorPlayer: public QWidget { Q_OBJECT public: MonitorPlayer(QWidget *parent = 0); ~MonitorPlayer(); bool prepare(); bool ready(); bool canOpen(QString mime); void open(QUrl url); void play(); void stop(); void pause(); bool close(); void setPosition(QTime); QTime position(); double volume(); void setVolume(double); QTime length(); bool isPlaying(); bool mediaPlayable(); QStringList outputDevices(); QString outputDeviceName(); QString outputDeviceID(); void setOutputDevice(QString deviceName); void readDevices(); QString defaultDeviceID(); double levelLeft() {return rms_l;} double levelRight() {return rms_r;} void newpad (GstElement *decodebin, GstPad *pad, gpointer data); static GstBusSyncReply bus_cb (GstBus *bus, GstMessage *msg, gpointer data); Q_SIGNALS: void finish(); void error(); void levelChanged(); void positionChanged(); void loadFinished(); private slots: void loadThreadFinished(); void messageReceived(GstMessage* message); private: struct Private; Private * p; GstElement *pipeline; GstBus *bus; //QTimer *timer; gint64 Gstart, Glength; int m_length; int m_position; dsDevice dev; double rms_l,rms_r; void setLink(int, QUrl&); void asyncOpen(QUrl url); void cleanup(); void sync_set_state(GstElement*, GstState); }; #endif // MONITORPLAYER_H knowthelist-2.3.0/src/collectionsetupmodel.cpp0000775000175000017500000001054212423536022020625 0ustar mariomario/* Copyright (C) 2005-2014 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #include "collectionsetupmodel.h" #include #include CollectionSetupModel::CollectionSetupModel() { } Qt::ItemFlags CollectionSetupModel::flags(const QModelIndex& index) const { Qt::ItemFlags f = QDirModel::flags(index); if (index.column() == 0) // make the first column checkable f |= Qt::ItemIsUserCheckable; return f; } QVariant CollectionSetupModel::data(const QModelIndex& index, int role) const { if (index.isValid() && index.column() == 0 && role == Qt::CheckStateRole) { // the item is checked only if we have stored its path if (checkedPartially.contains(filePath(index)) ) { return Qt::PartiallyChecked; } else return (checked.contains(filePath(index)) ? Qt::Checked : Qt::Unchecked); } return QDirModel::data(index, role); } bool CollectionSetupModel::setData(const QModelIndex& index, const QVariant& value, int role) { if (index.isValid() && index.column() == 0 && role == Qt::CheckStateRole) { // store checked paths, remove unchecked paths QModelIndex idx=parent(index); if (value.toInt() == Qt::Checked) { checked.insert(filePath(index)); // make parents always partially checked while( idx.isValid() ) { checkedPartially.insert(filePath(idx)); checked.remove(filePath(idx)); idx =idx.parent(); } } else { checked.remove(filePath(index)); // make parent unchecked if index was his only child while( idx.isValid() ) { bool hasChildren=false; foreach (const QString &value, checked) if ( value.contains(filePath(idx)) ) hasChildren = true; if ( !hasChildren ){ checkedPartially.remove(filePath(idx)); checked.insert(filePath(idx)); } idx =idx.parent(); } } emit dataChanged(parent(index),index); return true; } return QDirModel::setData(index, value, role); } QVariant CollectionSetupModel::headerData(int section, Qt::Orientation orientation, int role) const { if (orientation == Qt::Horizontal) { if (role != Qt::DisplayRole) return QVariant(); switch (section) { case 0: return QString(tr("Select folders for music collection")); default: return QVariant(); } } return QAbstractItemModel::headerData(section, orientation, role); } QStringList CollectionSetupModel::dirsChecked() { QStringList list; foreach (const QString &value, checked) list << value; return list; } void CollectionSetupModel::setDirsChecked(QStringList list) { checked.clear(); checkedPartially.clear(); foreach (const QString &value, list) { /* index parents Qt::PartiallyChecked */ QModelIndex idx=parent(index(value)); while( idx.isValid() ) { checkedPartially.insert(filePath(idx)); idx =idx.parent(); } checked.insert(value); } } knowthelist-2.3.0/src/collectionupdater.h0000775000175000017500000000312712423536022017556 0ustar mariomario/* Copyright (C) 2005-2014 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #ifndef COLLECTIONUPDATER_H #define COLLECTIONUPDATER_H #include "collectionwidget.h" #include "collectionupdater.h" #include #include "collectiondb.h" class CollectionUpdater : public QObject { Q_OBJECT public: CollectionUpdater(); ~CollectionUpdater(); void setDoMonitor(bool); void setDirectoryList(QStringList dirs, bool force=false); QStringList getRandomEntry(QString); public slots: void scan(); void monitor(); void stop(); signals: void changesDone(); void progressChanged(int percent); private: void readDir( const QString& dir, QStringList& entries ); void readTags( const QStringList& entries ); void asynchronScan(QStringList dirs); class CollectionUpdaterPrivate *p; }; #endif // COLLECTIONUPDATER_H knowthelist-2.3.0/src/djfilterwidget.ui0000775000175000017500000026257612423536022017252 0ustar mariomario DjFilterWidget 0 0 754 85 16777215 300 Form QFrame#frame{ background: qlineargradient( x1:0, y1:0, x2:0, y2:1, stop: 0.01 #202020, stop:0.11 #505050, stop:1 #505050 ); } QLineEdit { background:#606060; color: #a4a4a4; selection-color: white; border: 1px groove gray; border-radius: 0px; margin: 0 0 0 0; font-size: 10px; } QFrame#fraDisplay>QLabel { color: #dddddd; } QLineEdit:focus { background: #a0a0a0; color: #101010; selection-color: white; border: 1px groove black; border-radius: 10px; } QLineEdit:edit-focus { color: rgb(0, 63, 123); background: #a0a0a0; selection-color: white; border: 1px groove black; border-radius: 10px; padding: 2px 4px; } QFrame#fraDisplay{ border: 1px solid #a2a2a2; border-radius: 3px; background: qradialgradient( cx: 0.5, cy: -1.8, fx: 0.5, fy: 0, radius: 2, stop: 0 #9aa9be, stop: 1 #182238); } QComboBox { background:#606060; color: #a4a4a4; selection-color: white; border: 1px groove gray; border-radius: 0px; font-size: 10px; } QComboBox QAbstractItemView{ background-color: #4f4f4f; color: #999999; selection-background-color: #999999; selection-color: #4f4f4f; } QComboBox::drop-down { subcontrol-origin: padding; subcontrol-position: top right; width: 15px; border-left-width: 1px; border-left-color: gray; border-left-style: solid; border-top-right-radius: 3px; border-bottom-right-radius: 3px; } QComboBox::down-arrow { image: url(:down.png); } QComboBox:on { padding-top: 3px; padding-left: 4px; } 0 0 0 0 16777215 16777215 QFrame::NoFrame QFrame::Plain 0 0 0 0 3 0 0 42 0 Qt::LeftToRight QFrame::NoFrame QFrame::Raised 9 34 32 32 0 0 0 0 32 32 9 Record Case QFrame::NoFrame :/vinyl.png true 0 -1 0 0 290 0 290 16777215 Qt::LeftToRight QFrame::NoFrame QFrame::Raised 5 12 156 58 0 0 156 0 156 16777215 QFrame::StyledPanel QFrame::Raised 14 39 51 22 0 0 7 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Lucida Grande'; font-size:13pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt;">count of records which fit to this filter(s)</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt; text-decoration: underline;"></p></body></html> 0 Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 13 6 31 24 14 75 true 1 44 10 105 41 0 0 14 32 51 16 7 0 166 12 85 58 0 0 85 0 85 16777215 QFrame::NoFrame QFrame::Raised -4 23 51 31 0 0 56 56 8 how many records per turn 0 10 1 2 0 true false true 63 24 13 8 7 7 35 119 246 135 52 33 33 19 0 0 0 0 33 16777215 255 255 255 153 153 153 80 80 80 0 0 0 255 255 255 221 221 221 93 93 93 124 124 124 255 255 255 255 255 255 255 255 255 153 153 153 80 80 80 0 0 0 153 153 153 80 80 80 0 0 0 0 0 0 0 0 128 255 255 255 0 0 0 0 0 0 255 255 255 153 153 153 80 80 80 0 0 0 255 255 255 215 215 215 93 93 93 124 124 124 255 255 255 255 255 255 255 255 255 153 153 153 80 80 80 0 0 0 153 153 153 80 80 80 0 0 0 0 0 0 0 0 128 255 255 255 0 0 0 0 0 0 255 255 255 153 153 153 80 80 80 0 0 0 255 255 255 215 215 215 93 93 93 124 124 124 255 255 255 255 255 255 255 255 255 153 153 153 80 80 80 0 0 0 153 153 153 80 80 80 0 0 0 0 0 0 0 0 128 255 255 255 0 0 0 0 0 0 7 Activate this record case set Alt+J true false 2 5 52 15 7 Count 276 30 30 20 30 20 Remove this record case x 0 0 0 82 16777215 92 QFrame::NoFrame QFrame::Raised 0 13 13 13 3 0 0 60 11 0 0 0 255 87 193 168 193 255 118 154 243 34 57 116 45 76 155 0 0 0 255 255 255 0 0 0 255 87 193 255 87 193 0 0 0 161 185 243 255 255 220 0 0 0 0 0 0 255 87 193 168 193 255 118 154 243 34 57 116 45 76 155 0 0 0 255 255 255 0 0 0 255 87 193 255 87 193 0 0 0 161 185 243 255 255 220 0 0 0 34 57 116 255 87 193 168 193 255 118 154 243 34 57 116 45 76 155 34 57 116 255 255 255 34 57 116 255 87 193 255 87 193 0 0 0 68 115 232 255 255 220 0 0 0 7 true false PointingHandCursor QFrame::Sunken <html><head/><body><p><a href="#"><span style=" text-decoration: underline; color:#e1e1e1;">Path</span></a></p></body></html> Qt::AlignCenter 0 0 0 17 true 0 17 0 0 0 60 11 0 0 0 255 87 193 168 193 255 118 154 243 34 57 116 45 76 155 0 0 0 255 255 255 0 0 0 255 87 193 255 87 193 0 0 0 161 185 243 255 255 220 0 0 0 0 0 0 255 87 193 168 193 255 118 154 243 34 57 116 45 76 155 0 0 0 255 255 255 0 0 0 255 87 193 255 87 193 0 0 0 161 185 243 255 255 220 0 0 0 34 57 116 255 87 193 168 193 255 118 154 243 34 57 116 45 76 155 34 57 116 255 255 255 34 57 116 255 87 193 255 87 193 0 0 0 68 115 232 255 255 220 0 0 0 7 false false ArrowCursor QFrame::Sunken Genre Qt::AlignCenter 0 0 60 11 0 0 0 255 87 193 168 193 255 118 154 243 34 57 116 45 76 155 0 0 0 255 255 255 0 0 0 255 87 193 255 87 193 0 0 0 161 185 243 255 255 220 0 0 0 0 0 0 255 87 193 168 193 255 118 154 243 34 57 116 45 76 155 0 0 0 255 255 255 0 0 0 255 87 193 255 87 193 0 0 0 161 185 243 255 255 220 0 0 0 34 57 116 255 87 193 168 193 255 118 154 243 34 57 116 45 76 155 34 57 116 255 255 255 34 57 116 255 87 193 255 87 193 0 0 0 68 115 232 255 255 220 0 0 0 7 false false ArrowCursor QFrame::Sunken Artist Qt::AlignCenter 0 0 0 17 true 0 0 18 16777215 <html><head/><body><p>Confirm the remove</p></body></html> background-color: rgb(255, 65, 87); 9 Delete QLed QWidget
qled.h
1
StackDisplay QWidget
stackdisplay.h
1
knowthelist-2.3.0/src/modeselector.ui0000664000175000017500000000676212423536022016716 0ustar mariomario ModeSelector 0 0 76 30 0 0 55 30 16 Frame false QPushButton { color: #ffffff; border-style: inset; border: 1px solid #aaaaaa; border-radius: 4px; background: #555555; max-height: 11px; min-height: 11px; min-width:13px; max-width:13px; } QFrame::NoFrame QFrame::Raised 2 4 15 13 8 View: Artist > Album 90 15 13 4 20 4 15 13 8 View: Year > Artist > Album Y 100 15 20 20 38 4 15 13 8 View: Genre > Artist > Album G 123 15 13 4 push2 push3 push1 led2 led3 led1 QLed QWidget
qled.h
1
knowthelist-2.3.0/src/filter.h0000775000175000017500000000312112423536022015315 0ustar mariomario/* Copyright (C) 2005-2014 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #ifndef FILTER_H #define FILTER_H #include class Filter: public QObject { Q_OBJECT public: explicit Filter(); explicit Filter(QString genre, int grade); ~Filter(); int maxUsage(); void setMaxUsage(int); int usage(); void setUsage(int); QString genre(); QString path(); QString artist(); QString description(); int count(); long length(); void setPath(QString); void setGenre(QString); void setArtist(QString); void setCount(int); void setLength(long); bool active(); void setActive(bool); void update(); Q_SIGNALS: void statusChanged(bool status); void countChanged(); void usageChanged(); void maxUsageChanged(); void activated(); void filterChanged(); public slots: private: struct Private; Private * p; }; #endif // FILTER_H knowthelist-2.3.0/src/progressbar.h0000775000175000017500000000230012423536022016357 0ustar mariomario/* Copyright (C) 2005-2014 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #ifndef PROGRESSBAR_H #define PROGRESSBAR_H #include #include #include class ProgressBar:public QWidget { Q_OBJECT public: ProgressBar(QWidget *parent = 0, const char *name = 0); ~ProgressBar(); QToolButton* clearButton; QProgressBar* bar; int value(); public slots: void setValue(int value); signals: void stopped(); private: void resizeEvent(QResizeEvent *); }; #endif knowthelist-2.3.0/src/playerwidget.ui0000775000175000017500000034176412423536022016740 0ustar mariomario PlayerWidget 0 0 699 124 0 0 Form QFrame#frame{ background: qlineargradient( x1:0, y1:0, x2:0, y2:1, stop: 0.03 #666666, stop:0.2 #777777, stop:1 black ); } QPushButton { color: white; border: 1.5px solid #333333; border-radius: 4px; padding: 1px; background: qlineargradient( x1:0, y1:0, x2:0, y2:1, stop:0.1 #505050, stop:1 black ); max-height: 16px; min-height: 10px; } QPushButton#butPlay { color: white; border-style: inset; border: 1.5px solid #333333; border-radius: 4px; padding: 1px; background: qlineargradient( x1:0, y1:0, x2:0, y2:0.3, stop:0.1 white, stop:1 #326f22 ); max-height: 32px; min-height: 32px; } QPushButton#butPlay:checked { background: qlineargradient( x1:0, y1:0, x2:0, y2:0.3, stop:0.1 white, stop:1 #82df52 ); } QPushButton#butCue { color: #333333; border: 1.5px solid #333333; border-radius: 4px; padding: 1px; background: qlineargradient( x1:0, y1:0, x2:0, y2:0.3, stop:0.2 white, stop:1 #9a6242 ); max-height: 29px; min-height: 10px; font-weight: bold; } QPushButton#butCue:checked { background: qlineargradient( x1:0, y1:0, x2:0, y2:0.3, stop:0.2 white, stop:1 #ffa272 ); color: black; } QScrollBar:horizontal { border: 2px solid grey; background: qlineargradient( x1:0, y1:0, x2:0, y2:1, stop:0.1 #505050, stop:1 gray ); height: 15px; margin: 0px 20px 0 20px; } QScrollBar::handle:horizontal { background: qlineargradient( x1:0, y1:0, x2:0, y2:1, stop:0.1 white, stop:1 gray ); min-width: 20px; } QScrollBar::add-line:horizontal { border: 2px solid grey; background: qlineargradient( x1:0, y1:0, x2:0, y2:1, stop:0.1 #505050, stop:1 black ); width: 20px; subcontrol-position: right; subcontrol-origin: margin; } QScrollBar::sub-line:horizontal { border: 2px solid grey; background: qlineargradient( x1:0, y1:0, x2:0, y2:1, stop:0.1 #505050, stop:1 black ); width: 20px; subcontrol-position: left; subcontrol-origin: margin; } QScrollBar:left-arrow:horizontal, QScrollBar::right-arrow:horizontal { border: 2px solid grey; width: 3px; height: 3px; background: white; } QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal { background: none; } QFrame#fraDisplay{ border: 1px solid #a2a2a2; border-radius: 3px; background: qradialgradient( cx: 0.5, cy: -1.8, fx: 0.5, fy: 0, radius: 2, stop: 0 #9aa9be, stop: 1 #293859); } QFrame#fraInfo{ } QLabel{ color: #dddddd; } 0 0 0 0 0 0 QFrame::StyledPanel QFrame::Raised 0 0 0 2 2 0 0 0 0 16777215 120 QFrame::NoFrame QFrame::Raised 4 4 7 1 0 4 0 0 18 1000 100 Qt::Horizontal true 0 0 16777215 113 QFrame::NoFrame QFrame::Raised 4 8 6 15 5 0 0 0 26 221 221 221 80 80 80 0 0 0 0 0 0 0 0 0 0 0 0 221 221 221 255 255 255 221 221 221 80 80 80 80 80 80 0 0 0 0 0 0 255 255 220 0 0 0 221 221 221 80 80 80 0 0 0 0 0 0 0 0 0 0 0 0 221 221 221 255 255 255 221 221 221 80 80 80 80 80 80 0 0 0 0 0 0 255 255 220 0 0 0 221 221 221 80 80 80 0 0 0 0 0 0 0 0 0 0 0 0 221 221 221 255 255 255 221 221 221 80 80 80 80 80 80 0 0 0 0 0 0 255 255 220 0 0 0 Sans Serif 16 true QFrame::Plain texttexttextt false Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop true 2 0 0 17 31 400 16777215 QFrame::NoFrame QFrame::Raised 6 5 0 4 0 0 17 16 400 16777215 0 0 0 14 16777215 14 TextLabel Qt::AlignCenter true -2 0 0 0 0 25 400 16777215 QFrame::NoFrame QFrame::Raised 1 2 1 3 true 0 18 57 16777215 221 221 221 80 80 80 0 0 0 0 0 0 0 0 0 0 0 0 221 221 221 255 255 255 221 221 221 80 80 80 80 80 80 0 0 0 0 0 0 255 255 220 0 0 0 221 221 221 80 80 80 0 0 0 0 0 0 0 0 0 0 0 0 221 221 221 255 255 255 221 221 221 80 80 80 80 80 80 0 0 0 0 0 0 255 255 220 0 0 0 221 221 221 80 80 80 0 0 0 0 0 0 0 0 0 0 0 0 221 221 221 255 255 255 221 221 221 80 80 80 80 80 80 0 0 0 0 0 0 255 255 220 0 0 0 Arial 16 50 false 00:00 false Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing false 0 0 true 0 18 16777215 16777215 221 221 221 80 80 80 0 0 0 0 0 0 0 0 0 0 0 0 221 221 221 255 255 255 221 221 221 80 80 80 80 80 80 0 0 0 0 0 0 255 255 220 0 0 0 221 221 221 80 80 80 0 0 0 0 0 0 0 0 0 0 0 0 221 221 221 255 255 255 221 221 221 80 80 80 80 80 80 0 0 0 0 0 0 255 255 220 0 0 0 221 221 221 80 80 80 0 0 0 0 0 0 0 0 0 0 0 0 221 221 221 255 255 255 221 221 221 80 80 80 80 80 80 0 0 0 0 0 0 255 255 220 0 0 0 Arial 14 .00 false Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft false 1 0 0 0 25 QFrame::NoFrame QFrame::Raised 30 2 30 1 true 57 18 255 61 42 80 80 80 0 0 0 0 0 0 0 0 0 0 0 0 255 61 42 255 255 255 255 61 42 80 80 80 80 80 80 0 0 0 0 0 0 255 255 220 0 0 0 255 61 42 80 80 80 0 0 0 0 0 0 0 0 0 0 0 0 255 61 42 255 255 255 255 61 42 80 80 80 80 80 80 0 0 0 0 0 0 255 255 220 0 0 0 255 61 42 80 80 80 0 0 0 0 0 0 0 0 0 0 0 0 255 61 42 255 255 255 255 61 42 80 80 80 80 80 80 0 0 0 0 0 0 255 255 220 0 0 0 Arial 16 <html><head/><body><p><span style=" color:#ffffff;">Time remain</span></p></body></html> color: rgb(255, 61, 42); -00:00 Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing false 0 0 true 0 18 16777215 16777215 255 61 42 80 80 80 0 0 0 0 0 0 0 0 0 0 0 0 255 61 42 255 255 255 255 61 42 80 80 80 80 80 80 0 0 0 0 0 0 255 255 220 0 0 0 255 61 42 80 80 80 0 0 0 0 0 0 0 0 0 0 0 0 255 61 42 255 255 255 255 61 42 80 80 80 80 80 80 0 0 0 0 0 0 255 255 220 0 0 0 255 61 42 80 80 80 0 0 0 0 0 0 0 0 0 0 0 0 255 61 42 255 255 255 255 61 42 80 80 80 80 80 80 0 0 0 0 0 0 255 255 220 0 0 0 Arial 14 color: rgb(255, 61, 42); .00 Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft false 1 true 33 16 DejaVu Sans 9 <html><head/><body><p><span style=" color:#ffffff;">Seconds of silence at the end </span></p></body></html> color: rgb(255, 61, 42); -00 Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false 0 0 95 0 16777215 120 QFrame::NoFrame QFrame::Raised QLayout::SetDefaultConstraint 8 0 16 0 0 0 0 54 38 QFrame::NoFrame QFrame::Raised 6 0 0 1 1 60 38 60 38 true 0 0 73 8 QFrame::NoFrame QFrame::Raised 0 0 1 1 30 16 24 22 1 1 30 16 24 22 0 0 0 35 QFrame::NoFrame QFrame::Raised 0 0 59 16 59 35 75 true Jump to the point where the music starts mainly CUE true false VUMeter QWidget
vumeter.h
1
knowthelist-2.3.0/src/monitorplayer.cpp0000775000175000017500000004554012423536022017302 0ustar mariomario/* Copyright (C) 2005-2014 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #include #if QT_VERSION >= 0x050000 #include #else #include #endif #if defined(Q_OS_DARWIN) #include #include #elif defined(Q_OS_WIN32) #include #elif defined(Q_OS_UNIX) #include #endif #include "monitorplayer.h" void MonitorPlayer::sync_set_state(GstElement* element, GstState state) { GstStateChangeReturn res; \ res = gst_element_set_state (GST_ELEMENT (element), state); \ if(res == GST_STATE_CHANGE_FAILURE) return; \ if(res == GST_STATE_CHANGE_ASYNC) { \ GstState state; \ res = gst_element_get_state(GST_ELEMENT (element), &state, NULL, 1000000000/*GST_CLOCK_TIME_NONE*/); \ if(res == GST_STATE_CHANGE_FAILURE || res == GST_STATE_CHANGE_ASYNC) return; \ } } struct MonitorPlayer::Private { QFutureWatcher watcher; QMutex mutex; bool isStarted; bool isLoaded; QString error; QString deviceName; QString deviceID; QMap devices; }; void cb_newpad_mp (GstElement *decodebin, GstPad *pad, gpointer data) { MonitorPlayer* instance = (MonitorPlayer*)data; instance->newpad(decodebin, pad, data); } void MonitorPlayer::newpad (GstElement *decodebin, GstPad *pad, gpointer data) { GstCaps *caps; GstStructure *str; GstPad *audiopad; /* only link once */ GstElement *audio = gst_bin_get_by_name(GST_BIN(pipeline), "audiobin"); audiopad = gst_element_get_static_pad (audio, "sink"); gst_object_unref(audio); if (GST_PAD_IS_LINKED (audiopad)) { g_object_unref (audiopad); return; } /* check media type */ #ifdef GST_API_VERSION_1 caps = gst_pad_query_caps (pad,NULL); #else caps = gst_pad_get_caps (pad); #endif str = gst_caps_get_structure (caps, 0); if (!g_strrstr (gst_structure_get_name (str), "audio")) { gst_caps_unref (caps); gst_object_unref (audiopad); return; } gst_caps_unref (caps); /* link'n'play */ gst_pad_link (pad, audiopad); } MonitorPlayer::MonitorPlayer(QWidget *parent): QWidget(parent), pipeline(0), bus(0), Gstart(0), Glength(0) , p( new Private ) { p->isStarted=false; p->isLoaded=false; readDevices(); p->deviceID=defaultDeviceID(); connect(&p->watcher, SIGNAL(finished()), this, SLOT(loadThreadFinished())); } MonitorPlayer::~MonitorPlayer() { delete p; p=0; cleanup(); } GstBusSyncReply MonitorPlayer::bus_cb (GstBus *bus, GstMessage *msg, gpointer data) { Q_UNUSED(bus); MonitorPlayer* instance = (MonitorPlayer*)data; instance->messageReceived(msg); return GST_BUS_PASS; } void MonitorPlayer::cleanup() { if(pipeline) sync_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL); if(bus) gst_object_unref (bus); if(pipeline) gst_object_unref(G_OBJECT(pipeline)); } bool MonitorPlayer::prepare() { //Init Gst // QString caps_value = "audio/x-raw"; gst_init (0, 0); //prepare GstElement *dec, *conv,*resample,*sink, *level, *vol, *audio; GstPad *audiopad; GstCaps *caps; pipeline = gst_pipeline_new ("pipeline"); bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); #ifdef GST_API_VERSION_1 dec = gst_element_factory_make ("decodebin", "decoder"); #else dec = gst_element_factory_make ("decodebin2", "decoder"); caps_value = "audio/x-raw-int"; #endif caps = gst_caps_new_simple (caps_value.toLatin1().data(), "channels", G_TYPE_INT, 2, NULL); g_signal_connect (dec, "pad-added", G_CALLBACK (cb_newpad_mp), this); gst_bin_add (GST_BIN (pipeline), dec); audio = gst_bin_new ("audiobin"); conv = gst_element_factory_make ("audioconvert", "aconv"); audiopad = gst_element_get_static_pad (conv, "sink"); vol = gst_element_factory_make ("volume", "volume"); resample = gst_element_factory_make ("audioresample", "resample"); level = gst_element_factory_make ("level", "level"); #if defined(Q_OS_DARWIN) sink = gst_element_factory_make ("osxaudiosink", "sink"); g_object_set (sink, "device", 0, NULL); //g_object_set (sink, "volume", 9.5, NULL); #elif defined(Q_OS_WIN32) sink = gst_element_factory_make ("directsoundsink", "sink"); g_object_set (sink, "device", NULL, NULL); //g_object_set (sink, "volume", 99.5, NULL); #elif defined(Q_OS_UNIX) sink = gst_element_factory_make ("alsasink", "sink"); g_object_set (sink, "device", "default", NULL); //g_object_set (sink, "volume", 0.5, NULL); #else sink = gst_element_factory_make ("fakesink", "sink"); g_object_set (sink, "device", NULL, NULL); #endif gst_bin_add_many (GST_BIN (audio), conv, resample, level, vol, sink, NULL); gst_element_link (conv,resample); gst_element_link_filtered (resample, level, caps); gst_element_link (level,vol); gst_element_link (vol, sink); gst_element_add_pad (audio, gst_ghost_pad_new ("sink", audiopad)); gst_bin_add (GST_BIN (pipeline), audio); GstElement *l_src; l_src = gst_element_factory_make ("filesrc", "localsrc"); gst_bin_add_many (GST_BIN (pipeline), l_src, NULL); gst_element_set_state (l_src, GST_STATE_NULL); gst_element_link ( l_src,dec); #ifdef GST_API_VERSION_1 gst_bus_set_sync_handler (bus, bus_cb, this, NULL); #else gst_bus_set_sync_handler (bus, bus_cb, this); #endif gst_object_unref (audiopad); return pipeline; } bool MonitorPlayer::ready() { return pipeline; } void MonitorPlayer::open(QUrl url) { //To avoid delays load track in another thread qDebug() << Q_FUNC_INFO <<":"<objectName()<<" url="< future = QtConcurrent::run( this, &MonitorPlayer::asyncOpen,url); p->watcher.setFuture(future); } void MonitorPlayer::asyncOpen(QUrl url) { p->mutex.lock(); m_length = 0; p->isLoaded=false; p->error=""; sync_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL); GstElement *l_src = gst_bin_get_by_name(GST_BIN(pipeline), "localsrc"); g_object_set (G_OBJECT (l_src), "location", (const char*)url.toLocalFile().toUtf8(), NULL); sync_set_state (GST_ELEMENT (pipeline), GST_STATE_PAUSED); setPosition(QTime(0,0)); gst_object_unref(l_src); p->mutex.unlock(); } void MonitorPlayer::loadThreadFinished() { // async load in MonitorPlayerGst done qDebug() << Q_FUNC_INFO <<":"<objectName(); p->isLoaded=true; if (p->isStarted) { play(); } emit loadFinished(); } void MonitorPlayer::play() { p->isStarted=true; qDebug() << Q_FUNC_INFO <<":"<objectName(); if (p->isLoaded) { gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING); } } void MonitorPlayer::stop() { p->isStarted=false; gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_READY); } void MonitorPlayer::pause() { if(isPlaying()){ p->isStarted=false; gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PAUSED); } } bool MonitorPlayer::close() { gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL); return true; } void MonitorPlayer::setPosition(QTime position) { int time_milliseconds=QTime(0,0).msecsTo(position); gint64 time_nanoseconds=( time_milliseconds * GST_MSECOND ); gst_element_seek (pipeline, 1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, time_nanoseconds, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE); m_position=time_milliseconds; emit positionChanged(); } QTime MonitorPlayer::position() { if (pipeline) { gint64 value=0; #ifdef GST_API_VERSION_1 if(gst_element_query_position(pipeline, GST_FORMAT_TIME, &value)) { #else GstFormat fmt = GST_FORMAT_TIME; if(gst_element_query_position(pipeline, &fmt, &value)) { #endif m_position = static_cast( ( value / GST_MSECOND ) ); return QTime(0,0).addMSecs( m_position ); // nanosec -> msec } return QTime(0,0).addMSecs( m_position ); // nanosec -> msec } return QTime(0,0); } QTime MonitorPlayer::length() { gint64 value=0; if ( m_length == 0 && pipeline){ #ifdef GST_API_VERSION_1 if(gst_element_query_duration(pipeline, GST_FORMAT_TIME, &value)) { #else GstFormat fmt = GST_FORMAT_TIME; if(gst_element_query_duration(pipeline, &fmt, &value)) { #endif m_length = static_cast( ( value / GST_MSECOND )); } } return QTime(0,0).addMSecs( m_length ); // nanosec -> msec } double MonitorPlayer::volume() { gdouble vol = 0; GstElement *volume = gst_bin_get_by_name(GST_BIN(pipeline), "volume"); g_object_get (G_OBJECT(volume), "volume", &vol, NULL); gst_object_unref(volume); return vol; } void MonitorPlayer::setVolume(double v) { gdouble vol = 1.00 * v; GstElement *volume = gst_bin_get_by_name(GST_BIN(pipeline), "volume"); g_object_set (G_OBJECT(volume), "volume", vol, NULL); gst_object_unref(volume); } bool MonitorPlayer::mediaPlayable() { GstState st; gst_element_get_state (GST_ELEMENT (pipeline), &st, 0, 0); //qDebug()< i(p->devices); while (i.hasNext()) { i.next(); outList << i.value(); } return outList; } QString MonitorPlayer::outputDeviceName() { return p->deviceName; } QString MonitorPlayer::outputDeviceID() { return p->deviceID; } void MonitorPlayer::setOutputDevice(QString deviceName) { // for Mac device is DeviceID QMapIterator i(p->devices); while (i.hasNext()) { i.next(); if (i.value()==deviceName) { p->deviceID = i.key(); p->deviceName = i.value(); } } qDebug()<<"Monitor setDevice to DeviceID:"<deviceID<<" DevicenName:"<deviceName; GstElement *sink = gst_bin_get_by_name(GST_BIN(pipeline), "sink"); #if defined(Q_OS_WIN32) g_object_set (sink, "device", p->deviceID.toLatin1().data(), NULL); #elif defined(Q_OS_DARWIN) g_object_set (sink, "device", p->deviceID.toInt(), NULL); #elif defined(Q_OS_UNIX) g_object_set (sink, "device", QString("hw:%1").arg(p->deviceID).toLatin1().data(), NULL); #endif gst_object_unref(sink); } #if defined(Q_OS_WIN32) BOOL CALLBACK DSEnumProc(LPGUID lpGUID, const WCHAR* lpszDesc, const WCHAR* lpszDrvName, void *ctx) { if ( lpGUID ) { QList *l =reinterpret_cast *>(ctx); *l << dsDevice(QString::fromUtf16(reinterpret_cast(lpszDesc)), QUuid(*lpGUID)); } return(true); } #endif QString MonitorPlayer::defaultDeviceID() { #if defined(Q_OS_WIN32) GUID guid; //DSDEVID_DefaultVoicePlayback="{DEF00000-9C6D-47ED-AAF1-4DDA8F2B5C03}" const GUID defaultguid=QUuid("{DEF00000-9C6D-47ED-AAF1-4DDA8F2B5C03}"); if (GetDeviceID(&defaultguid, &guid) == DS_OK) { return QUuid(guid).toString(); } else return QString(); #elif defined(Q_OS_DARWIN) return QString("0"); #elif defined(Q_OS_UNIX) return QString("0"); #endif } void MonitorPlayer::readDevices() { #if defined(Q_OS_WIN32) p->devices.clear(); QList qlOutput; DirectSoundEnumerate(DSEnumProc, reinterpret_cast(&qlOutput)); foreach(dev, qlOutput) { p->devices.insert(dev.second.toString(),dev.first); } #elif defined(Q_OS_DARWIN) UInt32 dataSize = 0; AudioObjectPropertyAddress propertyAddress; propertyAddress.mSelector = kAudioHardwarePropertyDevices; propertyAddress.mScope = kAudioDevicePropertyScopeOutput; propertyAddress.mElement = kAudioObjectPropertyElementMaster; OSStatus status = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &dataSize); if(kAudioHardwareNoError != status) { qDebug()<<"Unable to get number of audio devices. Error: "<devices.clear(); for(UInt32 i = 0; i < deviceCount; i++) { CFStringRef deviceName = NULL; propertyAddress.mSelector = kAudioDevicePropertyStreamConfiguration; // probe for Inputstream if (AudioObjectGetPropertyData(audioDevices[i], &propertyAddress, 0, NULL, &dataSize, &deviceName) != noErr) { dataSize = sizeof(deviceName); propertyAddress.mSelector = kAudioDevicePropertyDeviceNameCFString; propertyAddress.mScope = kAudioDevicePropertyScopeOutput; status = AudioObjectGetPropertyData(audioDevices[i], &propertyAddress, 0, NULL, &dataSize, &deviceName); QString devName = CFStringGetCStringPtr(deviceName,CFStringGetSystemEncoding()); p->devices.insert(QString::number(audioDevices[i]),devName.trimmed() ); } } free(audioDevices); #elif defined(Q_OS_UNIX) int idx = 0; char* name; while(snd_card_get_name(idx,&name) == 0) { p->devices.insert(QString::number(idx),QString(name) ); idx++; } #endif } void MonitorPlayer::messageReceived(GstMessage *message) { switch (GST_MESSAGE_TYPE (message)) { case GST_MESSAGE_ERROR: { if ( p->error == "") { GError *err; gchar *debug; gst_message_parse_error (message, &err, &debug); p->error = "Error #"+QString::number(err->code)+" in module "+QString::number(err->domain)+"\n"+QString::fromUtf8(err->message); if(err->code == 6 && err->domain == 851) { p->error += "\nMay be you should to install gstreamer0.10-plugins-ugly or gstreamer0.10-plugins-bad"; } qDebug()<< "Gstreamer error:"<< p->error; g_error_free (err); g_free (debug); Q_EMIT error(); } break; } case GST_MESSAGE_EOS:{ qDebug() << Q_FUNC_INFO <<":"<objectName()<<" End of track reached"; Q_EMIT finish(); break; } case GST_MESSAGE_STATE_CHANGED: { GstState old_state, new_state; gst_message_parse_state_changed (message, &old_state, &new_state, NULL); switch(new_state){ case GST_STATE_PAUSED: case GST_STATE_NULL: rms_l=rms_r=0; default: break; } break; } case GST_MESSAGE_ELEMENT:{ const GstStructure *s = gst_message_get_structure (message); const gchar *src_name=GST_MESSAGE_SRC_NAME (message); if (strcmp (src_name, "level") == 0) { gint channels; gdouble peak_dB; gdouble rms; gint i; #ifdef GST_API_VERSION_1 const GValue *array_val; GValueArray *peak_arr; array_val = gst_structure_get_value (s, "peak"); peak_arr = (GValueArray *) g_value_get_boxed (array_val); channels = peak_arr->n_values; for (i = 0; i < channels; ++i) { peak_dB = g_value_get_double (peak_arr->values+i); #else const GValue *list; const GValue *value; list = gst_structure_get_value (s, "peak"); channels = gst_value_list_get_size (list); for (i = 0; i < channels; ++i) { list = gst_structure_get_value (s, "peak"); value = gst_value_list_get_value (list, i); peak_dB = g_value_get_double (value); #endif /* converting from dB to normal gives us a value between 0.0 and 1.0 */ rms = pow (10, peak_dB / 20); if (i==0) rms_l=rms; else rms_r=rms; } } } break; default: break; } } knowthelist-2.3.0/src/settingsdialog.ui0000775000175000017500000006541712423536022017256 0ustar mariomario SettingsDialog 0 0 703 512 600 400 Settings true 0 0 200 0 200 16777215 Qt::ScrollBarAlwaysOff Qt::ScrollBarAlwaysOff QAbstractItemView::SingleSelection QAbstractItemView::SelectRows 32 32 false Qt::SolidLine false false false 150 150 false 42 42 Row1 Row2 Row3 Row4 Row5 Row6 Row7 Column1 Fader Collection Audio devices AutoDJ Playlists File browser Common 2 0 3 10 10 251 16 Fader settings 10 80 160 22 30 12 Qt::Horizontal 10 60 371 16 0 0 Start fading before song end 10 40 388 16 QFrame::Plain Qt::Horizontal 190 80 61 16 12s 10 110 361 16 Fader Time 190 130 61 16 12s 10 130 160 22 30 12 Qt::Horizontal 10 170 371 20 Skip silent at start (AutoCue) true 10 200 371 20 Skip silent at the end true 1 0 Scan for new files and update the music collection Watch folders for changes 0 0 16777215 16777215 Qt::LeftToRight Scan Now Scan folders for songs Play Counter Statistics Reset 10 70 251 16 Monitor Player 10 90 201 26 10 10 251 16 Device Settings 10 40 388 16 QFrame::Plain Qt::Horizontal 10 10 251 16 AutoDJ settings 10 40 388 16 QFrame::Plain Qt::Horizontal 6 380 42 22 6 7 360 421 20 Minimum tracks within each playlist 7 90 42 22 1 7 70 131 16 DJ Count 120 90 281 251 QAbstractItemView::NoSelection 0 40 164 70 121 16 DJ Names 279 70 121 16 Filter Count 5 410 461 20 Increment play counter for AutoDj selected tracks 10 40 388 16 QFrame::Plain Qt::Horizontal 7 74 371 20 Auto Remove Played Tracks 10 10 251 16 Playlist Settings 10 88 291 26 10 66 361 16 Browser Root 310 86 50 30 ... 10 10 251 16 File Browser Settings 10 40 388 16 QFrame::Plain Qt::Horizontal 100 70 131 25 English Deutsch čeština magyar français 10 74 91 16 75 true Language 10 10 251 16 Common Settings 10 40 388 16 QFrame::Plain Qt::Horizontal 10 100 411 16 8 Change the language of the application (needs restart) 0 28 0 3 76 32 About 516 -2 164 32 0 0 Qt::RightToLeft Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok false buttonBox accepted() SettingsDialog accept() 248 254 157 274 buttonBox rejected() SettingsDialog reject() 316 260 286 274 knowthelist-2.3.0/src/player.cpp0000775000175000017500000004365212423536022015674 0ustar mariomario/* Copyright (C) 2005-2014 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #include "player.h" #include #if QT_VERSION >= 0x050000 #include #else #include #endif void Player::sync_set_state(GstElement* element, GstState state) { GstStateChangeReturn res; \ res = gst_element_set_state (GST_ELEMENT (element), state); \ if(res == GST_STATE_CHANGE_FAILURE) return; \ if(res == GST_STATE_CHANGE_ASYNC) { \ GstState state; \ res = gst_element_get_state(GST_ELEMENT (element), &state, NULL, GST_CLOCK_TIME_NONE); \ if(res == GST_STATE_CHANGE_FAILURE || res == GST_STATE_CHANGE_ASYNC) return; \ } } struct Player::Private { QFutureWatcher watcher; QMutex mutex; bool isStarted; bool isLoaded; QString error; }; void cb_newpad (GstElement *decodebin, GstPad *pad, gpointer data) { Player* instance = (Player*)data; instance->newpad(decodebin, pad, data); } void Player::newpad (GstElement *decodebin, GstPad *pad, gpointer data) { Q_UNUSED(decodebin); Q_UNUSED(data); GstCaps *caps; GstStructure *str; GstPad *audiopad; /* only link once */ GstElement *audio = gst_bin_get_by_name(GST_BIN(pipeline), "audiobin"); audiopad = gst_element_get_static_pad (audio, "sink"); gst_object_unref(audio); if (GST_PAD_IS_LINKED (audiopad)) { g_object_unref (audiopad); return; } /* check media type */ #ifdef GST_API_VERSION_1 caps = gst_pad_query_caps (pad,NULL); #else caps = gst_pad_get_caps (pad); #endif str = gst_caps_get_structure (caps, 0); if (!g_strrstr (gst_structure_get_name (str), "audio")) { gst_caps_unref (caps); gst_object_unref (audiopad); return; } gst_caps_unref (caps); /* link'n'play */ gst_pad_link (pad, audiopad); GstElement *valve = gst_bin_get_by_name(GST_BIN(pipeline), "valve"); g_object_set (valve, "drop", FALSE, NULL); } Player::Player(QWidget *parent) : QWidget(parent), pipeline(0), bus(0), Gstart(0), Glength(0) ,m_position(0) , p( new Private ) { p->isStarted=false; p->isLoaded=false; connect(&p->watcher, SIGNAL(finished()), this, SLOT(loadThreadFinished())); } Player::~Player() { delete p; p=0; cleanup(); } GstBusSyncReply Player::bus_cb (GstBus *bus, GstMessage *msg, gpointer data) { Q_UNUSED(bus); Player* instance = (Player*)data; instance->messageReceived(msg); return GST_BUS_PASS; } void Player::cleanup() { if(pipeline) sync_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL); if(bus) gst_object_unref (bus); if(pipeline) gst_object_unref(G_OBJECT(pipeline)); } bool Player::prepare() { //Init Gst // QString caps_value = "audio/x-raw"; // On mac we bundle the gstreamer plugins with knowthelist #if defined(Q_OS_DARWIN) QString scanner_path; QString plugin_path; QString registry_filename; QDir pd(QCoreApplication::applicationDirPath() + "/../plugins"); scanner_path = QCoreApplication::applicationDirPath() + "/../plugins/gst-plugin-scanner"; plugin_path = QCoreApplication::applicationDirPath() + "/../plugins/gstreamer"; registry_filename = QDesktopServices::storageLocation(QDesktopServices::DataLocation) + QString("/gst-registry-%1-bin").arg(QCoreApplication::applicationVersion()); if ( pd.exists()) setenv("GST_PLUGIN_SCANNER", scanner_path.toLocal8Bit().constData(), 1); if ( pd.exists()) { setenv("GST_PLUGIN_PATH", plugin_path.toLocal8Bit().constData(), 1); // Never load plugins from anywhere else. setenv("GST_PLUGIN_SYSTEM_PATH", plugin_path.toLocal8Bit().constData(), 1); } if (!registry_filename.isEmpty()) { setenv("GST_REGISTRY", registry_filename.toLocal8Bit().constData(), 1); } #elif defined(Q_OS_WIN32) QString plugin_path = QCoreApplication::applicationDirPath() + "/plugins"; QDir pluginDir(plugin_path); if ( pluginDir.exists()) _putenv_s("GST_PLUGIN_PATH", plugin_path.toLocal8Bit()); #endif //_putenv_s("GST_DEBUG", "*:4"); //win //setenv("GST_DEBUG", "*:3", 1); //unix gst_init (0, 0); //prepare GstElement *dec, *conv,*resample,*sink, *gain, *audio, *vol, *level, *equalizer; GstElement *levelout; GstPad *audiopad; GstCaps *caps; pipeline = gst_pipeline_new ("pipeline"); bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); #ifdef GST_API_VERSION_1 dec = gst_element_factory_make ("decodebin", "decoder"); #else dec = gst_element_factory_make ("decodebin2", "decoder"); caps_value = "audio/x-raw-int"; #endif caps = gst_caps_new_simple (caps_value.toLatin1().data(), "channels", G_TYPE_INT, 2, NULL); g_signal_connect (dec, "pad-added", G_CALLBACK (cb_newpad), this); gst_bin_add (GST_BIN (pipeline), dec); audio = gst_bin_new ("audiobin"); conv = gst_element_factory_make ("audioconvert", "aconv"); resample = gst_element_factory_make ("audioresample", "resample"); audiopad = gst_element_get_static_pad (conv, "sink"); gain = gst_element_factory_make ("audioamplify", "gain"); level = gst_element_factory_make ("level", "levelintern"); vol = gst_element_factory_make ("volume", "volume"); levelout = gst_element_factory_make ("level", "levelout"); equalizer = gst_element_factory_make ("equalizer-3bands", "equalizer"); sink = gst_element_factory_make ("autoaudiosink", "sink"); g_object_set (level, "message", TRUE, NULL); g_object_set (levelout, "message", TRUE, NULL); g_object_set (level, "peak-ttl", 300000000000, NULL); gst_bin_add_many (GST_BIN (audio), conv, resample, level, gain, equalizer, levelout, vol, sink, NULL); gst_element_link (conv,resample); gst_element_link_filtered (resample, level, caps); gst_element_link (level, gain); gst_element_link (gain, equalizer); gst_element_link (equalizer, vol); gst_element_link_filtered (vol, levelout, caps); gst_element_link (levelout,sink); gst_element_add_pad (audio, gst_ghost_pad_new ("sink", audiopad)); gst_bin_add (GST_BIN (pipeline), audio); GstElement *l_src; l_src = gst_element_factory_make ("filesrc", "localsrc"); gst_bin_add_many (GST_BIN (pipeline), l_src, NULL); gst_element_set_state (l_src, GST_STATE_NULL); gst_element_link ( l_src,dec); #ifdef GST_API_VERSION_1 gst_bus_set_sync_handler (bus, bus_cb, this, NULL); #else gst_bus_set_sync_handler (bus, bus_cb, this); #endif gst_object_unref (audiopad); return pipeline; } bool Player::ready() { return pipeline; } void Player::setGain(double g) { gdouble gain_value = 1.00 * g; GstElement *gain = gst_bin_get_by_name(GST_BIN(pipeline), "gain"); g_object_set (G_OBJECT(gain), "amplification", gain_value, NULL); gst_object_unref(gain); } void Player::setEqualizer(QString band, double gain) { gdouble gain_value = 1.00 * gain; GstElement *equalizer = gst_bin_get_by_name(GST_BIN(pipeline), "equalizer"); g_object_set (G_OBJECT(equalizer), band.toLatin1().data(), gain_value, NULL); gst_object_unref(equalizer); } void Player::open(QUrl url) { //To avoid delays load track in another thread qDebug() << Q_FUNC_INFO <<":"<objectName()<<" url="< future = QtConcurrent::run( this, &Player::asyncOpen,url); p->watcher.setFuture(future); } void Player::asyncOpen(QUrl url) { p->mutex.lock(); m_length = 0; m_position = 0; p->isLoaded=false; p->error=""; lastError=""; sync_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL); GstElement *l_src = gst_bin_get_by_name(GST_BIN(pipeline), "localsrc"); g_object_set (G_OBJECT (l_src), "location", (const char*)url.toLocalFile().toUtf8(), NULL); sync_set_state (GST_ELEMENT (pipeline), GST_STATE_PAUSED); setPosition(QTime(0,0)); gst_object_unref(l_src); p->mutex.unlock(); } void Player::loadThreadFinished() { // async load in player done qDebug() << Q_FUNC_INFO <<":"<objectName(); p->isLoaded=true; emit loadFinished(); if (p->isStarted) { play(); } } void Player::play() { p->isStarted=true; qDebug() << Q_FUNC_INFO <<":"<objectName(); if (p->isLoaded) { gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING); } } void Player::stop() { p->isStarted=false; gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_READY); } void Player::pause() { if(isPlaying()){ p->isStarted=false; gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PAUSED); } } bool Player::close() { gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL); return true; } void Player::setPosition(QTime position) { int time_milliseconds=QTime(0,0).msecsTo(position); gint64 time_nanoseconds=( time_milliseconds * GST_MSECOND ); gst_element_seek (pipeline, 1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, time_nanoseconds, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE); m_position=time_milliseconds; emit positionChanged(); } QTime Player::position() { if (pipeline) { gint64 value=0; #ifdef GST_API_VERSION_1 if(gst_element_query_position(pipeline, GST_FORMAT_TIME, &value)) { #else GstFormat fmt = GST_FORMAT_TIME; if(gst_element_query_position(pipeline, &fmt, &value)) { #endif m_position = static_cast( ( value / GST_MSECOND ) ); return QTime(0,0).addMSecs( m_position ); // nanosec -> msec } return QTime(0,0).addMSecs( m_position ); // nanosec -> msec } return QTime(0,0); } QTime Player::length() { gint64 value=0; if ( m_length == 0 && pipeline){ #ifdef GST_API_VERSION_1 if(gst_element_query_duration(pipeline, GST_FORMAT_TIME, &value)) { #else GstFormat fmt = GST_FORMAT_TIME; if(gst_element_query_duration(pipeline, &fmt, &value)) { #endif m_length = static_cast( ( value / GST_MSECOND )); } qDebug() << Q_FUNC_INFO <<": Can not get duration"; } return QTime(0,0).addMSecs( m_length ); // nanosec -> msec } double Player::volume() { gdouble vol = 0; GstElement *volume = gst_bin_get_by_name(GST_BIN(pipeline), "volume"); g_object_get (G_OBJECT(volume), "volume", &vol, NULL); gst_object_unref(volume); return vol; } void Player::setVolume(double v) { gdouble vol = 1.00 * v; //gdouble vol = 0.01 * v; GstElement *volume = gst_bin_get_by_name(GST_BIN(pipeline), "volume"); g_object_set (G_OBJECT(volume), "volume", vol, NULL); gst_object_unref(volume); } bool Player::mediaPlayable() { GstState st; gst_element_get_state (GST_ELEMENT (pipeline), &st, 0, 0); //qDebug()<error; } case GST_MESSAGE_ERROR: { if ( p->error == "") { GError *err; gchar *debug; gst_message_parse_error (message, &err, &debug); p->error = "Error #"+QString::number(err->code)+" in module "+QString::number(err->domain)+"\n"+QString::fromUtf8(err->message); if(err->domain != GST_STREAM_ERROR && err->code != GST_STREAM_ERROR_FAILED) { p->error += "\nMay be you should install more of gstreamer plugins"; lastError = QString::fromUtf8(err->message); } qDebug() << Q_FUNC_INFO <<": Gstreamer error:"<< p->error; g_error_free (err); g_free (debug); Q_EMIT error(); } break; } case GST_MESSAGE_EOS:{ qDebug() << Q_FUNC_INFO <<":"<objectName()<<" End of track reached"; Q_EMIT finish(); break; } case GST_MESSAGE_STATE_CHANGED: { GstState old_state, new_state; gst_message_parse_state_changed (message, &old_state, &new_state, NULL); switch(new_state){ case GST_STATE_PAUSED: case GST_STATE_NULL: rms_l=rms_r=0; rmsout_l=rmsout_r=0; default: break; } break; } case GST_MESSAGE_ELEMENT:{ const GstStructure *s = gst_message_get_structure (message); const gchar *src_name=GST_MESSAGE_SRC_NAME (message); if (strcmp (src_name, "levelintern") == 0) { gint channels; gdouble peak_dB; gdouble rms; gint i; #ifdef GST_API_VERSION_1 const GValue *array_val; GValueArray *peak_arr; array_val = gst_structure_get_value (s, "peak"); peak_arr = (GValueArray *) g_value_get_boxed (array_val); channels = peak_arr->n_values; for (i = 0; i < channels; ++i) { peak_dB = g_value_get_double (peak_arr->values+i); #else const GValue *list; const GValue *value; list = gst_structure_get_value (s, "peak"); channels = gst_value_list_get_size (list); for (i = 0; i < channels; ++i) { list = gst_structure_get_value (s, "peak"); value = gst_value_list_get_value (list, i); peak_dB = g_value_get_double (value); #endif /* converting from dB to normal gives us a value between 0.0 and 1.0 */ rms = pow (10, peak_dB / 20); if (i==0) rms_l=rms; else rms_r=rms; } } if (strcmp (src_name, "levelout") == 0) { gint channels; gdouble peak_dB; gdouble rms; gint i; #ifdef GST_API_VERSION_1 const GValue *array_val; GValueArray *peak_arr; array_val = gst_structure_get_value (s, "peak"); peak_arr = (GValueArray *) g_value_get_boxed (array_val); channels = peak_arr->n_values; for (i = 0; i < channels; ++i) { peak_dB = g_value_get_double (peak_arr->values+i); #else const GValue *list; const GValue *value; list = gst_structure_get_value (s, "peak"); channels = gst_value_list_get_size (list); for (i = 0; i < channels; ++i) { list = gst_structure_get_value (s, "peak"); value = gst_value_list_get_value (list, i); peak_dB = g_value_get_double (value); #endif /* converting from dB to normal gives us a value between 0.0 and 1.0 */ rms = pow (10, peak_dB / 20); if (i==0) rmsout_l=rms; else rmsout_r=rms; } } } break; default: break; } } knowthelist-2.3.0/src/filebrowser.cpp0000775000175000017500000000437012423536022016715 0ustar mariomario/* Copyright (C) 2005-2014 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #include "filebrowser.h" #include #include #include #include #include #if QT_VERSION >= 0x050000 #include #else #include #endif struct FileBrowserPrivate { QVBoxLayout *layout; QTreeView *filetree; QFileSystemModel *model; }; FileBrowser::FileBrowser(QWidget *parent) : QWidget(parent) , p( new FileBrowserPrivate ) { p->layout = new QVBoxLayout; // ToDo: maybe we add some buttons and links here p->model = new QFileSystemModel; p->model->setRootPath(QDir::currentPath()); p->filetree = new QTreeView(this); p->filetree->setModel(p->model); p->filetree->setDragEnabled(true); p->filetree->setSelectionMode(QAbstractItemView::ContiguousSelection); p->filetree->header()->resizeSection(0,400); #if QT_VERSION >= 0x050000 p->filetree->setRootIndex(p->model->index(QStandardPaths::standardLocations(QStandardPaths::MusicLocation).at(0))); #else p->filetree->setRootIndex(p->model->index(QDesktopServices::storageLocation(QDesktopServices::MusicLocation))); #endif p->filetree->setAttribute(Qt::WA_MacShowFocusRect, false); p->layout->addWidget(p->filetree); setLayout(p->layout); setAttribute(Qt::WA_MacShowFocusRect, false); } void FileBrowser::setRootPath(QString path){ p->filetree->setRootIndex(p->model->setRootPath(path)); } knowthelist-2.3.0/src/knowthelist.ui0000775000175000017500000107352212423536022016606 0ustar mariomario Knowthelist 0 0 1280 695 Knowthelist ../dist/knowthelist.png../dist/knowthelist.png QPushButton { color: white; border: 1.5px solid #333333; border-radius: 4px; padding: 1px; background: qlineargradient( x1:0, y1:0, x2:0, y2:1, stop: 0.1 #999999, stop:0.5 #505050, stop:1 black ); max-height: 16px; min-height: 10px; } QPushButton:pressed { background: qlineargradient( x1:0, y1:0, x2:0, y2:1, stop: 0.1 black, stop:0.5 #505050, stop:1 #999999 ); } QToolButton { color: white; border: 1.5px solid #333333; border-radius: 4px; padding: 1px; background: qlineargradient( x1:0, y1:0, x2:0, y2:1, stop: 0.1 #999999, stop:0.5 #505050, stop:1 black ); max-height: 20px; min-height: 20px; } QToolButton:pressed { background: qlineargradient( x1:0, y1:0, x2:0, y2:1, stop: 0.1 black, stop:0.5 #505050, stop:1 #999999 ); } QDial { color: white; background: qlineargradient( x1:0, y1:0, x2:0, y2:1, stop: 0.1 #999999, stop:0.5 #505050, stop:1 white ); max-height: 32px; min-height: 32px; } QSplitter { color: black; } QSplitter::handle { background: qlineargradient( x1:0, y1:0, x2:0, y2:1, stop: 0 #555, stop: 0.49 #222, stop:0.5 #aaa, stop:0.51 #222, stop:1 #000 ); } QSlider::handle:horizontal { background: qlineargradient( x1:0, y1:0, x2:1, y2:0, stop: 0 #000, stop: 0.1 #222, stop: 0.38 #444, stop:0.5 #ccc, stop:0.6 #444, stop:0.9 #222, stop:1 #000 ); border: 1px solid #5c5c5c; width: 18px; margin: 1px 0; /* handle is placed by default on the contents rect of the groove. Expand outside the groove */ border-radius: 3px; } QSlider::handle:vertical { background: qlineargradient( x1:0, y1:0, x2:0, y2:1, stop: 0 #000, stop: 0.1 #222, stop: 0.38 #444, stop:0.5 #ccc, stop:0.6 #444, stop:0.9 #222, stop:1 #000 ); border: 1px solid #5c5c5c; width: 12px; height: 18px; max-height:15px; margin: 0 2px; /* handle is placed by default on the contents rect of the groove. Expand outside the groove */ border-radius: 3px; } QFrame#frameMixer{ background: qlineargradient( x1:0, y1:0, x2:0, y2:1, stop: 0.1 #999999, stop:0.5 #505050, stop:1 black ); } QCheckBox { color: rgb(200, 200, 200); background-color: #444444; } QLabel, QTreeView { color: #e1e1e1; } QDialog { background-color: #444444; } QWidget#centralwidget{ background: qlineargradient( x1:0, y1:0, x2:0, y2:1, stop: 0.1 #999999, stop:0.5 #505050, stop:1 black ); } QLineEdit { margin: 2 2 2 3; border: 2px solid gray; border-radius: 6px; padding: 2px 2px; background: #dddddd; selection-background-color: darkgray; } SearchEdit { padding: 0px 18px; font-size:14px; } QTreeWidget, QTreeView{ selection-background-color: gray; selection-color: white; } QMenu { background-color: #333333; color: #B8C1C6; } QListWidget,QTreeView { background-color: #333333; } QListView { show-decoration-selected: 1; /* make the selection span the entire width of the view */ } QListView::item:alternate { background: #EEEEEE; } QListView::item:selected { border: 1px solid #6a6ea9; background: #EEEEEE; } QListView::item:selected:!active { background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ABAFE5, stop: 1 #8588B2); } QListView::item:selected:active { background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6a6ea9, stop: 1 #888dd9); } QListView::item:hover { background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #FAFBFE, stop: 1 #DCDEF1); } QScrollBar:horizontal { border: 2px solid grey; background: qlineargradient( x1:0, y1:0, x2:0, y2:1, stop:0.1 #505050, stop:1 gray ); height: 15px; margin: 0px 20px 0 20px; } QScrollBar::handle:horizontal { background: qlineargradient( x1:0, y1:0, x2:0, y2:1, stop:0.1 white, stop:1 gray ); min-width: 20px; } QScrollBar::add-line:horizontal { border: 2px solid grey; background: qlineargradient( x1:0, y1:0, x2:0, y2:1, stop:0.1 #505050, stop:1 black ); width: 20px; subcontrol-position: right; subcontrol-origin: margin; } QScrollBar::sub-line:horizontal { border: 2px solid grey; background: qlineargradient( x1:0, y1:0, x2:0, y2:1, stop:0.1 #505050, stop:1 black ); width: 20px; subcontrol-position: left; subcontrol-origin: margin; } QScrollBar:left-arrow:horizontal, QScrollBar::right-arrow:horizontal { border: 2px solid grey; width: 3px; height: 3px; background: white; } QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal { background: none; } DjSettings { border: 1px solid #6a6ea9; background: #EEEEEE; } QScrollBar:vertical { border: 2px solid grey; background: qlineargradient( x1:0, y1:0, x2:1, y2:0, stop:0.1 #505050, stop:1 gray ); width: 15px; } QScrollBar::handle:vertical { background: qlineargradient( x1:0, y1:0, x2:1, y2:0, stop:0.1 white, stop:1 gray ); max-height: 16px; min-height: 16px; margin: 17px 0px 17px 0px; } QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical { border: 2px solid grey; background: white; } QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { background: none; } QListWidget::item:focus { background: transparent; } QListWidget::item:hover { background: transparent; } QHeaderView::section { background-color: qlineargradient( x1:0, y1:0, x2:0, y2:1, stop: 0.01 #202020, stop:0.11 #505050, stop:1 #505050 ); color: white; padding-left: 4px; padding-top: 2px; padding-bottom: 3px; border: 0px solid #6c6c6c; } QPushButton#pushClose { color: #333333; border-style: inset; border: .5px solid #333333; border-radius: 4px; background: #555555; max-height: 22px; min-height: 22px; min-width:10px; max-width:10px; } QPushButton#butPlayWidget { color: white; border-style: inset; border: 1.5px solid #333333; border-radius: 4px; padding: 1px; background: qlineargradient( x1:0, y1:0, x2:0, y2:0.3, stop:0.1 white, stop:1 #666666 ); max-height: 19px; min-height: 19px; } QPushButton#butPlayWidget:pressed { background: qlineargradient( x1:0, y1:0, x2:0, y2:0.3, stop:0.1 white, stop:1 #82df52 ); } RatingWidget { background-color: #333333; } QMessageBox,QInputDialog{ background-color: #bbbbbb; color: #1c1c1c; } QToolTip{ color: #ffffff; background-color: #444444; border: 1px solid #cccccc; border-radius: 12px; } QMainWindow { border: 1px solid white; border-radius: 3px; background: qradialgradient( cx: 0.5, cy: -1.8, fx: 0.5, fy: 0, radius: 2, stop: 0 #9aa9be, stop: 1 #293859); } 6 4 6 6 0 0 0 QLayout::SetMaximumSize QLayout::SetMaximumSize 0 0 0 111 0 1 0 0 0 0 frameMixer 55 1 194 329 0 1 21 0 QFrame::StyledPanel QFrame::Raised 71 134 23 109 102 134 23 109 QFrame::StyledPanel QFrame::Raised 35 279 6 26 7 7 46 109 246 200 72 314 51 18 0 16 255 255 255 153 153 153 80 80 80 0 0 0 255 255 255 221 221 221 93 93 93 124 124 124 255 255 255 255 255 255 255 255 255 153 153 153 80 80 80 0 0 0 153 153 153 80 80 80 0 0 0 0 0 0 0 0 128 255 255 255 0 0 0 0 0 0 255 255 255 153 153 153 80 80 80 0 0 0 255 255 255 215 215 215 93 93 93 124 124 124 255 255 255 255 255 255 255 255 255 153 153 153 80 80 80 0 0 0 153 153 153 80 80 80 0 0 0 0 0 0 0 0 128 255 255 255 0 0 0 0 0 0 255 255 255 153 153 153 80 80 80 0 0 0 255 255 255 215 215 215 93 93 93 124 124 124 255 255 255 255 255 255 255 255 255 153 153 153 80 80 80 0 0 0 153 153 153 80 80 80 0 0 0 0 0 0 0 0 128 255 255 255 0 0 0 0 0 0 7 Fader true false false false 49 307 12 7 7 7 35 119 246 200 91 307 12 7 7 7 35 119 246 200 32 314 40 18 0 16 255 255 255 153 153 153 80 80 80 0 0 0 255 255 255 221 221 221 93 93 93 124 124 124 255 255 255 255 255 255 255 255 255 153 153 153 80 80 80 0 0 0 153 153 153 80 80 80 0 0 0 0 0 0 0 0 128 255 255 255 0 0 0 0 0 0 255 255 255 153 153 153 80 80 80 0 0 0 255 255 255 215 215 215 93 93 93 124 124 124 255 255 255 255 255 255 255 255 255 153 153 153 80 80 80 0 0 0 153 153 153 80 80 80 0 0 0 0 0 0 0 0 128 255 255 255 0 0 0 0 0 0 255 255 255 153 153 153 80 80 80 0 0 0 255 255 255 215 215 215 93 93 93 124 124 124 255 255 255 255 255 255 255 255 255 153 153 153 80 80 80 0 0 0 153 153 153 80 80 80 0 0 0 0 0 0 0 0 128 255 255 255 0 0 0 0 0 0 7 AutoD&J Alt+J true false 156 279 6 26 7 7 35 119 246 200 123 314 41 18 41 16 255 255 255 153 153 153 80 80 80 0 0 0 255 255 255 221 221 221 93 93 93 124 124 124 255 255 255 255 255 255 255 255 255 153 153 153 80 80 80 0 0 0 153 153 153 80 80 80 0 0 0 0 0 0 0 0 128 255 255 255 0 0 0 0 0 0 255 255 255 153 153 153 80 80 80 0 0 0 255 255 255 215 215 215 93 93 93 124 124 124 255 255 255 255 255 255 255 255 255 153 153 153 80 80 80 0 0 0 153 153 153 80 80 80 0 0 0 0 0 0 0 0 128 255 255 255 0 0 0 0 0 0 255 255 255 153 153 153 80 80 80 0 0 0 255 255 255 215 215 215 93 93 93 124 124 124 255 255 255 255 255 255 255 255 255 153 153 153 80 80 80 0 0 0 153 153 153 80 80 80 0 0 0 0 0 0 0 0 128 255 255 255 0 0 0 0 0 0 7 Set 29 132 31 110 232 232 232 154 169 190 41 56 89 255 255 255 226 226 226 99 99 99 132 132 132 255 255 255 255 255 255 255 255 255 154 169 190 41 56 89 154 169 190 41 56 89 0 0 0 0 0 128 255 255 255 0 0 0 0 0 0 232 232 232 154 169 190 41 56 89 255 255 255 227 227 227 99 99 99 132 132 132 255 255 255 255 255 255 255 255 255 154 169 190 41 56 89 154 169 190 41 56 89 0 0 0 0 0 128 255 255 255 83 83 120 0 64 0 232 232 232 154 169 190 41 56 89 255 255 255 227 227 227 99 99 99 132 132 132 128 128 128 255 255 255 128 128 128 154 169 190 41 56 89 154 169 190 41 56 89 0 0 0 0 0 128 255 255 255 83 83 120 0 64 0 100 57 Qt::Vertical QSlider::TicksBothSides 34 247 125 30 232 232 232 154 169 190 41 56 89 255 255 255 220 220 220 93 93 93 124 124 124 0 0 0 255 255 255 0 0 0 154 169 190 41 56 89 154 169 190 41 56 89 0 0 0 0 0 128 255 255 255 0 0 0 0 0 0 232 232 232 154 169 190 41 56 89 255 255 255 213 213 213 93 93 93 124 124 124 0 0 0 255 255 255 0 0 0 154 169 190 41 56 89 154 169 190 41 56 89 0 0 0 0 0 128 255 255 255 83 83 120 0 64 0 232 232 232 154 169 190 41 56 89 255 255 255 213 213 213 93 93 93 124 124 124 128 128 128 255 255 255 128 128 128 154 169 190 41 56 89 154 169 190 41 56 89 0 0 0 0 0 128 255 255 255 83 83 120 0 64 0 200 21 Qt::Horizontal QSlider::TicksBothSides 136 132 31 110 232 232 232 154 169 190 41 56 89 255 255 255 222 222 222 94 94 94 126 126 126 0 0 0 255 255 255 0 0 0 154 169 190 41 56 89 154 169 190 41 56 89 0 0 0 0 0 128 255 255 255 0 0 0 0 0 0 232 232 232 154 169 190 41 56 89 255 255 255 217 217 217 94 94 94 126 126 126 0 0 0 255 255 255 0 0 0 154 169 190 41 56 89 154 169 190 41 56 89 0 0 0 0 0 128 255 255 255 83 83 120 0 64 0 232 232 232 154 169 190 41 56 89 255 255 255 217 217 217 94 94 94 126 126 126 128 128 128 255 255 255 128 128 128 154 169 190 41 56 89 154 169 190 41 56 89 0 0 0 0 0 128 255 255 255 83 83 120 0 64 0 100 11 Qt::Vertical QSlider::TicksBothSides 40 279 117 26 117 26 117 26 255 255 255 153 153 153 80 80 80 0 0 0 255 255 255 221 221 221 93 93 93 124 124 124 255 255 255 255 255 255 255 255 255 153 153 153 80 80 80 0 0 0 153 153 153 80 80 80 0 0 0 0 0 0 0 0 128 255 255 255 0 0 0 0 0 0 255 255 255 153 153 153 80 80 80 0 0 0 255 255 255 215 215 215 93 93 93 124 124 124 255 255 255 255 255 255 255 255 255 153 153 153 80 80 80 0 0 0 153 153 153 80 80 80 0 0 0 0 0 0 0 0 128 255 255 255 0 0 0 0 0 0 255 255 255 153 153 153 80 80 80 0 0 0 255 255 255 215 215 215 93 93 93 124 124 124 255 255 255 255 255 255 255 255 255 153 153 153 80 80 80 0 0 0 153 153 153 80 80 80 0 0 0 0 0 0 0 0 128 255 255 255 0 0 0 0 0 0 9 QPushButton { color: white; border: 1.5px solid black; border-radius: 4px; padding: 1px; background: qlineargradient( x1:0, y1:0, x2:0, y2:1, stop:0 #505050, stop: 0.4 #808080, stop: 0.5 #606060 stop:1 black ); max-height: 10px; min-height: 16px; } FadeNo&w Alt+W false 43 1 33 32 -240 120 4 -60 true false false false true 43 33 33 32 -240 120 4 0 true true 43 65 33 32 -240 120 4 true true 119 1 33 32 -240 120 4 true true 119 33 33 32 -240 120 4 true true 119 65 33 32 -240 120 4 true true 43 99 33 32 10 180 4 100 true true 119 99 33 32 10 180 4 100 true true 9 101 35 16 7 Gain Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 82 98 31 16 255 255 255 153 153 153 80 80 80 0 0 0 255 255 255 221 221 221 93 93 93 124 124 124 255 255 255 255 255 255 255 255 255 153 153 153 80 80 80 0 0 0 153 153 153 80 80 80 0 0 0 0 0 0 0 0 128 255 255 255 0 0 0 0 0 0 255 255 255 153 153 153 80 80 80 0 0 0 255 255 255 215 215 215 93 93 93 124 124 124 255 255 255 255 255 255 255 255 255 153 153 153 80 80 80 0 0 0 153 153 153 80 80 80 0 0 0 0 0 0 0 0 128 255 255 255 0 0 0 0 0 0 255 255 255 153 153 153 80 80 80 0 0 0 255 255 255 215 215 215 93 93 93 124 124 124 255 255 255 255 255 255 255 255 255 153 153 153 80 80 80 0 0 0 153 153 153 80 80 80 0 0 0 0 0 0 0 0 128 255 255 255 0 0 0 0 0 0 7 AGC Alt+J true false 91 90 12 7 7 7 35 119 246 200 153 101 36 16 7 Gain 9 67 35 16 7 Low Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 153 67 36 16 7 Low 1 37 42 16 7 Mid Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 153 37 42 16 7 Mid 9 3 35 16 7 Qt::LeftToRight High Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 153 3 36 16 7 High QLayout::SetMaximumSize 0 0 0 111 0 1 0 0 0 3 0 0 132 0 132 16777215 0 10 0 0 0 0 0 0 126 16777215 16777215 QFrame::NoFrame QFrame::Raised 40 7 27 75 5 7 31 77 232 232 232 154 169 190 41 56 89 255 255 255 222 222 222 94 94 94 126 126 126 0 0 0 255 255 255 0 0 0 154 169 190 41 56 89 154 169 190 41 56 89 0 0 0 0 0 128 255 255 255 0 0 0 0 0 0 232 232 232 154 169 190 41 56 89 255 255 255 217 217 217 94 94 94 126 126 126 0 0 0 255 255 255 0 0 0 154 169 190 41 56 89 154 169 190 41 56 89 0 0 0 0 0 128 255 255 255 83 83 120 0 64 0 232 232 232 154 169 190 41 56 89 255 255 255 217 217 217 94 94 94 126 126 126 128 128 128 255 255 255 128 128 128 154 169 190 41 56 89 154 169 190 41 56 89 0 0 0 0 0 128 255 255 255 83 83 120 0 64 0 100 Qt::Vertical QSlider::TicksBothSides 4 88 61 20 225 225 225 154 169 190 41 56 89 225 225 225 225 225 225 154 169 190 41 56 89 154 169 190 41 56 89 225 225 225 154 169 190 41 56 89 225 225 225 225 225 225 154 169 190 41 56 89 154 169 190 41 56 89 225 225 225 154 169 190 41 56 89 225 225 225 225 225 225 154 169 190 41 56 89 154 169 190 41 56 89 9 0:00.0 77 19 41 26 64 87 51 20 225 225 225 154 169 190 41 56 89 225 225 225 225 225 225 154 169 190 41 56 89 154 169 190 41 56 89 225 225 225 154 169 190 41 56 89 225 225 225 225 225 225 154 169 190 41 56 89 154 169 190 41 56 89 225 225 225 154 169 190 41 56 89 225 225 225 225 225 225 154 169 190 41 56 89 154 169 190 41 56 89 9 -0:00.0 Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 4 108 111 16 0 0 18 1000 100 Qt::Horizontal true 77 57 41 26 QFrame::NoFrame QFrame::Raised 0 0 0 0 0 75 true 225 225 225 154 169 190 41 56 89 225 225 225 225 225 225 154 169 190 41 56 89 154 169 190 41 56 89 225 225 225 154 169 190 41 56 89 225 225 225 225 225 225 154 169 190 41 56 89 154 169 190 41 56 89 225 225 225 154 169 190 41 56 89 225 225 225 225 225 225 154 169 190 41 56 89 154 169 190 41 56 89 10 MonitorPlayer Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop true 0 120 120 120 120 true 0 0 0 33 16777215 35 color: rgb(255, 0, 0); <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="settings"><span style=" font-size:8pt; color:#df0000;">No 2nd soundcard selected!</span></a></p></body></html> true Settings QLed QWidget
qled.h
1
PlayerWidget QWidget
playerwidget.h
1
Playlist QWidget
playlist.h
1
FancyTabWidget QWidget
fancytabwidget.h
1
QVUMeter QWidget
qvumeter.h
1
toggleAutoFade toggleAutoDJ cmdOptions slider1 sliFader slider2 cmdFade potHigh_1 potMid_1 potLow_1 potHigh_2 potMid_2 potLow_2
knowthelist-2.3.0/src/ratingwidget.cpp0000664000175000017500000000700012423536022017050 0ustar mariomario/* Copyright 2010, David Sansome Copyright (C) 2005-2014 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #include "ratingwidget.h" #include #include #include const int RatingPainter::kStarCount; const int RatingPainter::kStarSize; RatingPainter::RatingPainter() { } QRect RatingPainter::Contents(const QRect& rect) { const int width = kStarSize * kStarCount; return QRect(rect.x(), rect.y(), width, rect.height()); } double RatingPainter::RatingForPos(const QPoint& pos, const QRect& rect) { const QRect contents = Contents(rect); const double raw = double(pos.x() - contents.left()) / contents.width(); // Round to the nearest 0.1 return double(int(raw * kStarCount * 2 + 0.5)) / (kStarCount * 2); } void RatingPainter::Paint(QPainter* painter, const QRect& rect, float rating) const { Q_UNUSED(rect); // save some time here if (rating==0) return; rating *= kStarCount; QPixmap on(":/star-on.png"); QPixmap off(":/star-off.png"); // Draw the stars int x=kStarSize/2; for(int i=0; idrawPixmap(t_rect, off); } else if (rating - 0.75 <= i) { // Half full const QRect target_left(t_rect.x(), t_rect.y(), kStarSize/2, kStarSize); const QRect target_right(t_rect.x() + kStarSize/2, t_rect.y(), kStarSize/2, kStarSize); const QRect source_left(0, 0, kStarSize/2, kStarSize); const QRect source_right(kStarSize/2, 0, kStarSize/2, kStarSize); painter->drawPixmap(target_left, on, source_left); painter->drawPixmap(target_right, off, source_right); } else { // Totally full painter->drawPixmap(t_rect, on); } } } RatingWidget::RatingWidget(QWidget* parent) : QWidget(parent), rating_(0.0), hover_rating_(-1.0) { setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); setMouseTracking(true); } QSize RatingWidget::sizeHint() const { return QSize(RatingPainter::kStarSize * (RatingPainter::kStarCount+2), RatingPainter::kStarSize); } void RatingWidget::setRating(float rating) { rating_ = rating; update(); } void RatingWidget::paintEvent(QPaintEvent* e) { Q_UNUSED(e); QStylePainter p(this); // Draw the stars painter_.Paint(&p, rect(), hover_rating_ == -1.0 ? rating_ : hover_rating_); } void RatingWidget::mousePressEvent(QMouseEvent* e) { rating_ = RatingPainter::RatingForPos(e->pos(), rect()); emit RatingChanged(rating_); } void RatingWidget::mouseMoveEvent(QMouseEvent* e) { hover_rating_ = RatingPainter::RatingForPos(e->pos(), rect()); update(); } void RatingWidget::leaveEvent(QEvent*) { hover_rating_ = -1.0; update(); } knowthelist-2.3.0/src/djfilterwidget.cpp0000775000175000017500000001517712423536022017410 0ustar mariomario/* Copyright (C) 2005-2014 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #include "djfilterwidget.h" #include "ui_djfilterwidget.h" #include #include #include #include struct DjFilterWidgetPrivate { Filter* filter; QTimer* timerSlide; int targetWidth; }; DjFilterWidget::DjFilterWidget(QWidget *parent) : QWidget(parent), ui(new Ui::DjFilterWidget) ,p(new DjFilterWidgetPrivate) { setFocusPolicy(Qt::ClickFocus); ui->setupUi(this); ui->ledActive->setLook(QLed::Flat); ui->ledActive->setShape(QLed::Rectangular); ui->ledActive->setColor(QColor(35,119,246)); ui->ledActive->off(); ui->txtPath->setAttribute(Qt::WA_MacShowFocusRect, false); ui->cmbGenres->setAttribute(Qt::WA_MacShowFocusRect, false); ui->cmbArtists->setAttribute(Qt::WA_MacShowFocusRect, false); #if defined(Q_OS_DARWIN) ui->cmbArtists->setStyleSheet("QComboBox { margin: 0 3 0 3;}"); ui->cmbGenres->setStyleSheet("QComboBox { margin: 0 3 0 3;}"); ui->fraFilterTextBoxes->layout()->setContentsMargins(0,13,13,14); ui->fraFilterTextBoxes->layout()->setSpacing(-1); #endif ui->lblFilterValue->setText( QString::null ); ui->sliFilterValue->setValue( 0 ); ui->stackDisplay->setCount( 0 ); ui->stackDisplay->setBarColor(QColor( 196,196,210)); ui->widgetClose->setMinimumWidth(0); ui->widgetClose->setMaximumWidth(0); timer = new QTimer( this ); timer->stop(); timer->setInterval(300); timer->setSingleShot(true); connect( timer,SIGNAL(timeout()),this,SLOT( slotSetFilter() )); p->timerSlide = new QTimer(this); p->timerSlide->setInterval(10); connect( p->timerSlide, SIGNAL(timeout()), SLOT(timerSlide_timeOut()) ); } DjFilterWidget::~DjFilterWidget() { delete ui; delete p; } void DjFilterWidget::changeEvent(QEvent *e) { QWidget::changeEvent(e); switch (e->type()) { case QEvent::LanguageChange: ui->retranslateUi(this); break; default: break; } } void DjFilterWidget::mousePressEvent(QMouseEvent *event) { if(ui->widgetClose->geometry().contains(event->pos())) { Q_EMIT deleted(); } else{ slideCloseWidget(false); } } void DjFilterWidget::slotSetFilter() { qDebug() << Q_FUNC_INFO ; timer->stop(); p->filter->setPath(ui->txtPath->text()); p->filter->setGenre(ui->cmbGenres->currentText()); p->filter->setArtist(ui->cmbArtists->currentText()); p->filter->update(); } void DjFilterWidget::setAllArtists(QStringList values) { ui->cmbArtists->addItems(values ); } void DjFilterWidget::setAllGenres(QStringList& values) { ui->cmbGenres->addItems(values ); } void DjFilterWidget::setID(QString value) { ui->lblNumber->setText(value); } void DjFilterWidget::setFilter(Filter* filter) { timer->stop(); p->filter = filter; onFilterCountChanged(); onFilterMaxUsageChanged(); ui->txtPath->setText(p->filter->path()); ui->cmbGenres->setEditText(p->filter->genre()); ui->cmbArtists->setEditText(p->filter->artist()); connect(p->filter,SIGNAL(statusChanged(bool)), this,SLOT(onFilterStatusChanged(bool))); connect(p->filter,SIGNAL(countChanged()), this,SLOT(onFilterCountChanged())); connect(p->filter,SIGNAL(usageChanged()), this,SLOT(onFilterUsageChanged())); connect(p->filter,SIGNAL(maxUsageChanged()), this,SLOT(onFilterMaxUsageChanged())); } Filter* DjFilterWidget::filter() { return p->filter; } void DjFilterWidget::on_sliFilterValue_valueChanged(int value) { ui->lblFilterValue->setText(QString("%1 %2").arg( value).arg(QString(tr("of")))); p->filter->setMaxUsage(ui->sliFilterValue->value()); } void DjFilterWidget::on_txtPath_textChanged(QString ) { if ( timer->isActive() ) timer->stop(); timer->start(); } void DjFilterWidget::on_cmbGenres_editTextChanged(QString ) { if ( timer->isActive() ) timer->stop(); timer->start(); } void DjFilterWidget::on_cmbArtists_editTextChanged(QString ) { if ( timer->isActive() ) timer->stop(); timer->start(); } void DjFilterWidget::on_pushActivate_clicked() { p->filter->setActive(true); } void DjFilterWidget::onFilterStatusChanged(bool b) { if (b) ui->ledActive->on(); else { ui->ledActive->off(); ui->stackDisplay->setSelected(-1); } } void DjFilterWidget::onFilterCountChanged() { ui->lblCount->setText( QString("%1").arg( p->filter->count())); } void DjFilterWidget::onFilterMaxUsageChanged() { ui->lblFilterValue->setText(QString("%1 %2").arg( p->filter->maxUsage()).arg(tr("of"))); ui->sliFilterValue->setValue(p->filter->maxUsage()); ui->stackDisplay->setCount(p->filter->maxUsage()); } void DjFilterWidget::onFilterUsageChanged() { ui->stackDisplay->setCount( p->filter->maxUsage()); ui->stackDisplay->setSelected(p->filter->usage()); } void DjFilterWidget::on_lbl1_linkActivated(const QString &link) { QFileDialog dialog(this); dialog.setFileMode(QFileDialog::DirectoryOnly); if (dialog.exec()) ui->txtPath->setText(dialog.selectedFiles().first()); } // esc key for exit close void DjFilterWidget::keyPressEvent(QKeyEvent *e) { if( e->key() == Qt::Key_Escape ) slideCloseWidget(false); else QWidget::keyPressEvent( e ); } void DjFilterWidget::on_pushClose_clicked() { slideCloseWidget( (ui->widgetClose->minimumWidth()<50) ); } void DjFilterWidget::slideCloseWidget(bool open) { p->targetWidth = (open) ? 70 : 0; p->timerSlide->start(); } void DjFilterWidget::timerSlide_timeOut() { int mWidth = ui->widgetClose->minimumWidth(); if ( p->targetWidth > mWidth ){ ui->widgetClose->setMinimumWidth(mWidth+5); ui->widgetClose->setMaximumWidth(mWidth+5); } else if ( p->targetWidth < mWidth ){ ui->widgetClose->setMinimumWidth(mWidth-5); ui->widgetClose->setMaximumWidth(mWidth-5); } else{ p->timerSlide->stop(); } } knowthelist-2.3.0/src/djsettings.cpp0000664000175000017500000000247012423536022016544 0ustar mariomario/* Copyright (C) 2014 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #include "djsettings.h" #include "ui_djsettings.h" DjSettings::DjSettings(QWidget *parent) : QWidget(parent), ui(new Ui::DjSettings) { ui->setupUi(this); } DjSettings::~DjSettings() { delete ui; } void DjSettings::setID(int value) { ui->label->setText(QString::number(value)); } void DjSettings::setFilterCount(int value) { ui->spinBox->setValue(value); } void DjSettings::setName(QString value) { ui->lineEdit->setText(value); } int DjSettings::filterCount() { return ui->spinBox->value(); } QString DjSettings::name() { return ui->lineEdit->text(); } knowthelist-2.3.0/src/playlist.cpp0000775000175000017500000007770012423536022016242 0ustar mariomario/* Copyright (C) 2005-2014 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #include "playlist.h" #include "playlistitem.h" #include #include #include #include #include #include #include #include #include #include #include #include Playlist::Playlist(QWidget* parent) : QTreeWidget( parent ) , m_marker( 0 ) , m_CurrentTrackColor(QColor( 255,100,100 )) , m_NextTrackColor(QColor( 200,200,255 )) , m_PlaylistMode( Playlist::Playlist_Single ) , nextPlaylistItem (0) , previousPlaylistItem(0) , currentPlaylistItem(0) , newPlaylistItem(0) , m_alternateMax(0) , showDropHighlighter(false) , autoClearOn(false) , m_isPlaying(false) , m_isInternDrop(false) , m_dragLocked(false) , isChangeSignalEnabled(true) { setSortingEnabled( false ); setAcceptDrops( true ); setDragEnabled( true ); setAllColumnsShowFocus( false ); setDropIndicatorShown(true); setAcceptDrops(true); setDragEnabled(true); setSelectionBehavior(QAbstractItemView::SelectRows); setSelectionMode(QAbstractItemView::ExtendedSelection); setDragDropMode(QAbstractItemView::InternalMove); setAttribute(Qt::WA_MacShowFocusRect, false); setUniformRowHeights(true); QStringList headers; headers << tr("Url")<setResizeMode(QHeaderView::Interactive); header()->hideSection(PlaylistItem::Column_Url); // prevent click event if doubleclicked ignoreNextRelease = false; timer = new QTimer(this); connect(timer, SIGNAL(timeout()), this, SLOT(emitClicked())); timerDragLock = new QTimer(this); timerDragLock->setInterval(300); connect(timerDragLock, SIGNAL(timeout()), this, SLOT(timeoutDragLock())); connect( this, SIGNAL(itemClicked(QTreeWidgetItem*,int)) , this, SLOT(slotItemClicked(QTreeWidgetItem*,int))); connect( this, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)) , this, SLOT(slotItemDoubleClicked(QTreeWidgetItem*,int))); connect( this, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(slotItemChanged(QTreeWidgetItem*,QTreeWidgetItem*))); } Playlist::~Playlist() { // save width and sort settings QSettings settings; settings.setValue("playlist_"+objectName(), header()->saveState()); } /** Add a song to the playlist */ void Playlist::addTrack( QUrl file, PlaylistItem* after ) { Track *track = new Track(file); addTrack(track, after); } void Playlist::addTrack( Track* track, PlaylistItem* after ) { if (!track || !track->isValid()) return; //qDebug() << Q_FUNC_INFO <<":"< tracks ) { clear(); appendTracks( tracks); } void Playlist::appendTracks( const QList tracks ) { // a week attempt to speed up the setItemWidget time issue setUpdatesEnabled(false); bool doSort = isSortingEnabled(); setSortingEnabled(false); hide(); appendTracks( tracks,(PlaylistItem*)lastChild()); setSortingEnabled(doSort); setUpdatesEnabled(true); show(); } void Playlist::appendTracks( QList tracks, PlaylistItem* after ) { foreach ( Track* track, tracks) { addTrack(new Track(*track),after); after = this->newTrack(); } checkCurrentItem(); } void Playlist::setPlaylistMode(Mode newMode) { m_PlaylistMode = newMode; double percent = this->size().width()/100.0; switch ( m_PlaylistMode ) { case Playlist::Tracklist: header()->hideSection( PlaylistItem::Column_No ); header()->showSection( PlaylistItem::Column_Played ); header()->showSection( PlaylistItem::Column_Year ); header()->showSection( PlaylistItem::Column_Genre ); header()->showSection( PlaylistItem::Column_Tracknumber ); header()->showSection( PlaylistItem::Column_Album ); header()->showSection( PlaylistItem::Column_Rate ); header()->resizeSection(PlaylistItem::Column_Artist,22*percent); header()->resizeSection(PlaylistItem::Column_Title,22*percent); header()->resizeSection(PlaylistItem::Column_Album,20*percent); header()->resizeSection(PlaylistItem::Column_Length,7*percent); header()->resizeSection(PlaylistItem::Column_Genre,10*percent); header()->resizeSection(PlaylistItem::Column_Year,8*percent); header()->resizeSection(PlaylistItem::Column_Tracknumber,5*percent); header()->resizeSection(PlaylistItem::Column_Played,5*percent); header()->resizeSection(PlaylistItem::Column_Rate,75); setSortingEnabled(true); sortByColumn(PlaylistItem::Column_Played,Qt::DescendingOrder); m_CurrentTrackColor = Qt::white; m_NextTrackColor = Qt::white; break; default : header()->showSection( PlaylistItem::Column_No ); header()->hideSection( PlaylistItem::Column_Played ); header()->hideSection( PlaylistItem::Column_Year ); header()->hideSection( PlaylistItem::Column_Genre ); header()->hideSection( PlaylistItem::Column_Tracknumber ); header()->hideSection( PlaylistItem::Column_Album ); header()->hideSection( PlaylistItem::Column_Rate ); header()->resizeSection(PlaylistItem::Column_No,6*percent); header()->resizeSection(PlaylistItem::Column_Artist,40*percent); header()->resizeSection(PlaylistItem::Column_Title,40*percent); header()->resizeSection(PlaylistItem::Column_Length,10*percent); header()->resizeSection(PlaylistItem::Column_Rate,0); setSortingEnabled(false); m_CurrentTrackColor = QColor( 255,100,100 ); m_NextTrackColor = QColor( 200,200,255 ); } QSettings settings; if ( settings.contains("playlist_"+objectName()) ) header()->restoreState( settings.value("playlist_"+objectName()).toByteArray()); handleChanges(); } void Playlist::checkCurrentItem() { if ( autoClearOn && newPlaylistItem == firstChild() ) setCurrentPlaylistItem(newPlaylistItem); if ( !currentPlaylistItem ) setCurrentPlaylistItem(firstChild()); handleChanges(); } /** handle changes after remove or adding tracks to play list */ void Playlist::handleChanges() { if ( m_PlaylistMode==Playlist::Tracklist) return; if ( itemBelow(currentPlaylistItem) ) { nextPlaylistItem = (PlaylistItem*)itemBelow(currentPlaylistItem); } else { nextPlaylistItem = NULL; } updatePlaylistItems(); Q_EMIT countChanged(countTrack()); Q_EMIT countChanged(allTracks()); fillNoColumn(); isChangeSignalEnabled = true; } void Playlist::setCurrentPlaylistItem( PlaylistItem* item ) { currentPlaylistItem = item; if ( autoClearOn ){ // Only for the mode, where current item is always on top of the list if ( currentPlaylistItem != firstChild() ){ // Move nextPlaylistItem at first row QTreeWidgetItem* child = takeTopLevelItem(indexOfTopLevelItem(item)); this->insertTopLevelItem(0,child); currentPlaylistItem=(PlaylistItem*)child; } } if (currentPlaylistItem) Q_EMIT currentTrackChanged(currentPlaylistItem->track()); else Q_EMIT currentTrackChanged(NULL); } void Playlist::setNextPlaylistItem( PlaylistItem* item ) { if ( autoClearOn ){ // Move nextPlaylistItem to second row // Only for the mode, where current item is always on top of the list QTreeWidgetItem* child = takeTopLevelItem(indexOfTopLevelItem(item)); this->insertTopLevelItem(1,child); handleChanges(); } } void Playlist::updatePlaylistItems() { // Set all items to normal for( PlaylistItem *item = firstChild(); item; item = item->nextSibling() ) { if (item) { item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsDragEnabled|Qt::ItemIsEnabled); item->setForeColor( Qt::white ); } } if (currentPlaylistItem) { if (m_isPlaying) currentPlaylistItem->setFlags(Qt::ItemIsEnabled); else currentPlaylistItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsDragEnabled|Qt::ItemIsEnabled); if (!m_isCurrentList) currentPlaylistItem->setForeColor( m_CurrentTrackColor.darker(130)); else currentPlaylistItem->setForeColor( m_CurrentTrackColor); } if (nextPlaylistItem) { nextPlaylistItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsDragEnabled|Qt::ItemIsEnabled); if (!m_isCurrentList) nextPlaylistItem->setForeColor( m_NextTrackColor.darker(130)); else nextPlaylistItem->setForeColor( m_NextTrackColor); } } QList Playlist::allTracks() { QList trackList; for(int i=0;itopLevelItemCount();i++){ if ( PlaylistItem *item = dynamic_cast(this->topLevelItem(i))){ if ( item->track()->isValid() ) trackList.append(item->track()); } } return trackList; } void Playlist::removePlaylistItem( PlaylistItem *item ) { if ( item ) { qDebug() << Q_FUNC_INFO << ":"<track()->url(); //unset if not available any more if ( item == currentPlaylistItem ) setCurrentPlaylistItem(0); if ( item == nextPlaylistItem ) setNextPlaylistItem(0); newPlaylistItem=0; takeTopLevelItem(indexOfTopLevelItem(item)); delete item; } } void Playlist::skipForward() { qDebug() << Q_FUNC_INFO <<":"<= 0x050000 QString pathName = QStandardPaths::standardLocations(QStandardPaths::DataLocation).at(0); #else QString pathName = QDesktopServices::storageLocation(QDesktopServices::DataLocation); #endif QDir path(pathName); if (!path.exists()) path.mkpath(pathName); return path.absolutePath() + "/" + this->objectName()+".xspf"; } // Export content as a xspf playlist void Playlist::saveXML( const QString &path ) const { qDebug() << Q_FUNC_INFO << "BEGIN " ; QFile file( path ); if( !file.open(QFile::WriteOnly) ) return; QDomDocument newdoc; QDomElement playlistElem = newdoc.createElement( "playlist" ); playlistElem.setAttribute( "version", "1" ); playlistElem.setAttribute( "xmlns", "http://xspf.org/ns/0/" ); newdoc.appendChild( playlistElem ); QDomElement elem = newdoc.createElement( "creator" ); QDomText t = newdoc.createTextNode( "Knowthelist" ); elem.appendChild( t ); playlistElem.appendChild( elem ); QDomElement listElem = newdoc.createElement( "trackList" ); for( PlaylistItem *item = firstChild(); item; item = item->nextSibling() ) { if (item) { QDomElement trackElem = newdoc.createElement("track"); QDomElement extElem = newdoc.createElement( "extension" ); // i.setAttribute("url", item->track()->url().toLocalFile()); if ( currentPlaylistItem ) if ( item == currentPlaylistItem ) extElem.setAttribute("current", "1"); if ( item == nextTrack() ) extElem.setAttribute("next", "1"); if ( item->track()->flags().testFlag(Track::isAutoDjSelection )) extElem.setAttribute("isAutoDjSelection", "1"); QStringList tag = item->track()->tagList(); for( int x = 0; x < tag.count(); ++x ) { if (x==4 ||x==5) { extElem.setAttribute( Track::tagNameList.at(x), tag.at(x) ); } else { QDomElement elem = newdoc.createElement( Track::tagNameList.at(x) ); QDomText t = newdoc.createTextNode( tag.at(x) ); elem.appendChild( t ); trackElem.appendChild( elem ); } } trackElem.appendChild( extElem ); listElem.appendChild( trackElem ); } } playlistElem.appendChild( listElem ); QTextStream stream( &file ); stream.setCodec( "UTF-8" ); stream << "\n"; stream << newdoc.toString(); file.close(); qDebug() << Q_FUNC_INFO<< "END " ; } void Playlist::loadXML( const QString &path ) { QFile file( path ); if( file.open( QFile::ReadOnly ) ) { QTextStream stream( &file ); stream.setCodec( QTextCodec::codecForName("utf8") ); QDomDocument d; if( !d.setContent(stream.readAll()) ) { qDebug() << "Could not load XML\n"; return; } QDomNode n = d.namedItem( "playlist" ).namedItem( "trackList" ).firstChild(); const QString TRACK( "track" ); //so we don't construct the QStrings all the time const QString URL( "url" ); const QString CURRENT( "current" ); const QString NEXT( "next" ); while( !n.isNull() ) { if( n.nodeName() == TRACK ) { const QDomElement e = n.toElement(); if( e.isNull() ) { qDebug() << "Element '" << n.nodeName() << "' is null, skipping."; continue; } //qDebug() << "Add from xml url='" << e.attribute( URL ); Track *track = new Track(); track->setUrl( QUrl::fromLocalFile(e.namedItem("location").firstChild().nodeValue())); track->setArtist( e.namedItem("creator").firstChild().nodeValue()); track->setTitle( e.namedItem("title").firstChild().nodeValue()); track->setAlbum( e.namedItem("album").firstChild().nodeValue()); track->setGenre( e.namedItem("extension").toElement().attribute( "genre" )); track->setYear( e.namedItem("extension").toElement().attribute( "year" )); track->setLength( e.namedItem("duration").firstChild().nodeValue()); track->setCounter("0"); if ( e.namedItem("extension").toElement().attribute( "isAutoDjSelection" ) =="1" ) track->setFlags( track->flags() | Track::isAutoDjSelection ); appendSong(track); if ( e.namedItem("extension").toElement().attribute( CURRENT ) == "1" ) this->setCurrentPlaylistItem( newPlaylistItem ); if ( e.namedItem("extension").toElement().attribute( NEXT ) == "1" ) this->setNextPlaylistItem( newPlaylistItem ); } n = n.nextSibling(); } } file.close(); qDebug() << "End " << Q_FUNC_INFO; } void Playlist::removeSelectedItems() { if ( m_PlaylistMode==Playlist::Tracklist) return; QListIterator it(selectedItems()); while (it.hasNext()){ PlaylistItem *item = dynamic_cast(it.next()); if ( item != currentPlaylistItem || (!m_isPlaying) ) removePlaylistItem( item ); } checkCurrentItem(); } void Playlist::fillNoColumn() { int no = 0; int i = 0; for (int ii = 0; ii < this->topLevelItemCount(); ii++) { QTreeWidgetItem *item = this->topLevelItem ( ii ); //if this item number is less then then alternateMax increment 2 (alternate) else 1 //alternateMax is equal to the count of then other player+1 i++; //qDebug() << this->name() << ": markNextTrack(): " << markNextTrack(); if ( m_PlaylistMode != Playlist::Playlist_Multi ) no = i; else if ( i > m_alternateMax) no = i + m_alternateMax; else { if ( m_isCurrentList ) no = i * 2 - 1; else no = i * 2; } //qDebug() << this->name() << ": m_alternateMax: " << m_alternateMax << " i: " << i << " no: " << no; item->setText(PlaylistItem::Column_No,QString::number(no)); } } void Playlist::onRatingChanged(float rate) { if(RatingWidget* rateWidget = dynamic_cast(QObject::sender())){ QModelIndex modidx = indexAt( QPoint(0,rateWidget->pos().y()) ); (PlaylistItem*)this->itemFromIndex(modidx); if(PlaylistItem* item = (PlaylistItem*)this->itemFromIndex(modidx)){ Track* track = item->track(); if (track){ track->setRate(rate * 10); qDebug() << Q_FUNC_INFO<track()->url(); emit trackPropertyChanged(track); } } } } void Playlist::slotItemChanged( QTreeWidgetItem * current, QTreeWidgetItem * previous ) { Q_UNUSED(previous); if ((selectedItems().count()>1) || (selectedItems().count()==0)) return; PlaylistItem* item = static_cast(current); if (item && isChangeSignalEnabled ) emit trackSelected(item->track()); } void Playlist::slotItemDoubleClicked( QTreeWidgetItem *sender, int column ) { Q_UNUSED(column); PlaylistItem* item = static_cast(sender); if (item) emit trackDoubleClicked( item->track() ); } void Playlist::slotItemClicked(QTreeWidgetItem *after,int col) { isChangeSignalEnabled = true; PlaylistItem* item = static_cast(after); if (item) emit trackSelected( item->track() ); } // avoid multiple drops on quick drags void Playlist::timeoutDragLock() { m_dragLocked=false; timerDragLock->stop(); } // prevent click event if doubleclicked void Playlist::emitClicked() { emit itemClicked( currentItem(), currentColumn() ); timer->stop(); } void Playlist::mouseReleaseEvent(QMouseEvent *event) { if (!ignoreNextRelease) { timer->start(QApplication::doubleClickInterval()); blockSignals(true); QTreeWidget::mouseReleaseEvent(event); blockSignals(false); } ignoreNextRelease = false; } void Playlist::mouseDoubleClickEvent(QMouseEvent *event) { ignoreNextRelease = true; timer->stop(); QTreeWidget::mouseDoubleClickEvent(event); } void Playlist::mousePressEvent( QMouseEvent *e ) { if (e->button() == Qt::LeftButton){ startPos = e->pos(); } QTreeWidget::mousePressEvent(e); if (e->button() == Qt::RightButton) showContextMenu( dynamic_cast(currentItem()), currentColumn() ); } void Playlist::mouseMoveEvent(QMouseEvent *event) { if(event->buttons() & Qt::LeftButton) { int distance = (event->pos() - startPos).manhattanLength(); if(distance >= QApplication::startDragDistance() && !m_dragLocked) { performDrag(); } } } void Playlist::performDrag() { m_dragLocked=true; QByteArray itemData; QDataStream dataStream(&itemData, QIODevice::WriteOnly); QVector tags; QPixmap cover; int i=0; //iterate selected items QListIterator it(selectedItems()); while (it.hasNext()){ PlaylistItem *item = dynamic_cast(it.next()); if ( (item != currentPlaylistItem || (!m_isPlaying)) && item->track()->isValid() ) { qDebug() << Q_FUNC_INFO <<": send Data:"<track()->url(); QStringList tag = item->track()->tagList(); tags << tag; if (i==0){ cover=QPixmap::fromImage( item->track()->coverImage()); emit trackSelected(item->track()); } i++; } } dataStream << tags; QMimeData *mimeData = new QMimeData; mimeData->setData("text/playlistitem", itemData); QDrag *drag = new QDrag(this); drag->setMimeData(mimeData); if (!cover.isNull()) drag->setPixmap(cover.scaled(50,50)); timerDragLock->start(); if (drag->exec(Qt::CopyAction | Qt::MoveAction, Qt::CopyAction) == Qt::MoveAction){ if ( m_PlaylistMode != Playlist::Tracklist ) { //ToDo: before remove, give over current or next Track to newTrack, if within the same playlist isChangeSignalEnabled = false; removeSelectedItems(); } } } void Playlist::dragEnterEvent(QDragEnterEvent *event) { if (m_PlaylistMode == Playlist::Tracklist){ event->ignore(); return; } if (event->mimeData()->hasFormat("text/uri-list") || event->mimeData()->hasFormat("text/playlistitem")) { event->acceptProposedAction(); } } void Playlist::dropEvent(QDropEvent *event) { m_isInternDrop = false; if (event->mimeData()->hasUrls()) { QList urlList = event->mimeData()->urls(); // returns list of QUrls event->accept(); appendList(urlList,m_marker); } else if (event->mimeData()->hasFormat("text/playlistitem")) { //decode playlistitem QByteArray itemData = event->mimeData()->data("text/playlistitem"); QDataStream stream(&itemData, QIODevice::ReadOnly); QVector tags; stream >> tags; //add Tracks to this playlist foreach ( QStringList tag, tags) { qDebug() << Q_FUNC_INFO <<": is playlistitem; tags:"<newTrack(); } checkCurrentItem(); event->setDropAction(Qt::MoveAction); event->accept(); if (event->source()->objectName()==this->objectName()) m_isInternDrop=true; } else event->ignore(); showDropHighlighter=false; viewport()->repaint(); } void Playlist::dragMoveEvent (QDragMoveEvent *event) { dropSite = event->answerRect(); showDropHighlighter=true; viewport()->repaint(); } void Playlist::dragLeaveEvent (QDragLeaveEvent *event) { Q_UNUSED(event); showDropHighlighter=false; viewport()->repaint(); } void Playlist::paintEvent ( QPaintEvent* event ) { QTreeView::paintEvent (event); if (showDropHighlighter) { QPainter painter ( viewport() ); int x, y, w, h; dropSite.getRect ( &x, &y, &w, &h ); QPoint point(x,y); QModelIndex modidx = indexAt( point ); int addHeight=0; //if is playing mark as next only if (isPlaying() && modidx.row()==0){ modidx = model()->index(1,1); } //Draw drop line after last item if (!modidx.isValid()) { modidx = model()->index(model()->rowCount()-1,1,modidx); addHeight=1; } //bookmark item in case of a drop m_marker = (PlaylistItem*)this->itemFromIndex(modidx); if (addHeight==0) { if (itemAbove(m_marker)) { //one item above m_marker = (PlaylistItem*)itemAbove(m_marker); } else { //add new item at first row m_marker = 0; } } // qDebug() << Q_FUNC_INFO <<": modidx:"<accept(); } void Playlist::keyPressEvent ( QKeyEvent* e ) { qDebug() << Q_FUNC_INFO << " " << e->key() << "del="<(currentItem()); if( (e->key() == Qt::Key_Delete) || (e->key() == 0x1000003) ) //also for Mac { this->removeSelectedItems(); } else if( e->key() == Qt::Key_L){ setCurrentPlaylistItem( item ); handleChanges(); } else if( e->key() == Qt::Key_N){ setNextPlaylistItem( item ); } else if( e->key() == Qt::Key_1) Q_EMIT wantLoad( item->track(),"Left" ); else if( e->key() == Qt::Key_2) Q_EMIT wantLoad( item->track(),"Right" ); else if( e->key() == Qt::Key_P) Q_EMIT trackDoubleClicked( item->track() ); else if( e->key() == Qt::CTRL + Qt::Key_S) Q_EMIT wantSearch(QString::null); else QTreeWidget::keyPressEvent( e ); } // needed for showContextMenu actions void Playlist::dummySlot(){} void Playlist::showContextMenu( PlaylistItem *item, int col ) { enum Id { LOAD, LOAD_NEXT, VIEW, EDIT, REMOVE, LISTEN, FILTER, LOAD1, LOAD2 }; if( item == NULL ) return; const bool isCurrentPlaylistItem = (item == currentPlaylistItem); QMenu popup( this ); popup.setTitle( item->track()->prettyTitle( 50 ) ); if (m_PlaylistMode == Playlist::Tracklist ) { popup.addAction( style()->standardPixmap(QStyle::SP_MediaPlay), tr( "Add to PlayList&1" ), this, SLOT(dummySlot()), Qt::Key_1 );//, LOAD1 popup.addAction( style()->standardPixmap(QStyle::SP_MediaPlay), tr( "Add to PlayList&2" ), this, SLOT(dummySlot()), Qt::Key_2 );//, LOAD2 } if (!m_isPlaying && !isCurrentPlaylistItem && m_PlaylistMode != Playlist::Tracklist ) popup.addAction( style()->standardPixmap(QStyle::SP_MediaPlay), tr( "&Load" ), this, SLOT(dummySlot()), Qt::Key_L ); if (!isCurrentPlaylistItem && m_PlaylistMode != Playlist::Tracklist ) popup.addAction( style()->standardPixmap(QStyle::SP_ArrowRight), tr( "Load as &Next" ), this, SLOT(dummySlot()), Qt::Key_N ); popup.addSeparator(); popup.addAction( style()->standardPixmap(QStyle::SP_DriveCDIcon), tr( "&Prelisten Track" ), this, SLOT(dummySlot()), Qt::Key_P ); popup.addSeparator(); popup.addAction( style()->standardPixmap(QStyle::SP_ArrowRight), tr( "&Search for: '%1'" ).arg( item->text(col) ), this, SLOT(dummySlot()),Qt::Key_S ); popup.addSeparator(); if (!isCurrentPlaylistItem && m_PlaylistMode != Playlist::Tracklist ) popup.addAction(style()->standardPixmap(QStyle::SP_TrashIcon), tr( "&Remove Selected" ), this, SLOT( removeSelectedItems() ), Qt::Key_Delete ); popup.addSeparator(); popup.addAction( style()->standardPixmap(QStyle::SP_DirOpenIcon), tr( "&Open File Location" ), this, SLOT(dummySlot()),Qt::Key_O ); popup.addAction( style()->standardPixmap(QStyle::SP_MessageBoxInformation), tr( "&View Tag Information" ), this, SLOT(dummySlot()),Qt::Key_V ); QAction *a = popup.exec( QCursor::pos()); if (!a) return; QKeySequence shortcut = a->shortcut(); if( shortcut == QKeySequence(Qt::Key_L) ){ setCurrentPlaylistItem( item ); handleChanges(); } else if( shortcut == QKeySequence(Qt::Key_N) ){ setNextPlaylistItem( item ); } else if( shortcut == QKeySequence(Qt::Key_1) ){ Q_EMIT wantLoad(item->track(),"Left" ); } else if( shortcut == QKeySequence(Qt::Key_2) ){ Q_EMIT wantLoad(item->track(),"Right" ); } else if( shortcut == QKeySequence(Qt::Key_P) ){ Q_EMIT itemDoubleClicked(item,col); } else if( shortcut == QKeySequence(Qt::Key_S) ){ Q_EMIT wantSearch( item->text(col) ); } else if( shortcut == QKeySequence(Qt::Key_V) ){ showTrackInfo( item->track() ); } else if( shortcut == QKeySequence(Qt::Key_O) ){ if ( item->track()) QDesktopServices::openUrl( QUrl(QString("file://%1").arg(item->track()->dirPath()))); } else if( shortcut == QKeySequence(Qt::Key_Delete) ){ item=0; } } void Playlist::showTrackInfo( Track* mb ) { const QString body = "%1%2"; QString str = " width=\"100%\" border=\"1\">"; str += body.arg( tr( "Title" ), mb->title() ); str += body.arg( tr( "Artist" ), mb->artist() ); str += body.arg( tr( "Album" ), mb->album() ); str += body.arg( tr( "Genre" ), mb->genre() ); str += body.arg( tr( "Year" ), mb->year() ); str += body.arg( tr( "Location" ), mb->url().toString() ); str += "
"; QMessageBox::information( 0, tr( "Meta Information" ),str ); } knowthelist-2.3.0/src/djsession.cpp0000775000175000017500000003104612423536022016373 0ustar mariomario/* Copyright (C) 2005-2014 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #include "djsession.h" #include "track.h" #include "dj.h" #if QT_VERSION >= 0x050000 #include #else #include #endif #include struct DjSessionPrivate { QMutex mutex1; Dj* currentDj; int minCount; CollectionDB* database; QList playList1_Tracks; QList playList2_Tracks; QPair playList1_Info; QPair playList2_Info; QStringList seenUrls; bool isEnabledAutoDJCount; }; DjSession::DjSession() :p(new DjSessionPrivate) { p->database = new CollectionDB(); p->minCount=10; p->currentDj=0; p->isEnabledAutoDJCount=false; } DjSession::~DjSession() { delete p; } void DjSession::setCurrentDj(Dj* dj) { // retire current Auto-DJ if (p->currentDj) disconnect(p->currentDj,SIGNAL(filterChanged(Filter*)), this,SLOT(on_dj_filterChanged(Filter*))); // hire new DJ p->currentDj = dj; connect(p->currentDj,SIGNAL(filterChanged(Filter*)), this,SLOT(on_dj_filterChanged(Filter*))); } Dj* DjSession::currentDj() { return p->currentDj; } void DjSession::searchTracks() { // init qrand QTime time = QTime::currentTime(); qsrand((uint)time.msec()); // how many tracks are needed p->mutex1.lock(); int diffCount1= p->minCount - p->playList1_Tracks.count(); int diffCount2= p->minCount - p->playList2_Tracks.count(); int needed = (diffCount1 > 0) ? diffCount1 : 0; needed = (diffCount2 > 0) ? needed + diffCount2 : needed; qDebug() << Q_FUNC_INFO << " need "< tracks1; QList tracks2; for (int i=0; i 0){ tracks1.append( getRandomTrack() ); diffCount1--; } else tracks2.append( getRandomTrack() ); } else{ if ( diffCount2 > 0){ tracks2.append( getRandomTrack() ); diffCount2--; } else tracks1.append( getRandomTrack() ); } } // new tracks available, trigger fill up of playlists qDebug() << Q_FUNC_INFO << " provide "< 0 ) emit foundTracks_Playlist1(tracks1); if ( tracks2.count() > 0 ) emit foundTracks_Playlist2(tracks2); p->mutex1.unlock(); } /*ToDo: - Genre: Combobox with distinct all genres */ Track* DjSession::getRandomTrack() { Track* track=0; int i=0; Filter* f = p->currentDj->requestFilter(); int maxCount=0; do { track = new Track( p->database->getRandomEntry(f->path(),f->genre(),f->artist()) ); if (maxCount==0) maxCount=p->database->lastMaxCount(); i++; } while ((track->prettyLength()=="?" || track->containIn( p->playList1_Tracks ) || track->containIn( p->playList2_Tracks ) || p->seenUrls.contains(track->url().toString()) ) && i=maxCount*3) qDebug() << Q_FUNC_INFO << " no new track found."; else qDebug() << Q_FUNC_INFO <setCount(maxCount); f->setLength(p->database->lastLengthSum()); p->seenUrls.append(track->url().toString()); p->seenUrls.removeDuplicates(); track->setFlags(track->flags()|Track::isAutoDjSelection); return track; } void DjSession::updatePlaylists() { QFuture future = QtConcurrent::run( this, &DjSession::searchTracks); } void DjSession::forceTracks(QList tracks) { int count1 = p->playList1_Tracks.count(); int count2 = p->playList2_Tracks.count(); qDebug() << Q_FUNC_INFO < tracks1; QList tracks2; for (int i=0; iflags().testFlag(Track::isOnFirstPlayer) ){ tracks1.append( tracks.at(i) ); count1++; } else if ( tracks.at(i)->flags().testFlag(Track::isOnSecondPlayer) ){ tracks2.append( tracks.at(i) ); count2++; } else if ( count1 < count2 ){ tracks1.append( tracks.at(i) ); count1++; } else{ tracks2.append( tracks.at(i) ); count2++; } } // new tracks available, trigger fill up of playlists qDebug() << Q_FUNC_INFO << " provide "< 0 ) emit foundTracks_Playlist1(tracks1); if ( tracks2.count() > 0 ) emit foundTracks_Playlist2(tracks2); } void DjSession::playDefaultList() { qDebug() << Q_FUNC_INFO ; QList selectedTags; //Retrieve songs from database selectedTags = p->database->selectPlaylistTracks("defaultKnowthelist"); QList tracks; tracks.clear(); qDebug() << Q_FUNC_INFO << "Song count: " << selectedTags.count(); //add tags to this track list foreach ( QStringList tag, selectedTags) { tracks.append( new Track(tag)); } forceTracks(tracks); } void DjSession::on_dj_filterChanged(Filter* f) { //qDebug() << Q_FUNC_INFO ; int cnt = p->database->getCount(f->path(),f->genre(),f->artist()); f->setLength(p->database->lastLengthSum()); f->setCount(cnt); summariseCount(); } void DjSession::onResetStats() { p->database->resetSongCounter(); } void DjSession::onTrackFinished(Track *track) { if (track && (p->isEnabledAutoDJCount || !track->flags().testFlag(Track::isAutoDjSelection))){ p->database->incSongCounter(track->url().toLocalFile()); } } void DjSession::onTrackPropertyChanged(Track* track) { if ( track ){ p->database->setSongRate( track->url().toLocalFile(), track->rate() ); } } void DjSession::onTracksChanged_Playlist1(QList tracks) { p->playList1_Info.second=0; p->playList1_Tracks = tracks; foreach (Track* track, p->playList1_Tracks){ Track::Options flags = track->flags(); flags|=Track::isOnFirstPlayer; flags&= ~Track::isOnSecondPlayer; track->setFlags( flags ); p->playList1_Info.second+=track->length(); } p->playList1_Info.first=p->playList1_Tracks.count(); Q_EMIT changed_Playlist1(p->playList1_Info); } void DjSession::onTracksChanged_Playlist2(QList tracks) { p->playList2_Info.second=0; p->playList2_Tracks = tracks; foreach (Track* track, p->playList2_Tracks){ Track::Options flags = track->flags(); flags&= ~Track::isOnFirstPlayer; flags|= Track::isOnSecondPlayer; track->setFlags( flags ); p->playList2_Info.second+=track->length(); } p->playList2_Info.first=p->playList2_Tracks.count(); Q_EMIT changed_Playlist2(p->playList2_Info); } void DjSession::storePlaylists( const QString &name, bool replace ) { qDebug() << Q_FUNC_INFO << " Start"; QList listToStore; listToStore.append( p->playList1_Tracks ); listToStore.append( p->playList2_Tracks ); if (replace) p->database->executeSql( QString("DELETE FROM playlists WHERE name ='%1';") .arg(p->database->escapeString( name ))); int n=0; QList::Iterator i = listToStore.begin(); while (i != listToStore.end()) { QString command = QString("INSERT OR REPLACE INTO playlists " "( url, name, length, flags, norder, changedate ) " "VALUES('%1','%2', %3, %4, %5, strftime('%s', 'now'));") .arg(p->database->escapeString( (*i)->url().toLocalFile() )) .arg(p->database->escapeString( name )) .arg( (*i)->length() ) .arg( (*i)->flags() ) .arg( n ); p->database->executeSql( command ); i++; n++; } Q_EMIT savedPlaylists(); qDebug() << Q_FUNC_INFO << " Insert finish"; } void DjSession::summariseCount() { QString res; QStringList genres; QStringList paths; QStringList artists; int filterCount = p->currentDj->filters().count(); for (int i=0;icurrentDj->filters().at(i); qDebug() << Q_FUNC_INFO << " countOfFilter= "<count(); res+=f->description(); genres.append(f->genre()); paths.append(f->path()); artists.append(f->artist()); } QPair counts = p->database->getCount(paths,genres,artists); p->currentDj->setLengthTracks( counts.second ); p->currentDj->setDescription(res); p->currentDj->setCountTracks( counts.first ); } bool DjSession::isEnabledAutoDJCount() { return p->isEnabledAutoDJCount; } void DjSession::setIsEnabledAutoDJCount(bool value) { p->isEnabledAutoDJCount=value; } int DjSession::minCount() { return p->minCount; } void DjSession::setMinCount(int value) { p->minCount=value; } // obsolate: keep this just in case we need an export function later void DjSession::savePlaylists( const QString &filename ) { qDebug() << Q_FUNC_INFO << "BEGIN " ; QFile file( filename ); if( !file.open(QFile::WriteOnly) ) return; QList listToSave; listToSave.append( p->playList1_Tracks ); listToSave.append( p->playList2_Tracks ); QDomDocument newdoc; QDomElement playlistElem = newdoc.createElement( "playlist" ); playlistElem.setAttribute( "version", "1" ); playlistElem.setAttribute( "xmlns", "http://xspf.org/ns/0/" ); newdoc.appendChild( playlistElem ); QDomElement elem = newdoc.createElement( "creator" ); QDomText t = newdoc.createTextNode( "Knowthelist" ); elem.appendChild( t ); playlistElem.appendChild( elem ); QDomElement listElem = newdoc.createElement( "trackList" ); QList::Iterator i = listToSave.begin(); while (i != listToSave.end()) { QDomElement trackElem = newdoc.createElement("track"); QDomElement extElem = newdoc.createElement( "extension" ); if ( (*i)->flags().testFlag(Track::isAutoDjSelection )) extElem.setAttribute("isAutoDjSelection", "1"); if ( (*i)->flags().testFlag(Track::isOnFirstPlayer )) extElem.setAttribute("isOnFirstPlayer", "1"); if ( (*i)->flags().testFlag(Track::isOnSecondPlayer )) extElem.setAttribute("isOnSecondPlayer", "1"); extElem.setAttribute("Rating", (*i)->rate()); QStringList tag = (*i)->tagList(); for( int x = 0; x < tag.count(); ++x ) { if (x==4 ||x==5) { extElem.setAttribute( Track::tagNameList.at(x), tag.at(x) ); } else { QDomElement elem = newdoc.createElement( Track::tagNameList.at(x) ); QDomText t = newdoc.createTextNode( tag.at(x) ); elem.appendChild( t ); trackElem.appendChild( elem ); } } trackElem.appendChild( extElem ); listElem.appendChild( trackElem ); i++; } playlistElem.appendChild( listElem ); QTextStream stream( &file ); stream.setCodec( "UTF-8" ); stream << "\n"; stream << newdoc.toString(); file.close(); Q_EMIT savedPlaylists(); qDebug() << Q_FUNC_INFO<< "END " ; } knowthelist-2.3.0/src/ratingwidget.h0000664000175000017500000000340512423536022016522 0ustar mariomario/* Copyright 2010, David Sansome Copyright (C) 2005-2014 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #ifndef RATINGWIDGET_H #define RATINGWIDGET_H #include #include class RatingPainter { public: RatingPainter(); static const int kStarCount = 5; static const int kStarSize = 15; static QRect Contents(const QRect& rect); static double RatingForPos(const QPoint& pos, const QRect& rect); void Paint(QPainter* painter, const QRect& rect, float rating) const; private: QPixmap stars_[kStarCount*2+1]; }; class RatingWidget : public QWidget { Q_OBJECT Q_PROPERTY(float rating READ rating WRITE setRating); public: RatingWidget(QWidget* parent = 0); QSize sizeHint() const; float rating() const { return rating_; } void setRating(float rating); signals: void RatingChanged(float rating); protected: void paintEvent(QPaintEvent*); void mousePressEvent(QMouseEvent* e); void mouseMoveEvent(QMouseEvent* e); void leaveEvent(QEvent*); private: RatingPainter painter_; float rating_; float hover_rating_; }; #endif // RATINGWIDGET_H knowthelist-2.3.0/src/filebrowser.h0000775000175000017500000000211312423536022016353 0ustar mariomario/* Copyright (C) 2005-2014 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #ifndef FILEBROWSER_H #define FILEBROWSER_H #include class FileBrowser : public QWidget { Q_OBJECT public: explicit FileBrowser(QWidget *parent = 0); void setRootPath(QString); signals: public slots: protected: private: struct FileBrowserPrivate* p; }; #endif // FILEBROWSER_H knowthelist-2.3.0/src/track.cpp0000775000175000017500000002713412423536022015501 0ustar mariomario/* Copyright (C) 2004 Max Howell Copyright (C) 2005-2014 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #include "track.h" #include "playlistitem.h" #include #include #include #include #include #include #include #include #include #include #include #include #include QStringList Track::tagNameList = QStringList() << "location" << "creator" << "title" << "album" << "year" << "genre" << "trackNum" << "duration" << "counter" << "rate"; struct TrackPrivate { QUrl url; QString title; QString artist; QString album; QString year; QString comment; QString genre; QString tracknumber; int counter; int length; int rate; Track::Options flags; }; Track::Track() :p(new TrackPrivate) { p->counter=-1; p->rate=0; } Track::~Track() { delete p; } Track::Track( const QUrl &u ) :p(new TrackPrivate) { p->url=u; readTags(); } Track::Track( const QStringList& list ) :p(new TrackPrivate) { if (list.count()>9){ p->url = QUrl::fromLocalFile( list.at(0)); p->artist = list.at(1); p->title = list.at(2); p->album = list.at(3); p->year = list.at(4); p->genre = list.at(5); p->tracknumber = list.at(6); p->length= QString(list.at(7)).toInt(); p->counter = QString(list.at(8)).toInt(); p->rate = QString(list.at(9)).toInt(); } if (list.count()>10) p->flags = QFlag(list.at(10).toInt()); } Track::Track( const PlaylistItem *item ) :p(new TrackPrivate) { p->url = QUrl::fromLocalFile(item->urlString()) ; p->title = item->title(); p->artist = item->exactText( 2 ); p->album = item->exactText( 4 ); p->year = item->exactText( 5 ); p->comment= item->exactText( 6 ); p->genre = item->exactText( 7 ); p->tracknumber = item->exactText( 8 ); p->counter = item->exactText( 9 ).toInt(); // p->rate = item->rate(); } void Track::readTags() { QString fileName = p->url.toLocalFile(); #ifdef Q_OS_WIN32 TagLib::FileRef fileref = TagLib::FileRef( fileName.toStdWString().c_str(), true, TagLib::AudioProperties::Fast); #else TagLib::FileRef fileref = TagLib::FileRef( QFile::encodeName(fileName).constData(), true, TagLib::AudioProperties::Fast); #endif if ( !fileref.isNull() ) { if( fileref.tag() ) { TagLib::Tag *tag = fileref.tag(); p->title = !tag->title().isNull() ? TStringToQString( tag->title() ).trimmed() : QObject::tr("Unknown"); p->artist = !tag->artist().isNull() ? TStringToQString( tag->artist() ).trimmed() : QObject::tr("Unknown"); p->album = !tag->album().isNull() ? TStringToQString( tag->album() ).trimmed() : QObject::tr("Unknown"); p->comment = TStringToQString( tag->comment() ).trimmed(); p->genre = !tag->genre().isNull() ? TStringToQString( tag->genre() ).trimmed() : QObject::tr("Unknown"); p->year = tag->year() ? QString::number( tag->year() ) : QString::null; p->tracknumber = tag->track() ? QString::number( tag->track() ) : QString::null; p->length = fileref.audioProperties()->length(); p->counter = 0; p->rate = 0; //polish up empty tags if( p->title == QObject::tr("Unknown") ) { QFileInfo fileInfo(p->url.toLocalFile()); p->title = fileInfo.fileName().replace( '_', ' ' ).replace('.' + fileInfo.suffix(),"") ; } } } } bool Track::operator==(Track *track) { if (!isValid()) return false; return p->artist == track->artist() && p->title == track->title(); } bool Track::containIn( QList list ) { foreach( Track* i, list ) { if( *i == this ){ return true; } } return false; } QImage Track::coverImage() { if (!p->url.isValid()) return QImage(); qDebug()<<"image url:"<url; if (p->url.path()=="") return QImage(); QByteArray fileName = QFile::encodeName( p->url.toLocalFile() ); const char * encodedName = fileName.constData(); TagLib::MPEG::File fileref( encodedName); if (!fileref.isOpen()) return QImage(); TagLib::ID3v2::Tag *tag = fileref.ID3v2Tag(); if ( tag ) { TagLib::ID3v2::FrameList l = fileref.ID3v2Tag()->frameListMap()[ "APIC" ]; if ( !l.isEmpty() ) { //qDebug() << "Found APIC frame(s)" << endl; TagLib::ID3v2::Frame *f = l.front(); TagLib::ID3v2::AttachedPictureFrame *ap = (TagLib::ID3v2::AttachedPictureFrame*)f; const TagLib::ByteVector bytes = ap->picture(); QImage image = QImage::fromData(reinterpret_cast(bytes.data()), bytes.size()); if (! image.isNull() ) { return image; } } } return defaultImage(); } /* * Create a default cover image: a gray record with diagonal record name as text */ QImage Track::defaultImage() { QImage img(120, 120, QImage::Format_RGB888); img.fill(QColor(Qt::white)); QPainter painter(&img); painter.setPen(QPen(Qt::lightGray)); painter.setBrush(Qt::lightGray); painter.setRenderHint(QPainter::Antialiasing, true); painter.drawEllipse(QPoint(60,60),45,45); painter.setBrush(Qt::white); painter.drawEllipse(QPoint(60,60),15,15); painter.setPen(QPen(QColor(60,60,60))); painter.setFont(QFont("Monospace")); painter.translate(QPoint(-26,62)); painter.rotate(-45); painter.drawText( img.rect(), Qt::AlignCenter , p->artist + '\n' + p->title); return img; } QString Track::prettyTitle() const { QString s = QString::null; if( p->artist != QObject::tr("Unknown") ) s += p->artist + " - "; s += p->title; return s; } QString Track::prettyTitle( QString filename ) //static { QString &s = filename; s = s.left( s.indexOf( '.' ) ); return s; } QString Track::prettyArtist( int maxlen ) const { return this->rsqueeze(p->artist,maxlen); } QString Track::prettyTitle( int maxlen ) const { return this->rsqueeze(p->title,maxlen); } QString Track::rsqueeze( const QString & str, int maxlen ) const { if (str.length() > maxlen) { int part = maxlen-3; return QString(str.left(part) + "..."); } else return str; } void Track::setLengthFromPretty(QString s) { int i=-1; if ( s.contains(':') ){ QStringList list=s.split(':'); i=list.at(0).toInt()*60; i+=list.at(1).toInt(); } p->length = i; } QString Track::prettyLength( int seconds ) { QString s; if( seconds > 0 ) s = prettyTime( seconds, false ); else if( seconds == -1 ) s = '?'; return s; } QString Track::prettyTime( int seconds, bool showHours ) { QString s = QChar( ':' ); s.append( zeroPad( seconds % 60 ) ); seconds /= 60; if( showHours ) { s.clear(); s.prepend( zeroPad( seconds % 60 ) ); s.prepend( ':' ); seconds /= 60; } s.prepend( QString::number( seconds ) ); return s; } bool Track::isValid() { if ( p->url.isEmpty() || !p->url.isValid() ) return false; if (p->url.toString().contains(".mp3",Qt::CaseInsensitive) || p->url.toString().contains(".ogg",Qt::CaseInsensitive) || p->url.toString().contains(".wav",Qt::CaseInsensitive) || p->url.toString().contains(".m4a",Qt::CaseInsensitive) || p->url.toString().contains(".m4p",Qt::CaseInsensitive) || p->url.toString().contains(".flac",Qt::CaseInsensitive) || p->url.toString().contains(".aiff",Qt::CaseInsensitive) || p->url.toString().contains(".oga",Qt::CaseInsensitive) || p->url.toString().contains(".wma",Qt::CaseInsensitive) || p->url.toString().contains(".au",Qt::CaseInsensitive) || p->url.toString().contains(".tta",Qt::CaseInsensitive) || p->url.toString().contains(".raw",Qt::CaseInsensitive) ) return true; else return false; } QString Track::dirPath() { QString localPath = p->url.toLocalFile(); QFileInfo fileInfo(localPath); return fileInfo.absolutePath(); } QStringList Track::tagList(){ return (QStringList() << p->url.toLocalFile() << p->artist << p->title << p->album << p->year << p->genre << p->tracknumber << QString().setNum(p->length) << QString().setNum(p->counter) << QString().setNum(p->rate)); } int Track::length() { return p->length > 0 ? p->length : 0; } QUrl Track::url() { return p->url; } QString Track::title() { return p->title; } QString Track::artist() { return p->artist; } QString Track::album() { return p->album; } int Track::rate() { return p->rate; } QString Track::year() { return p->year; } QString Track::comment() { return p->comment; } QString Track::genre() { return p->genre; } QString Track::tracknumber() { return p->tracknumber > 0 ? p->tracknumber : "0"; } int Track::counter() { return p->counter; } QString Track::prettyLength() { return prettyLength( p->length ); } Track::Options Track::flags() { return p->flags; } void Track::setUrl(QUrl url) { p->url = url; } void Track::setTitle(QString s) { p->title = s; } void Track::setArtist(QString s) { p->artist = s; } void Track::setAlbum(QString s) { p->album = s; } void Track::setRate(int s) { p->rate = s; } void Track::setYear(QString s) { p->year = s; } void Track::setComment(QString s) { p->comment = s; } void Track::setGenre(QString s) { p->genre = s; } void Track::setTracknumber(QString s) { p->tracknumber = s; } void Track::setLength(QString s) { p->length = s.toInt();} void Track::setCounter(QString s) { p->counter = s.toInt();} void Track::setFlags(Track::Options flags) { p->flags = flags;} knowthelist-2.3.0/src/stylehelper.h0000775000175000017500000000625412423536022016402 0ustar mariomario/************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** Commercial Usage ** ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at http://qt.nokia.com/contact. ** **************************************************************************/ #ifndef STYLEHELPER_H #define STYLEHELPER_H #include #include QT_BEGIN_NAMESPACE class QPalette; class QPainter; class QRect; // Note, this is exported but in a private header as qtopengl depends on it. // We should consider adding this as a public helper function. void qt_blurImage(QPainter *p, QImage &blurImage, qreal radius, bool quality, bool alphaOnly, int transposed = 0); QT_END_NAMESPACE // Helper class holding all custom color values namespace Utils { class StyleHelper { public: static const unsigned int DEFAULT_BASE_COLOR = 0x666666; // Height of the project explorer navigation bar static qreal sidebarFontSize(); // This is our color table, all colors derive from baseColor static QColor requestedBaseColor() { return m_requestedBaseColor; } static QColor baseColor(bool lightColored = false); static QColor panelTextColor(bool lightColored = false); static QColor highlightColor(bool lightColored = false); static QColor shadowColor(bool lightColored = false); static QColor borderColor(bool lightColored = false); static QColor sidebarHighlight() { return QColor(255, 255, 255, 40); } static QColor sidebarShadow() { return QColor(0, 0, 0, 40); } // Sets the base color and makes sure all top level widgets are updated static void setBaseColor(const QColor &color); // Gradients used for panels static void verticalGradient(QPainter *painter, const QRect &spanRect, const QRect &clipRect, bool lightColored = false); static bool usePixmapCache() { return true; } static void drawIconWithShadow(const QIcon &icon, const QRect &rect, QPainter *p, QIcon::Mode iconMode, int radius = 3, const QColor &color = QColor(0, 0, 0, 130), const QPoint &offset = QPoint(1, -2)); private: static QColor m_baseColor; static QColor m_requestedBaseColor; }; } // namespace Utils using Utils::StyleHelper; #endif // STYLEHELPER_H knowthelist-2.3.0/src/collectionupdater.cpp0000775000175000017500000002070512423536022020112 0ustar mariomario/* Copyright (C) 2004 Max Howell Copyright (C) 2005-2014 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #include "collectionupdater.h" #include "collectiondb.h" #if QT_VERSION >= 0x050000 #include #else #include #endif class CollectionUpdaterPrivate { public: bool doMonitor; QStringList dirs; bool isStoped; QPoint startPos; bool openContext; bool dragLocked; QTimer *timer; bool incremental; CollectionDB *collectionDB; QMutex mutex; }; CollectionUpdater::CollectionUpdater() { p = new CollectionUpdaterPrivate; QSettings settings; p->doMonitor = settings.value("Monitor").toBool(); p->dirs=settings.value("Dirs").toStringList(); p->collectionDB = new CollectionDB(); if ( !p->collectionDB ) qWarning() << Q_FUNC_INFO << "Could not open SQLite database\n"; //optimization for speeding up SQLite p->collectionDB->executeSql( "PRAGMA synchronous = OFF;" ); if ( !p->collectionDB->isDbValid() ) { qDebug() << "Rebuilding database!" << endl; p->collectionDB->dropTables(); p->collectionDB->createTables(); p->collectionDB->dropStatsTable(); p->collectionDB->createStatsTable(); scan(); } p->timer = new QTimer( this ); p->timer->setInterval(600000); //1000 * 60 * 10 = 10min connect(p->timer,SIGNAL(timeout()),this,SLOT(monitor())); if ( p->doMonitor){ monitor(); p->timer->start(); } } CollectionUpdater::~CollectionUpdater() { delete p; } void CollectionUpdater::setDoMonitor(bool value) { p->doMonitor = value; if ( p->doMonitor) p->timer->start(); else p->timer->stop(); } void CollectionUpdater::stop() { p->isStoped = true; } void CollectionUpdater::setDirectoryList(QStringList dirs, bool force) { if ( p->dirs != dirs || force ){ p->dirs = dirs; scan(); } } void CollectionUpdater::monitor() { qDebug() << Q_FUNC_INFO; p->incremental = true; p->isStoped = false; QStringList folders; QList entries = p->collectionDB->selectSql( "SELECT dir, changedate FROM directories;" ); foreach ( QStringList entry, entries) { QString dir(entry[0]); QString changedate(entry[1]); QFileInfo fi(dir); if ( fi.exists() ) { if ( QString::number(fi.lastModified().toTime_t()) != changedate ) { folders << dir; qDebug() << "Collection dir changed: " << dir; } } else { // this folder has been removed folders << dir; qDebug() << "Collection dir removed: " << dir; } } if ( !folders.isEmpty() ) QFuture future = QtConcurrent::run( this, &CollectionUpdater::asynchronScan, folders); } void CollectionUpdater::scan() { p->incremental = false; p->isStoped = false; QFuture future = QtConcurrent::run( this, &CollectionUpdater::asynchronScan, p->dirs); } void CollectionUpdater::asynchronScan(QStringList dirs) { qDebug() << Q_FUNC_INFO << dirs.count() << "dirs" << endl; // avoid multiple runs QMutexLocker locker(&p->mutex); Q_EMIT progressChanged(1); if ( !p->incremental ) p->collectionDB->purgeDirCache(); QStringList entries; int dirCount = dirs.count(); //iterate over all folders for ( int i = 0; i < dirCount; i++ ) { Q_EMIT progressChanged(((i+1)*10)/dirCount); readDir( dirs[ i ], entries ); } if ( !entries.empty() ) { Q_EMIT progressChanged(10); readTags( entries ); } Q_EMIT progressChanged(100); if (!entries.empty()) Q_EMIT changesDone(); } void CollectionUpdater::readDir( const QString& dir, QStringList& entries ) { //update dir statistics for rescanning purposes QFileInfo fi( dir ); if ( fi.exists() ) p->collectionDB->updateDirStats( dir, ( long ) fi.lastModified().toTime_t() ); else { if ( p->incremental ) { p->collectionDB->removeSongsInDir( dir ); p->collectionDB->removeDirFromCollection( dir ); } return; } QDir rDir( dir ); rDir.setFilter(QDir::Dirs | QDir::Files | QDir::NoDotDot | QDir::NoDot | QDir::NoSymLinks | QDir::Readable); QFileInfoList list = rDir.entryInfoList(); Q_FOREACH (const QFileInfo fi, list) { if ( fi.isDir() ) { if ( !p->incremental || !p->collectionDB->isDirInCollection( fi.absoluteFilePath() ) ) readDir( fi.absoluteFilePath(), entries ); } else if ( fi.isFile() ) entries << fi.absoluteFilePath(); } } void CollectionUpdater::readTags( const QStringList& entries ) { qDebug() << Q_FUNC_INFO << " Start"; QUrl url; p->collectionDB->createTables( true ); int entriesCount = entries.count(); for ( int i = 0; i < entriesCount; i++ ) { if ( !( i % 20 ) ) Q_EMIT progressChanged(((i*90)/entriesCount)+10); url = QUrl::fromLocalFile( entries[ i ] ); Track track( url ); if ( track.isValid() ) { QString command = QString("INSERT INTO tags_temp " "( url, dir, artist, title, album, genre, year, length, track ) " "VALUES('%1','%2',%3,'%4',%5,%6,%7,%8,%9);") .arg(p->collectionDB->escapeString( track.url().toLocalFile() )) .arg(p->collectionDB->escapeString( track.dirPath() )) .arg(p->collectionDB->escapeString( QString::number( p->collectionDB->getValueID( "artist", track.artist(), true, !p->incremental ) ) )) .arg(p->collectionDB->escapeString( track.title() )) .arg(p->collectionDB->escapeString( QString::number( p->collectionDB->getValueID( "album", track.album(), true, !p->incremental ) )) ) .arg(p->collectionDB->escapeString( QString::number( p->collectionDB->getValueID( "genre", track.genre(), true, !p->incremental ) ) )) .arg(p->collectionDB->escapeString( QString::number( p->collectionDB->getValueID( "year", track.year(), true, !p->incremental ) ) )) .arg(p->collectionDB->escapeString( QString::number( track.length() ))) .arg(p->collectionDB->escapeString( track.tracknumber() )); p->collectionDB->executeSql( command ); //stop the process? if ( p->isStoped ) i = entries.count(); } } qDebug() << Q_FUNC_INFO << " Insert finish"; //update database only if not stoped if ( !p->isStoped ) { // let's lock the database (will block other threads) p->collectionDB->executeSql( "BEGIN TRANSACTION;" ); // remove tables and recreate them (quicker than DELETE FROM) if ( !p->incremental ) { p->collectionDB->dropTables(); p->collectionDB->createTables(); } else { // remove old entries from database, only for ( int i = 0; i < p->dirs.count(); i++ ) p->collectionDB->removeSongsInDir( p->dirs[ i ] ); } // rename tables p->collectionDB->moveTempTables(); // remove temp tables and unlock database p->collectionDB->dropTables( true ); p->collectionDB->executeSql( "END TRANSACTION;" ); } else { qDebug() << Q_FUNC_INFO << " Stop"; } qDebug() << Q_FUNC_INFO << " End"; } knowthelist-2.3.0/src/src.pro0000775000175000017500000001235212423536022015176 0ustar mariomario# # Knowthelist # Copyright (C) 2011-2014 Mario Stephan # License: LGPL-3.0+ # DEFINES += APP_VERSION="\\\"2.3.0\\\"" QT += core \ gui \ xml \ sql greaterThan(QT_MAJOR_VERSION, 4){ #use qt5 and gstreamer 1.x QT += widgets DEFINES += GST_API_VERSION_1 } #else use qt4 and gstreamer 0.10 TARGET = knowthelist TEMPLATE = app SOURCES += main.cpp \ knowthelist.cpp \ player.cpp \ vumeter.cpp \ qvumeter.cpp \ playerwidget.cpp \ qled.cpp \ playlistitem.cpp \ playlist.cpp \ progressbar.cpp \ collectiondb.cpp \ settingsdialog.cpp \ track.cpp \ trackanalyser.cpp \ djsession.cpp \ dj.cpp \ filter.cpp \ djwidget.cpp \ djfilterwidget.cpp \ fancytabwidget.cpp \ stylehelper.cpp \ filebrowser.cpp \ collectionwidget.cpp \ collectiontree.cpp \ collectionupdater.cpp \ collectiontreeitem.cpp \ monitorplayer.cpp \ collectionsetupmodel.cpp \ stackdisplay.cpp \ djsettings.cpp \ modeselector.cpp \ playlistbrowser.cpp \ playlistwidget.cpp \ djbrowser.cpp \ ratingwidget.cpp HEADERS += knowthelist.h \ vumeter.h \ qvumeter.h \ playerwidget.h \ qled.h \ playlistitem.h \ playlist.h \ player.h \ progressbar.h \ collectiondb.h \ settingsdialog.h \ track.h \ trackanalyser.h \ djsession.h \ dj.h \ filter.h \ djwidget.h \ djfilterwidget.h \ fancytabwidget.h \ stylehelper.h \ filebrowser.h \ collectionwidget.h \ collectiontree.h \ collectionupdater.h \ collectiontreeitem.h \ monitorplayer.h \ collectionsetupmodel.h \ stackdisplay.h \ djsettings.h \ modeselector.h \ playlistbrowser.h \ playlistwidget.h \ djbrowser.h \ ratingwidget.h FORMS += \ settingsdialog.ui \ djwidget.ui \ djfilterwidget.ui \ playerwidget.ui \ knowthelist.ui \ djsettings.ui \ modeselector.ui \ playlistwidget.ui TRANSLATIONS += \ ../locale/knowthelist_cs.ts \ ../locale/knowthelist_de.ts \ ../locale/knowthelist_hu.ts \ ../locale/knowthelist_fr.ts \ ../locale/knowthelist_nl.ts \ ../locale/knowthelist_ru.ts \ ../locale/knowthelist_es.ts \ ../locale/knowthelist_tr.ts \ ../locale/knowthelist_it.ts OTHER_FILES += \ knowthelist.rc DESTDIR = ../ win32 { GST_HOME = $$quote($$(GSTREAMER_1_0_ROOT_X86)) isEmpty(GST_HOME) { message(\"GSTREAMER_1_0_ROOT_X86\" not detected ...) } else { message(\"GSTREAMER_1_0_ROOT_X86\" detected in \"$${GST_HOME}\") } #TAGLIB_HOME = $$quote(C:\Program Files (x86)\taglib-1.9.1) INCLUDEPATH += $${GST_HOME}\include\gstreamer-1.0 \ $${GST_HOME}\include\glib-2.0 \ $${GST_HOME}\lib\glib-2.0\include \ $${GST_HOME}\include \ LIBS += $${GST_HOME}\lib\gstreamer-1.0.lib \ $${GST_HOME}\lib\gobject-2.0.lib \ $${GST_HOME}\lib\glib-2.0.lib \ $${GST_HOME}\lib\libtag.dll.a \ -ldsound \ -lwinmm RC_FILE = knowthelist.rc #DEPLOY_COMMAND = $$[QT_INSTALL_BINS]\windeployqt.exe #DEPLOY_TARGET = $$DESTDIR$${TARGET}$${TARGET_EXT}.exe #QMAKE_POST_LINK = $$DEPLOY_COMMAND $$DEPLOY_TARGET $$escape_expand(\\n\\t) #EXTRA_BINFILES += \ #$${GST_HOME}bin\*.dll \ #$${GST_HOME}\bin\*.dll #for(FILE,EXTRA_BINFILES){ # message($$QMAKE_COPY \"$$FILE\" \"$${DESTDIR}\" $$escape_expand(\\n\\t)) # QMAKE_POST_LINK += $$QMAKE_COPY \"$$FILE\" \"$${DESTDIR}\" $$escape_expand(\\n\\t) #} # copy patched version of directsoundsink.dll direct to GStreamer plugin path QMAKE_POST_LINK = $$QMAKE_COPY \"$${DESTDIR}\libgstdirectsoundsink.dll\" \"$${GST_HOME}lib\gstreamer-1.0\" $$escape_expand(\\n\\t) } macx { DEFINES += GST_API_VERSION_1 INCLUDEPATH += /usr/local/include/gstreamer-1.0 \ /usr/local/include/glib-2.0 \ /usr/local/lib/glib-2.0/include \ /usr/local/include LIBS += -L/usr/local/lib \ -lgstreamer-1.0 \ -lglib-2.0 \ -lgobject-2.0 \ -ltag \ -framework CoreAudio \ -framework CoreFoundation } unix:!macx { isEmpty(PREFIX):PREFIX = /usr BINDIR = $$PREFIX/bin DATADIR = $$PREFIX/share target.path = $$BINDIR icon.path = $$DATADIR/pixmaps icon.files += ../dist/knowthelist.png desktop.path = $$DATADIR/applications desktop.files += ../dist/Knowthelist.desktop INSTALLS += target icon desktop contains(DEFINES, GST_API_VERSION_1) { CONFIG += link_pkgconfig \ gstreamer-1.0 PKGCONFIG += gstreamer-1.0 \ taglib alsa } else { CONFIG += link_pkgconfig \ gstreamer PKGCONFIG += gstreamer-0.10 \ taglib alsa } } RESOURCES += ../images/icons.qrc \ ../locale/locale.qrc ICON = ../dist/headset.icns isEmpty(QMAKE_LRELEASE) { win32:QMAKE_LRELEASE = $$[QT_INSTALL_BINS]\lrelease.exe else:QMAKE_LRELEASE = $$[QT_INSTALL_BINS]/lrelease } lrelease.commands = $$QMAKE_LRELEASE ${QMAKE_FILE_IN} lrelease.input = TRANSLATIONS lrelease.output = ../locale/${QMAKE_FILE_BASE}.qm lrelease.CONFIG = no_link target_predeps QMAKE_EXTRA_COMPILERS += lrelease knowthelist-2.3.0/src/playlistbrowser.h0000664000175000017500000000170212423536022017275 0ustar mariomario#ifndef PLAYLISTBROWSER_H #define PLAYLISTBROWSER_H #include "playlistwidget.h" #include #include class QPushButton; class Track; class PlaylistBrowser : public QWidget { Q_OBJECT public: explicit PlaylistBrowser(QWidget *parent = 0); ~PlaylistBrowser(); QList readFileList(QString filename); QPair readFileValues(QString filename); QList selectedTracks(); signals: void selectionStarted(QList); void selectionChanged(QList); void savePlaylists(QString); void storePlaylists(QString); public slots: void loadDatabaseList(); void loadFileList(); void playDatabaseList(); void playFileList(); void removeFileList(); void removeDatabaseList(); void onSelectionChanged(PlaylistWidget* item); void onPushSave(); void updateLists(); private: class PlaylistBrowsertPrivate *p; }; #endif // PLAYLISTBROWSER_H knowthelist-2.3.0/src/filter.cpp0000775000175000017500000000554612423536022015665 0ustar mariomario/* Copyright (C) 2005-2014 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #include "filter.h" #include struct Filter::Private { int maxUsage; int usage; bool isActive; QString path; QString genre; QString artist; int count; long length; }; /* * *ToDo: - replace path with a string from Tag (if we have a good tagger tool inside) **/ Filter::Filter() :p(new Private) { p->usage = 0; p->maxUsage = 0; p->count = 0; p->length = 0; p->path = "", p->genre = ""; p->artist = ""; p->isActive = false; } Filter::Filter(QString genre, int maxUsage) :p(new Private) { p->maxUsage = maxUsage; p->genre = genre; } Filter::~Filter() { delete p; } int Filter::maxUsage() { return p->maxUsage; } void Filter::setMaxUsage(int value) { p->maxUsage = value; emit maxUsageChanged(); } bool Filter::active() { return p->isActive; } void Filter::setActive(bool b) { p->isActive = b; Q_EMIT statusChanged(b); if ( b == true ) { setUsage(0); Q_EMIT activated(); } } void Filter::update() { //qDebug() << Q_FUNC_INFO ; Q_EMIT filterChanged(); } QString Filter::path() { return p->path; } void Filter::setPath(QString path) { p->path = path; } QString Filter::genre() { return p->genre; } void Filter::setGenre(QString genre) { p->genre = genre; } QString Filter::artist() { return p->artist; } void Filter::setArtist(QString artist) { p->artist = artist; } int Filter::usage() { return p->usage; } void Filter::setUsage(int value) { p->usage = value; emit usageChanged(); } int Filter::count() { return p->count; } void Filter::setCount(int value) { p->count = value; emit countChanged(); } long Filter::length() { return p->length; } void Filter::setLength(long value) { p->length = value; } QString Filter::description() { QString ret; if ( !p->artist.isEmpty()) ret+=p->artist +" "; if ( !p->genre.isEmpty()) ret+=p->genre +" "; if ( !p->path.isEmpty()) { QStringList token = p->path.split("/"); ret+=token.last() +" "; } return ret; } knowthelist-2.3.0/src/djwidget.cpp0000775000175000017500000001323612423536022016174 0ustar mariomario/* Copyright (C) 2005-2014 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #include "djwidget.h" #include "ui_djwidget.h" #include #include #include #include struct DjWidgetPrivate { Dj* dj; bool isActive; QTimer* timerSlide; int targetWidth; }; DjWidget::DjWidget(QWidget *parent) : QWidget(parent), ui(new Ui::DjWidget) ,p(new DjWidgetPrivate) { setFocusPolicy(Qt::ClickFocus); ui->setupUi(this); ui->lblDesciption->setText( QString::null ); ui->widgetClose->setMinimumWidth(0); ui->widgetClose->setMaximumWidth(0); QFont font = ui->lblDesciption->font(); #if defined(Q_OS_DARWIN) int newSize = font.pointSize()-4; #else int newSize = font.pointSize()-1; #endif font.setPointSize(newSize); ui->lblDesciption->setFont(font); p->timerSlide = new QTimer(this); p->timerSlide->setInterval(10); connect( p->timerSlide, SIGNAL(timeout()), SLOT(timerSlide_timeOut()) ); } DjWidget::~DjWidget() { delete ui; delete p; } void DjWidget::changeEvent(QEvent* event) { QWidget::changeEvent(event); switch (event->type()) { case QEvent::LanguageChange: ui->retranslateUi(this); break; default: break; } } void DjWidget::mousePressEvent(QMouseEvent *event) { if(ui->widgetClose->geometry().contains(event->pos())) { Q_EMIT deleted(); } else{ slideCloseWidget(false); Q_EMIT activated(); } } void DjWidget::setDj(Dj* dj) { qDebug() << Q_FUNC_INFO ; p->dj = dj; connect(p->dj,SIGNAL(countChanged()),this,SLOT(updateView())); deactivateDJ(); } Dj* DjWidget::dj() { return p->dj; } // auto connect slot void DjWidget::on_lblName_linkActivated(const QString &link) { Q_UNUSED(link); Q_EMIT activated(); } void DjWidget::clicked() { Q_EMIT activated(); } void DjWidget::activateDJ() { p->isActive = true; updateView(); } void DjWidget::deactivateDJ() { p->isActive = false; updateView(); } void DjWidget::updateView() { // Filter description and count update // update Labels setToolTip( tr("This Dj plays: ") + p->dj->description() ); QString strCase = (p->dj->filters().count() > 1) ? tr("cases") : tr("case"); ui->lblDesciption->setText( QString::number( p->dj->filters().count() ) + " " + strCase + " " + QString::number( p->dj->countTracks() ) + " " + tr("tracks") + " " + Track::prettyTime( p->dj->lengthTracks() ,true) + " " + tr("hours")); // active/passive look differentiation QString activeStyle; if (p->isActive){ activeStyle = "color:#ff6464;'>"; this->setStyleSheet("#frameDj{ background: qlineargradient(" "x1:0, y1:0, x2:0, y2:1," "stop: 0.01 #202020," "stop:0.11 #505050," "stop:1 #505050" ");}"); } else { activeStyle = "color:#eeeeee;'>"; this->setStyleSheet("#frameDj{ background: qlineargradient(" "x1:0, y1:0, x2:0, y2:1," "stop: 0.01 #202020," "stop:0.11 #404040," "stop:1 #404040" ");}"); } ui->lblName->setText("" "

" "tracks.clear(); qDebug() << Q_FUNC_INFO << "Song count: " << tags.count(); //add tags to this track list foreach ( QStringList tag, tags) { //qDebug() << Q_FUNC_INFO <<": is playlistitem; tags:"<tracks.append( new Track(tag)); } emit selectionChanged(p->tracks); //qDebug() << Q_FUNC_INFO << "[End]" << endl; } QString CollectionTree::filter() { //ToDo: do we need this private variable return p->filterString; } void CollectionTree::setFilter( QString filter ) { p->filterString = filter; p->database->setFilterString(filter); } void CollectionTree::mousePressEvent( QMouseEvent *e ) { if (e->button() == Qt::LeftButton) startPos = e->pos(); QTreeWidget::mousePressEvent(e); if (e->button() == Qt::RightButton) showContextMenu( currentItem(), currentColumn() ); } void CollectionTree::mouseMoveEvent(QMouseEvent *event) { if(event->buttons() & Qt::LeftButton) { int distance = (event->pos() - startPos).manhattanLength(); if(distance >= QApplication::startDragDistance()) { performDrag(); } } } void CollectionTree::performDrag() { QByteArray itemData; QDataStream dataStream(&itemData, QIODevice::WriteOnly); QVector tags; QPixmap cover; int i=0; //iterate selected items QListIterator it( p->tracks ); while (it.hasNext()){ Track *track = dynamic_cast(it.next()); if ( track->isValid() ) { qDebug() << Q_FUNC_INFO <<": send Data:"<url(); QStringList tag = track->tagList(); tags << tag; if (i==0) cover=QPixmap::fromImage( track->coverImage()); i++; } } dataStream << tags; QMimeData *mimeData = new QMimeData; mimeData->setData("text/playlistitem", itemData); QDrag *drag = new QDrag(this); drag->setMimeData(mimeData); if (!cover.isNull()) drag->setPixmap(cover.scaled(50,50)); if (drag->exec(Qt::CopyAction | Qt::MoveAction, Qt::CopyAction) == Qt::MoveAction){ } } void CollectionTree::showContextMenu(QTreeWidgetItem *item, int col ) { Q_UNUSED(col); //ToDo: create popup before first use enum Id { LOAD1, LOAD2 }; if( item == NULL ) return; QMenu popup( this ); popup.setTitle( item->text(0) ); popup.addAction( style()->standardPixmap(QStyle::SP_MediaPlay), tr( "Add to PlayList&1" ), this, SLOT(onLoad1Triggered()), Qt::Key_1 );//, LOAD1 popup.addAction( style()->standardPixmap(QStyle::SP_MediaPlay), tr( "Add to PlayList&2" ), this, SLOT(onLoad2Triggered()), Qt::Key_2 );//, LOAD2 popup.addSeparator(); popup.addAction( style()->standardPixmap(QStyle::SP_BrowserReload), tr( "Re-scan collection" ), this,SLOT(onRescanTriggered()),Qt::Key_R ); popup.exec( QCursor::pos()); } void CollectionTree::onLoad1Triggered() { Q_EMIT wantLoad(p->tracks,"Left" ); } void CollectionTree::onLoad2Triggered() { Q_EMIT wantLoad(p->tracks,"Right" ); } void CollectionTree::onRescanTriggered() { Q_EMIT rescan(); } void CollectionTree::showTrackInfo( Track* mb ) { const QString body = "%1%2"; QString str = " width=\"100%\" border=\"1\">"; str += body.arg( tr( "Title" ), mb->title() ); str += body.arg( tr( "Artist" ), mb->artist() ); str += body.arg( tr( "Album" ), mb->album() ); str += body.arg( tr( "Genre" ), mb->genre() ); str += body.arg( tr( "Year" ), mb->year() ); str += body.arg( tr( "Location" ), mb->url().toString() ); str += "
"; QMessageBox::information( 0, tr( "Meta Information" ),str ); } void CollectionTree::resizeEvent(QResizeEvent *) { //QRect rec = p->collectiontree->geometry(); header()->resizeSection(0,this->width()-100); } knowthelist-2.3.0/src/playlistwidget.cpp0000664000175000017500000001146612423536022017440 0ustar mariomario#include "playlistwidget.h" #include "ui_playlistwidget.h" #include #include #include class PlaylistWidgetPrivate { public: QString name; QString description; bool isActive; QTimer* timerSlide; int targetWidth; bool isRemovable; }; PlaylistWidget::PlaylistWidget(QWidget *parent) : QWidget(parent), ui(new Ui::PlaylistWidget) { ui->setupUi(this); ui->lblDesciption->setText( QString::null ); ui->widgetClose->setMinimumWidth(0); ui->widgetClose->setMaximumWidth(0); setFocusPolicy(Qt::ClickFocus); p = new PlaylistWidgetPrivate; p->isActive=false; p->isRemovable=true; QFont font = ui->lblDesciption->font(); #if defined(Q_OS_DARWIN) int newSize = font.pointSize()-4; #else int newSize = font.pointSize()-1; #endif font.setPointSize(newSize); ui->lblDesciption->setFont(font); p->timerSlide = new QTimer(this); p->timerSlide->setInterval(10); connect( p->timerSlide, SIGNAL(timeout()), SLOT(timerSlide_timeOut()) ); } PlaylistWidget::~PlaylistWidget() { delete ui; delete p; } // auto connect slot void PlaylistWidget::on_lblName_linkActivated(const QString &link) { Q_UNUSED(link); Q_EMIT activated(); } bool PlaylistWidget::isRemovable() { return p->isRemovable; } void PlaylistWidget::setRemovable(bool value) { p->isRemovable=value; ui->pushClose->setVisible(value); // if (!value) //r ui->horizontalSpacer->changeSize(42,0); } QString PlaylistWidget::name() { return p->name; } void PlaylistWidget::setName(QString value) { p->name=value; updateView(); } QString PlaylistWidget::description() { return p->description; } void PlaylistWidget::setDescription(QString value) { p->description=value; updateView(); } void PlaylistWidget::activate() { p->isActive = true; updateView(); } void PlaylistWidget::deactivate() { p->isActive = false; updateView(); } void PlaylistWidget::mousePressEvent(QMouseEvent* event) { if(ui->widgetClose->geometry().contains(event->pos())) { Q_EMIT deleted(); } else{ slideCloseWidget(false); Q_EMIT activated(); } } void PlaylistWidget::updateView() { // update Labels ui->lblDesciption->setText(p->description); // active/passive look differentiation QString activeStyle; if (p->isActive){ activeStyle = "color:#ff6464;'>"; ui->framePlaylistWidget->setStyleSheet("#framePlaylistWidget { background: qlineargradient(" "x1:0, y1:0, x2:0, y2:1," "stop: 0.01 #202020," "stop:0.11 #505050," "stop:1 #505050" ");}"); } else { activeStyle = "color:#eeeeee;'>"; ui->framePlaylistWidget->setStyleSheet("#framePlaylistWidget { background: qlineargradient(" "x1:0, y1:0, x2:0, y2:1," "stop: 0.01 #202020," "stop:0.11 #404040," "stop:1 #404040" ");}"); } ui->lblName->setText("" "

" "length() < otherLength; } } else { int value = text(sortCol).replace(QObject::tr("Unknown"),"0").toInt(&ok); int otherValue = otherText.toInt(&ok); if (ok) return value < otherValue; } return QTreeWidgetItem::operator <(other); } knowthelist-2.3.0/src/qvumeter.cpp0000775000175000017500000001464312423536022016246 0ustar mariomario/*************************************************************************** * Copyright (C) 2008 - Giuseppe Cigala * * g_cigala@virgilio.it * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "qvumeter.h" #include QVUMeter::QVUMeter(QWidget *parent) : QWidget(parent) { colBack = QColor(40, 40, 40); colValue = Qt::white; colHigh = Qt::red; colLow = Qt::green; dimVal = 9; min = 0; max = 100; leftVal = 0; rightVal = 0; } void QVUMeter::paintEvent(QPaintEvent *) { paintBorder(); paintBar(); paintValue(); } void QVUMeter::paintBorder() { QPainter painter(this); painter.setWindow(0, 0, 100, 540); painter.setRenderHint(QPainter::Antialiasing); QColor light = Qt::white; QColor dark = colBack.darker(140); painter.setPen(QPen(colBack, 3, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); QLinearGradient linGrad(5, 250, 10, 250); linGrad.setColorAt(0, light); linGrad.setColorAt(1, colBack); linGrad.setSpread(QGradient::PadSpread); painter.setBrush(linGrad); QRectF border(5, 5, 90, 530); painter.drawRoundRect(border, 30, 5); QLinearGradient linGrad1(85, 250, 95, 250); linGrad1.setColorAt(0, colBack); linGrad1.setColorAt(1, dark); linGrad1.setSpread(QGradient::PadSpread); painter.setBrush(linGrad1); QRectF border1(20, 5, 75, 530); painter.drawRoundRect(border1, 30, 5); // paint label painter.setPen(QPen(colValue, 2)); QRectF Left(20, 505, 25, 20); QRectF Right(55, 505, 25, 20); QFont valFont("Arial", 12, QFont::Bold); painter.setFont(valFont); painter.drawText(Left, Qt::AlignCenter, "L"); painter.drawText(Right, Qt::AlignCenter, "R"); } void QVUMeter::paintBar() { QPainter painter(this); painter.setWindow(0, 0, 100, 540); painter.setRenderHint(QPainter::Antialiasing); QLinearGradient linGrad(50, 0, 50, 500); linGrad.setColorAt(0, colHigh); linGrad.setColorAt(1, colLow); linGrad.setSpread(QGradient::PadSpread); painter.setBrush(linGrad); // draw color bar QRectF bar3(20, 50, 25, 450); painter.drawRect(bar3); QRectF bar4(55, 50, 25, 450); painter.drawRect(bar4); // draw background bar painter.setBrush(QColor(40, 40, 40)); double length = 450.0; double leftBar = abs(length * (min-leftVal)/(max-min)); double rightBar = abs(length * (min-rightVal)/(max-min)); QRectF bar1(20, 50, 25, 450-leftBar); painter.drawRect(bar1); QRectF bar2(55, 50, 25, 450-rightBar); painter.drawRect(bar2); painter.setPen(QPen(Qt::black, 2)); for (int i = 0; i <=60; i++) { painter.drawLine(21, 500-450*i/60, 44, 500-450*i/60); painter.drawLine(56, 500-450*i/60, 79, 500-450*i/60); } } void QVUMeter::paintValue() { QPainter painter(this); painter.setWindow(0, 0, 100, 540); painter.setRenderHint(QPainter::Antialiasing); painter.setBrush(Qt::black); painter.drawRect(20, 15, 25, 25); painter.drawRect(55, 15, 25, 25); painter.setPen(Qt::gray); painter.drawLine(20, 40, 45, 40); painter.drawLine(45, 15, 45, 40); painter.drawLine(55, 40, 80, 40); painter.drawLine(80, 15, 80, 40); painter.setPen(QPen(colValue, 1)); QFont valFont("Arial", dimVal, QFont::Bold); painter.setFont(valFont); QRectF leftR(20, 15, 25, 25); QString lVal = QString("%1").arg(leftVal, 0,'f', 0); painter.drawText(leftR, Qt::AlignCenter, lVal); QRectF rightR(55, 15, 25, 25); QString rVal = QString("%1").arg(rightVal, 0,'f', 0); painter.drawText(rightR, Qt::AlignCenter, rVal); Q_EMIT valueLChanged(leftVal); Q_EMIT valueRChanged(rightVal); } void QVUMeter::setValueDim(int dim) { dimVal = dim; update(); } void QVUMeter::setColorBg(QColor color) { colBack = color; update(); } void QVUMeter::setColorValue(QColor color) { colValue = color; update(); } void QVUMeter::setColorHigh(QColor color) { colHigh = color; update(); } void QVUMeter::setColorLow(QColor color) { colLow = color; update(); } void QVUMeter::setLeftValue(double leftValue) { if (leftValue > max) { leftVal = max; update(); } else if (leftValue < min) { leftVal = min; update(); } else if (leftVal != leftValue) { leftVal = leftValue; update(); } } void QVUMeter::setRightValue(double rightValue) { if (rightValue > max) { rightVal = max; update(); } else if (rightValue < min) { rightVal = min; update(); } else { rightVal = rightValue; update(); } } void QVUMeter::setMinValue(double minValue) { if (minValue > max) { min = max; max = minValue; update(); } else { min = minValue; update(); } } void QVUMeter::setMaxValue(double maxValue) { if (maxValue < min) { max = min; min = maxValue; update(); } else { max = maxValue; update(); } } QSize QVUMeter::minimumSizeHint() const { return QSize(10, 54); } QSize QVUMeter::sizeHint() const { return QSize(100, 540); } knowthelist-2.3.0/src/trackanalyser.cpp0000775000175000017500000002477512423536022017250 0ustar mariomario/* Copyright (C) 2011 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #include "trackanalyser.h" #include #if QT_VERSION >= 0x050000 #include #else #include #endif struct TrackAnalyser::Private { QFutureWatcher watcher; QMutex mutex; }; TrackAnalyser::TrackAnalyser(QWidget *parent) : QWidget(parent), pipeline(0), m_finished(false) , p( new Private ) { gst_init (0, 0); prepare(); connect(&p->watcher, SIGNAL(finished()), this, SLOT(loadThreadFinished())); } void TrackAnalyser::sync_set_state(GstElement* element, GstState state) { GstStateChangeReturn res; \ res = gst_element_set_state (GST_ELEMENT (element), state); \ if(res == GST_STATE_CHANGE_FAILURE) return; \ if(res == GST_STATE_CHANGE_ASYNC) { \ GstState state; \ res = gst_element_get_state(GST_ELEMENT (element), &state, NULL, 1000000000/*GST_CLOCK_TIME_NONE*/); \ if(res == GST_STATE_CHANGE_FAILURE || res == GST_STATE_CHANGE_ASYNC) return; \ } } TrackAnalyser::~TrackAnalyser() { delete p; p=0; cleanup(); } void cb_newpad_ta (GstElement *decodebin, GstPad *pad, gpointer data) { TrackAnalyser* instance = (TrackAnalyser*)data; instance->newpad(decodebin, pad, data); } void TrackAnalyser::newpad (GstElement *decodebin, GstPad *pad, gpointer data) { GstCaps *caps; GstStructure *str; GstPad *audiopad; /* only link once */ GstElement *audio = gst_bin_get_by_name(GST_BIN(pipeline), "audiobin"); audiopad = gst_element_get_static_pad (audio, "sink"); gst_object_unref(audio); if (GST_PAD_IS_LINKED (audiopad)) { g_object_unref (audiopad); return; } /* check media type */ #ifdef GST_API_VERSION_1 caps = gst_pad_query_caps (pad,NULL); #else caps = gst_pad_get_caps (pad); #endif str = gst_caps_get_structure (caps, 0); if (!g_strrstr (gst_structure_get_name (str), "audio")) { gst_caps_unref (caps); gst_object_unref (audiopad); return; } gst_caps_unref (caps); /* link'n'play */ gst_pad_link (pad, audiopad); } GstBusSyncReply TrackAnalyser::bus_cb (GstBus *bus, GstMessage *msg, gpointer data) { TrackAnalyser* instance = (TrackAnalyser*)data; instance->messageReceived(msg); return GST_BUS_PASS; } void TrackAnalyser::cleanup() { if(pipeline) sync_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL); if(bus) gst_object_unref (bus); if(pipeline) gst_object_unref(G_OBJECT(pipeline)); } bool TrackAnalyser::prepare() { GstElement *dec, *conv, *sink, *cutter, *audio, *analysis; GstPad *audiopad; GstCaps *caps; pipeline = gst_pipeline_new ("pipeline"); bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); #ifdef GST_API_VERSION_1 caps = gst_caps_new_simple ("audio/x-raw", "channels", G_TYPE_INT, 2, NULL); dec = gst_element_factory_make ("decodebin", "decoder"); #else caps = gst_caps_new_simple ("audio/x-raw-int", "channels", G_TYPE_INT, 2, NULL); dec = gst_element_factory_make ("decodebin2", "decoder"); #endif g_signal_connect (dec, "pad-added", G_CALLBACK (cb_newpad_ta), this); gst_bin_add (GST_BIN (pipeline), dec); audio = gst_bin_new ("audiobin"); conv = gst_element_factory_make ("audioconvert", "conv"); audiopad = gst_element_get_static_pad (conv, "sink"); analysis = gst_element_factory_make ("rganalysis", "analysis"); cutter = gst_element_factory_make ("cutter", "cutter"); sink = gst_element_factory_make ("fakesink", "sink"); g_object_set (analysis, "message", TRUE, NULL); g_object_set (analysis, "num-tracks", 1, NULL); g_object_set (cutter, "threshold-dB", -25.0, NULL); gst_bin_add_many (GST_BIN (audio), conv, analysis, cutter, sink, NULL); gst_element_link (conv, analysis); gst_element_link_filtered (analysis, cutter, caps); gst_element_link (cutter, sink); gst_element_add_pad (audio, gst_ghost_pad_new ("sink", audiopad)); gst_bin_add (GST_BIN (pipeline), audio); GstElement *l_src; l_src = gst_element_factory_make ("filesrc", "localsrc"); gst_bin_add_many (GST_BIN (pipeline), l_src, NULL); gst_element_set_state (l_src, GST_STATE_NULL); gst_element_link ( l_src,dec); gst_object_unref (audiopad); #ifdef GST_API_VERSION_1 gst_bus_set_sync_handler (bus, bus_cb, this, NULL); #else gst_bus_set_sync_handler (bus, bus_cb, this); #endif return pipeline; } double TrackAnalyser::gainDB() { return m_GainDB; } double TrackAnalyser::gainFactor() { return pow (10, m_GainDB / 20); } QTime TrackAnalyser::startPosition() { return m_StartPosition; } QTime TrackAnalyser::endPosition() { return m_EndPosition; } void TrackAnalyser::open(QUrl url) { //To avoid delays load track in another thread qDebug() << Q_FUNC_INFO <<":"<objectName()<<" url="< future = QtConcurrent::run( this, &TrackAnalyser::asyncOpen,url); p->watcher.setFuture(future); } void TrackAnalyser::asyncOpen(QUrl url) { p->mutex.lock(); m_GainDB = GAIN_INVALID; m_StartPosition = QTime(0,0); sync_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL); GstElement *l_src = gst_bin_get_by_name(GST_BIN(pipeline), "localsrc"); g_object_set (G_OBJECT (l_src), "location", (const char*)url.toLocalFile().toUtf8(), NULL); sync_set_state (GST_ELEMENT (pipeline), GST_STATE_PAUSED); m_MaxPosition=length(); m_EndPosition=m_MaxPosition; m_finished=false; gst_object_unref(l_src); p->mutex.unlock(); } void TrackAnalyser::loadThreadFinished() { // async load in player done qDebug() << Q_FUNC_INFO <<":"<objectName(); start(); } void TrackAnalyser::start() { qDebug() << Q_FUNC_INFO <<":"<objectName(); gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING); } bool TrackAnalyser::close() { gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL); return true; } QTime TrackAnalyser::length() { if (pipeline) { gint64 value=0; #ifdef GST_API_VERSION_1 if(gst_element_query_duration(pipeline, GST_FORMAT_TIME, &value)) { #else GstFormat fmt = GST_FORMAT_TIME; if(gst_element_query_duration(pipeline, &fmt, &value)) { #endif return QTime(0,0).addMSecs( static_cast( ( value / GST_MSECOND ) )); // nanosec -> msec } } return m_MaxPosition; } void TrackAnalyser::messageReceived(GstMessage *message) { switch (GST_MESSAGE_TYPE (message)) { case GST_MESSAGE_ERROR: { GError *err; gchar *debug; gst_message_parse_error (message, &err, &debug); QString str; str = "Error #"+QString::number(err->code)+" in module "+QString::number(err->domain)+"\n"+QString::fromUtf8(err->message); if(err->code == 6 && err->domain == 851) { str += "\nMay be you should to install gstreamer0.10-plugins-ugly or gstreamer0.10-plugins-bad"; } qDebug()<< "Gstreamer error:"<< str; g_error_free (err); g_free (debug); need_finish(); break; } case GST_MESSAGE_EOS:{ qDebug() << Q_FUNC_INFO <<":"<objectName()<<" End of track reached"; need_finish(); break; } case GST_MESSAGE_ELEMENT:{ GstClockTime timestamp; const GstStructure *s = gst_message_get_structure (message); const gchar *name = gst_structure_get_name (s); if (strcmp (name, "cutter") == 0) { gst_structure_get_clock_time (s, "timestamp", ×tamp); const GValue *value; value=gst_structure_get_value (s, "above"); bool isSilent=!g_value_get_boolean(value); //if we detect a falling edge, set EndPostion to this if (isSilent) m_EndPosition=QTime(0,0).addMSecs( static_cast( ( timestamp / GST_MSECOND ) )); // nanosec -> msec else { //if this is the first rising edge, set StartPosition if (m_StartPosition==QTime(0,0) && m_EndPosition==m_MaxPosition) m_StartPosition=QTime(0,0).addMSecs( static_cast( ( timestamp / GST_MSECOND ) )); // nanosec -> msec //if we detect a rising edge, set EndPostion to track end m_EndPosition=m_MaxPosition; } //qDebug() << Q_FUNC_INFO <( ( timestamp / GST_MSECOND ) ))<< " silent:" << isSilent; } break; } case GST_MESSAGE_TAG:{ GstTagList *tags = NULL; gst_message_parse_tag (message, &tags); if (gst_tag_list_get_double (tags, GST_TAG_TRACK_GAIN, &m_GainDB)) { qDebug() << Q_FUNC_INFO << ": Gain-db:" << m_GainDB; qDebug() << Q_FUNC_INFO << ": Gain-norm:" << pow (10, m_GainDB / 20); } } default: break; } } void TrackAnalyser::need_finish() { m_finished=true; Q_EMIT finish(); } knowthelist-2.3.0/src/djwidget.h0000775000175000017500000000321312423536022015633 0ustar mariomario/* Copyright (C) 2005-2014 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #ifndef DJWIDGET_H #define DJWIDGET_H #include #include "dj.h" #include "track.h" namespace Ui { class DjWidget; } class DjWidget : public QWidget { Q_OBJECT public: DjWidget(QWidget *parent = 0); ~DjWidget(); void setDj(Dj *dj); void slideCloseWidget(bool open); Dj* dj(); public Q_SLOTS: void activateDJ(); void deactivateDJ(); void updateView(); void clicked(); Q_SIGNALS: void activated(); void deleted(); void started(); void filterCountChanged(int count); protected: void changeEvent(QEvent *event); void mousePressEvent(QMouseEvent* event); void keyPressEvent(QKeyEvent *e); private slots: void on_lblName_linkActivated(const QString &link); void timerSlide_timeOut(); void on_pushClose_clicked(); void on_butPlayWidget_pressed(); private: Ui::DjWidget *ui; struct DjWidgetPrivate* p; }; #endif // DJWIDGET_H knowthelist-2.3.0/src/collectionwidget.h0000775000175000017500000000510612423536022017374 0ustar mariomario/* Copyright (C) 2005-2014 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #ifndef COLLECTIONWIDGET_H #define COLLECTIONWIDGET_H #include "collectiondb.h" #include "collectiontree.h" #include "modeselector.h" #include "playlist.h" #include "progressbar.h" #include #include #include #include #include //class CollectionUpdater; class QCustomEvent; class QPixmap; class QPoint; class QPushButton; class SearchEdit: public QLineEdit{ Q_OBJECT public: SearchEdit( QWidget* parent=0); ~SearchEdit(); void dropEvent(QDropEvent* event); void dragEnterEvent(QDragEnterEvent*); signals: void trackDropped(QString); protected: void resizeEvent(QResizeEvent *); void keyPressEvent (QKeyEvent* e); private slots: void updateCloseButton(const QString &text); private: QToolButton *clearButton; }; class CollectionWidget: public QWidget { Q_OBJECT public: CollectionWidget( QWidget* parent ); ~CollectionWidget(); Track* getRandomSong(QString genre); QString filterText(); bool hasItems(); void setTracklist(Playlist* pl); public slots: void setFilterText( QString strFilter ); void loadSettings(); void scan(); signals: void trackDropped(QString); void randomClicked(); void selectionChanged(QList); void wantLoad (QList,QString); void filterChanged(QString); void setupDirs(); private slots: void onSetFilterTimeout(); void onSetClicked(); void onSetFilter(); void onModeSelected(ModeSelector::modeType value); private: void resizeEvent(QResizeEvent *); class CollectionWidgetPrivate *p; }; #endif /* COLLECTIONWIDGET_H */ knowthelist-2.3.0/src/modeselector.h0000664000175000017500000000253312423536022016520 0ustar mariomario/* Copyright (C) 2014 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #ifndef MODESELECTOR_H #define MODESELECTOR_H #include namespace Ui { class ModeSelector; } class ModeSelector : public QFrame { Q_OBJECT public: explicit ModeSelector(QWidget *parent = 0); ~ModeSelector(); enum modeType { MODENONE, MODEYEAR, MODEGENRE }; void setMode(ModeSelector::modeType value); ModeSelector::modeType mode(); Q_SIGNALS: void modeChanged(ModeSelector::modeType value); private slots: void on_push1_clicked(); void on_push2_clicked(); void on_push3_clicked(); private: Ui::ModeSelector *ui; modeType selMode; }; #endif // MODESELECTOR_H knowthelist-2.3.0/src/collectiontree.h0000664000175000017500000000401712423536022017045 0ustar mariomario/* Copyright (C) 2005-2014 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #ifndef COLLVIEW_H #define COLLVIEW_H #include #include "collectiondb.h" #include "collectiontreeitem.h" #include "track.h" class QMouseEvent; class CollectionTree : public QTreeWidget { Q_OBJECT public: explicit CollectionTree(QWidget *parent = 0); ~CollectionTree(); QString filter(); enum modeType { MODENONE, MODEYEAR, MODEGENRE }; modeType treeMode; Q_SIGNALS: void selectionChanged(QList); void wantLoad(QList, QString); void rescan(); public slots: void on_currentItemChanged( QTreeWidgetItem* item ); void on_itemExpanded( QTreeWidgetItem* item ); void showContextMenu(QTreeWidgetItem *, int ); void triggerRandomSelection(); void asynchronTriggerRandomSelection(); void setFilter( QString filter ); void createTrunk(); void onRescanTriggered(); void onLoad1Triggered(); void onLoad2Triggered(); private: class CollectionTreePrivate * p; void mousePressEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); void resizeEvent(QResizeEvent *); void performDrag(); QPoint startPos; bool openContext; bool m_dragLocked; void showTrackInfo( Track* mb ); void asynchronCurrentItemChanged( QTreeWidgetItem* item ); }; #endif // COLLVIEW_H knowthelist-2.3.0/src/djsession.h0000775000175000017500000000375212423536022016043 0ustar mariomario/* Copyright (C) 2005-2014 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #ifndef DJSESSION_H #define DJSESSION_H #include "dj.h" #include "collectiondb.h" #include class Track; class DjSession : public QObject { Q_OBJECT public: DjSession(); ~DjSession(); Dj mainDJ; int minCount(); void setMinCount(int value); void setIsEnabledAutoDJCount(bool value); bool isEnabledAutoDJCount(); Track* getRandomTrack(); Dj* currentDj(); Q_SIGNALS: void foundTracks_Playlist1(QList); void foundTracks_Playlist2(QList); void changed_Playlist1(QPair); void changed_Playlist2(QPair); void savedPlaylists(); public slots: void updatePlaylists(); void playDefaultList(); void onTracksChanged_Playlist1(QList tracks); void onTracksChanged_Playlist2(QList tracks); void onTrackFinished(Track *track); void forceTracks(QList tracks); void on_dj_filterChanged(Filter* f); void onResetStats(); void onTrackPropertyChanged(Track* track); void savePlaylists( const QString &filename ); void storePlaylists(const QString &name , bool replace=false); void setCurrentDj(Dj*); private: class DjSessionPrivate *p; void searchTracks(); void summariseCount(); }; #endif // DJSESSION_H knowthelist-2.3.0/src/dj.h0000775000175000017500000000304612423536022014433 0ustar mariomario/* Copyright (C) 2005-2014 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #ifndef DJ_H #define DJ_H #include "filter.h" class Dj: public QObject { Q_OBJECT public: Dj(); ~Dj(); QList filters(); Filter* requestFilter(); QString name; QString description(); void setDescription(QString); int countTracks(); void setCountTracks(int); int lengthTracks(); void setLengthTracks(int); void addFilter(Filter* filter); void removeFilter(Filter* filter); void setActiveFilterIdx(int idx); int activeFilterIdx(); Q_SIGNALS: void filterChanged(Filter*); void countChanged(); private Q_SLOTS: void on_filter_activated(); void on_filter_filterChanged(); void on_filter_countChanged(); void on_filter_maxUsageChanged(); void checkSequence(); protected: private: struct DjPrivate* p; }; #endif // DJ_H knowthelist-2.3.0/src/djwidget.ui0000775000175000017500000002257012423536022016030 0ustar mariomario DjWidget 0 0 435 75 100 75 Form false QFrame#frameDj{ background: qlineargradient( x1:0, y1:0, x2:0, y2:1, stop: 0.01 #202020, stop:0.11 #505050, stop:1 #505050 ); } QFrame#frameDj::item:selected { border: 1px solid #6a6ea9; } QFrame#frameDj::item:selected:!active { background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ABAFE5, stop: 1 #8588B2); } QFrame#frameDj::item:selected:active { background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6a6ea9, stop: 1 #888dd9); } QFrame#frameDj::item:hover { background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #FAFBFE, stop: 1 #DCDEF1); } 0 0 0 76 QFrame::NoFrame QFrame::Raised 10 12 0 5 0 26 26 AutoDJ :/DJ.png true 0 0 0 0 22 16777215 22 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="#"><span style=" font-size:8pt; text-decoration: underline; color:#d0fff8;">DJ Main</span></a></p></body></html> false Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop false 0 0 45 0 QFrame::NoFrame QFrame::Raised 32 0 0 6 0 0 35 0 16777215 16777215 Start a session of this DJ :/play.png:/play.png Remove this DJ x 0 0 0 0 32000 60 TextLabel false true 0 0 18 16777215 <html><head/><body><p>Confirm the remove</p></body></html> background-color: rgb(255, 65, 87); Delete knowthelist-2.3.0/src/fancytabwidget.cpp0000775000175000017500000005215012423536022017364 0ustar mariomario/************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** Commercial Usage ** ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at http://qt.nokia.com/contact. ** **************************************************************************/ #include "fancytabwidget.h" #include "stylehelper.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace Core; using namespace Internal; const int FancyTabBar::m_rounding = 22; const int FancyTabBar::m_textPadding = 4; void FancyTabProxyStyle::drawControl( ControlElement element, const QStyleOption* option, QPainter* p, const QWidget* widget) const { const QStyleOptionTabV3* v_opt = qstyleoption_cast(option); if (element != CE_TabBarTab || !v_opt) { QProxyStyle::drawControl(element, option, p, widget); return; } const QRect rect = v_opt->rect; const bool selected = v_opt->state & State_Selected; const bool vertical_tabs = v_opt->shape == QTabBar::RoundedWest; const QString text = v_opt->text; if (selected) { //background p->save(); QLinearGradient grad(rect.topLeft(), rect.topRight()); grad.setColorAt(0, QColor(255, 255, 255, 140)); grad.setColorAt(1, QColor(255, 255, 255, 210)); p->fillRect(rect.adjusted(0, 0, 0, -1), grad); p->restore(); //shadows p->setPen(QColor(0, 0, 0, 110)); p->drawLine(rect.topLeft() + QPoint(1,-1), rect.topRight() - QPoint(0,1)); p->drawLine(rect.bottomLeft(), rect.bottomRight()); p->setPen(QColor(0, 0, 0, 40)); p->drawLine(rect.topLeft(), rect.bottomLeft()); //highlights p->setPen(QColor(255, 255, 255, 50)); p->drawLine(rect.topLeft() + QPoint(0, -2), rect.topRight() - QPoint(0,2)); p->drawLine(rect.bottomLeft() + QPoint(0, 1), rect.bottomRight() + QPoint(0,1)); p->setPen(QColor(255, 255, 255, 40)); p->drawLine(rect.topLeft() + QPoint(0, 0), rect.topRight()); p->drawLine(rect.topRight() + QPoint(0, 1), rect.bottomRight() - QPoint(0, 1)); p->drawLine(rect.bottomLeft() + QPoint(0,-1), rect.bottomRight()-QPoint(0,1)); } QTransform m; if (vertical_tabs) { m = QTransform::fromTranslate(rect.left(), rect.bottom()); m.rotate(-90); } else { m = QTransform::fromTranslate(rect.left(), rect.top()); } const QRect draw_rect(QPoint(0, 0), m.mapRect(rect).size()); p->save(); p->setTransform(m); QRect icon_rect(QPoint(8, 0), v_opt->iconSize); QRect text_rect(icon_rect.topRight() + QPoint(4, 0), draw_rect.size()); text_rect.setRight(draw_rect.width()); icon_rect.translate(0, (draw_rect.height() - icon_rect.height()) / 2); QFont boldFont(p->font()); boldFont.setPointSizeF(Utils::StyleHelper::sidebarFontSize()); boldFont.setBold(true); p->setFont(boldFont); p->setPen(selected ? QColor(255, 255, 255, 160) : QColor(0, 0, 0, 110)); int textFlags = Qt::AlignHCenter | Qt::AlignVCenter; p->drawText(text_rect, textFlags, text); p->setPen(selected ? QColor(60, 60, 60) : Utils::StyleHelper::panelTextColor()); #ifndef Q_WS_MAC if (widget) { const QString fader_key = "tab_" + text + "_fader"; const QString animation_key = "tab_" + text + "_animation"; const QString tab_hover = widget->property("tab_hover").toString(); int fader = widget->property(fader_key.toUtf8().constData()).toInt(); QPropertyAnimation* animation = widget->property(animation_key.toUtf8().constData()).value(); if (!animation) { QWidget* mut_widget = const_cast(widget); fader = 0; mut_widget->setProperty(fader_key.toUtf8().constData(), fader); animation = new QPropertyAnimation(mut_widget, fader_key.toUtf8(), mut_widget); connect(animation, SIGNAL(valueChanged(QVariant)), mut_widget, SLOT(update())); mut_widget->setProperty(animation_key.toUtf8().constData(), QVariant::fromValue(animation)); } if (text == tab_hover) { if (animation->state() != QAbstractAnimation::Running && fader != 40) { animation->stop(); animation->setDuration(80); animation->setEndValue(40); animation->start(); } } else { if (animation->state() != QAbstractAnimation::Running && fader != 0) { animation->stop(); animation->setDuration(160); animation->setEndValue(0); animation->start(); } } if (!selected) { p->save(); QLinearGradient grad(draw_rect.topLeft(), vertical_tabs ? draw_rect.bottomLeft() : draw_rect.topRight()); grad.setColorAt(0, Qt::transparent); grad.setColorAt(0.5, QColor(255, 255, 255, fader)); grad.setColorAt(1, Qt::transparent); p->fillRect(draw_rect, grad); p->setPen(QPen(grad, 1.0)); p->drawLine(draw_rect.topLeft(), vertical_tabs ? draw_rect.bottomLeft() : draw_rect.topRight()); p->drawLine(draw_rect.bottomRight(), vertical_tabs ? draw_rect.topRight() : draw_rect.bottomLeft()); p->restore(); } } #endif Utils::StyleHelper::drawIconWithShadow(v_opt->icon, icon_rect, p, QIcon::Normal); p->drawText(text_rect.translated(0, -1), textFlags, text); p->restore(); } void FancyTabProxyStyle::polish(QWidget* widget) { if (QString(widget->metaObject()->className()) == "QTabBar") { widget->setMouseTracking(true); widget->installEventFilter(this); } QProxyStyle::polish(widget); } void FancyTabProxyStyle::polish(QApplication* app) { QProxyStyle::polish(app); } void FancyTabProxyStyle::polish(QPalette& palette) { QProxyStyle::polish(palette); } bool FancyTabProxyStyle::eventFilter(QObject* o, QEvent* e) { QTabBar* bar = qobject_cast(o); if (bar && (e->type() == QEvent::MouseMove || e->type() == QEvent::Leave)) { QMouseEvent* event = static_cast(e); const QString old_hovered_tab = bar->property("tab_hover").toString(); const QString hovered_tab = e->type() == QEvent::Leave ? QString() : bar->tabText(bar->tabAt(event->pos())); bar->setProperty("tab_hover", hovered_tab); if (old_hovered_tab != hovered_tab) bar->update(); } return false; } FancyTab::FancyTab(QWidget* tabbar) : QWidget(tabbar), tabbar(tabbar), m_fader(0) { animator.setPropertyName("fader"); animator.setTargetObject(this); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum); } void FancyTab::fadeIn() { animator.stop(); animator.setDuration(80); animator.setEndValue(40); animator.start(); } void FancyTab::fadeOut() { animator.stop(); animator.setDuration(160); animator.setEndValue(0); animator.start(); } void FancyTab::setFader(float value) { m_fader = value; tabbar->update(); } FancyTabBar::FancyTabBar(QWidget *parent) : QWidget(parent) { setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); setStyle(new QCommonStyle); setMinimumWidth(qMax(2 * m_rounding, 40)); setAttribute(Qt::WA_Hover, true); setFocusPolicy(Qt::NoFocus); setMouseTracking(true); // Needed for hover events m_triggerTimer.setSingleShot(true); QVBoxLayout* layout = new QVBoxLayout; layout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding)); layout->setSpacing(0); layout->setContentsMargins(0, 0, 0, 0); setLayout(layout); // We use a zerotimer to keep the sidebar responsive connect(&m_triggerTimer, SIGNAL(timeout()), this, SLOT(emitCurrentIndex())); } FancyTabBar::~FancyTabBar() { delete style(); } QSize FancyTab::sizeHint() const { QFont boldFont(font()); boldFont.setPointSizeF(Utils::StyleHelper::sidebarFontSize()); boldFont.setBold(true); QFontMetrics fm(boldFont); int spacing = 8; int width = 60 + spacing + 2; int iconHeight = 32; QSize ret(width, iconHeight + spacing + fm.height()); return ret; } QSize FancyTabBar::tabSizeHint(bool minimum) const { QFont boldFont(font()); boldFont.setPointSizeF(Utils::StyleHelper::sidebarFontSize()); boldFont.setBold(true); QFontMetrics fm(boldFont); int spacing = 8; int width = 60 + spacing + 2; int iconHeight = minimum ? 0 : 32; return QSize(width, iconHeight + spacing + fm.height()); } void FancyTabBar::paintEvent(QPaintEvent *event) { Q_UNUSED(event) QPainter p(this); for (int i = 0; i < count(); ++i) if (i != currentIndex()) paintTab(&p, i); // paint active tab last, since it overlaps the neighbors if (currentIndex() != -1) paintTab(&p, currentIndex()); } void FancyTab::enterEvent(QEvent*) { fadeIn(); } void FancyTab::leaveEvent(QEvent*) { fadeOut(); } QSize FancyTabBar::sizeHint() const { QSize sh = tabSizeHint(); return QSize(sh.width(), sh.height() * m_tabs.count()); } QSize FancyTabBar::minimumSizeHint() const { QSize sh = tabSizeHint(true); return QSize(sh.width(), sh.height() * m_tabs.count()); } QRect FancyTabBar::tabRect(int index) const { return m_tabs[index]->geometry(); } QString FancyTabBar::tabToolTip(int index) const { return m_tabs[index]->toolTip(); } void FancyTabBar::setTabToolTip(int index, const QString& toolTip) { m_tabs[index]->setToolTip(toolTip); } // This keeps the sidebar responsive since // we get a repaint before loading the // mode itself void FancyTabBar::emitCurrentIndex() { emit currentChanged(m_currentIndex); } void FancyTabBar::mousePressEvent(QMouseEvent *e) { e->accept(); for (int index = 0; index < m_tabs.count(); ++index) { if (tabRect(index).contains(e->pos())) { m_currentIndex = index; update(); m_triggerTimer.start(0); break; } } } void FancyTabBar::addTab(const QIcon& icon, const QString& label) { FancyTab *tab = new FancyTab(this); tab->icon = icon; tab->text = label; m_tabs.append(tab); qobject_cast(layout())->insertWidget(layout()->count()-1, tab); } void FancyTabBar::addSpacer(int size) { qobject_cast(layout())->insertSpacerItem(layout()->count()-1, new QSpacerItem(0, size, QSizePolicy::Fixed, QSizePolicy::Maximum)); } void FancyTabBar::paintTab(QPainter *painter, int tabIndex) const { if (!validIndex(tabIndex)) { qWarning("invalid index"); return; } painter->save(); QRect rect = tabRect(tabIndex); bool selected = (tabIndex == m_currentIndex); if (selected) { //background painter->save(); QLinearGradient grad(rect.topLeft(), rect.topRight()); grad.setColorAt(0, QColor(255, 255, 255, 140)); grad.setColorAt(1, QColor(255, 255, 255, 210)); painter->fillRect(rect.adjusted(0, 0, 0, -1), grad); painter->restore(); //shadows painter->setPen(QColor(0, 0, 0, 110)); painter->drawLine(rect.topLeft() + QPoint(1,-1), rect.topRight() - QPoint(0,1)); painter->drawLine(rect.bottomLeft(), rect.bottomRight()); painter->setPen(QColor(0, 0, 0, 40)); painter->drawLine(rect.topLeft(), rect.bottomLeft()); //highlights painter->setPen(QColor(255, 255, 255, 50)); painter->drawLine(rect.topLeft() + QPoint(0, -2), rect.topRight() - QPoint(0,2)); painter->drawLine(rect.bottomLeft() + QPoint(0, 1), rect.bottomRight() + QPoint(0,1)); painter->setPen(QColor(255, 255, 255, 40)); painter->drawLine(rect.topLeft() + QPoint(0, 0), rect.topRight()); painter->drawLine(rect.topRight() + QPoint(0, 1), rect.bottomRight() - QPoint(0, 1)); painter->drawLine(rect.bottomLeft() + QPoint(0,-1), rect.bottomRight()-QPoint(0,1)); } QString tabText(painter->fontMetrics().elidedText(this->tabText(tabIndex), Qt::ElideRight, width())); QRect tabTextRect(tabRect(tabIndex)); QRect tabIconRect(tabTextRect); tabIconRect.adjust(+4, +4, -4, -4); tabTextRect.translate(0, -2); QFont boldFont(painter->font()); boldFont.setPointSizeF(Utils::StyleHelper::sidebarFontSize()); boldFont.setBold(true); painter->setFont(boldFont); painter->setPen(selected ? QColor(255, 255, 255, 160) : QColor(0, 0, 0, 110)); int textFlags = Qt::AlignCenter | Qt::AlignBottom; painter->drawText(tabTextRect, textFlags, tabText); painter->setPen(selected ? QColor(60, 60, 60) : Utils::StyleHelper::panelTextColor()); #ifndef Q_WS_MAC if (!selected) { painter->save(); int fader = int(m_tabs[tabIndex]->fader()); QLinearGradient grad(rect.topLeft(), rect.topRight()); grad.setColorAt(0, Qt::transparent); grad.setColorAt(0.5, QColor(255, 255, 255, fader)); grad.setColorAt(1, Qt::transparent); painter->fillRect(rect, grad); painter->setPen(QPen(grad, 1.0)); painter->drawLine(rect.topLeft(), rect.topRight()); painter->drawLine(rect.bottomLeft(), rect.bottomRight()); painter->restore(); } #endif const int textHeight = painter->fontMetrics().height(); tabIconRect.adjust(0, 4, 0, -textHeight); Utils::StyleHelper::drawIconWithShadow(tabIcon(tabIndex), tabIconRect, painter, QIcon::Normal); painter->translate(0, -1); painter->drawText(tabTextRect, textFlags, tabText); painter->restore(); } void FancyTabBar::setCurrentIndex(int index) { m_currentIndex = index; update(); emit currentChanged(m_currentIndex); } ////// // FancyColorButton ////// class FancyColorButton : public QWidget { public: FancyColorButton(QWidget *parent) : m_parent(parent) { setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred); } void mousePressEvent(QMouseEvent *ev) { if (ev->modifiers() & Qt::ShiftModifier) Utils::StyleHelper::setBaseColor(QColorDialog::getColor(Utils::StyleHelper::requestedBaseColor(), m_parent)); } private: QWidget *m_parent; }; ////// // FancyTabWidget ////// FancyTabWidget::FancyTabWidget(QWidget* parent) : QWidget(parent), mode_(Mode_None), tab_bar_(NULL), stack_(new QStackedLayout), side_widget_(new QWidget), side_layout_(new QVBoxLayout), top_layout_(new QVBoxLayout), use_background_(false), menu_(NULL), proxy_style_(new FancyTabProxyStyle) { side_layout_->setSpacing(0); side_layout_->setMargin(0); side_layout_->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding)); side_widget_->setLayout(side_layout_); side_widget_->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding); top_layout_->setMargin(0); top_layout_->setSpacing(0); top_layout_->addLayout(stack_); QHBoxLayout* main_layout = new QHBoxLayout; main_layout->setMargin(0); main_layout->setSpacing(1); main_layout->addWidget(side_widget_); main_layout->addLayout(top_layout_); setLayout(main_layout); } void FancyTabWidget::AddTab(QWidget* tab, const QIcon& icon, const QString& label) { stack_->addWidget(tab); items_ << Item(icon, label); } void FancyTabWidget::AddSpacer(int size) { items_ << Item(size); } void FancyTabWidget::SetBackgroundPixmap(const QPixmap& pixmap) { background_pixmap_ = pixmap; update(); } void FancyTabWidget::paintEvent(QPaintEvent*) { if (!use_background_) return; QPainter painter(this); QRect rect = side_widget_->rect().adjusted(0, 0, 1, 0); rect = style()->visualRect(layoutDirection(), geometry(), rect); Utils::StyleHelper::verticalGradient(&painter, rect, rect); if (!background_pixmap_.isNull()) { QRect pixmap_rect(background_pixmap_.rect()); pixmap_rect.moveTo(rect.topLeft()); while (pixmap_rect.top() < rect.bottom()) { QRect source_rect(pixmap_rect.intersected(rect)); source_rect.moveTo(0, 0); painter.drawPixmap(pixmap_rect.topLeft(), background_pixmap_, source_rect); pixmap_rect.moveTop(pixmap_rect.bottom() - 10); } } painter.setPen(Utils::StyleHelper::borderColor()); painter.drawLine(rect.topRight(), rect.bottomRight()); QColor light = Utils::StyleHelper::sidebarHighlight(); painter.setPen(light); painter.drawLine(rect.bottomLeft(), rect.bottomRight()); } int FancyTabWidget::current_index() const { return stack_->currentIndex(); } void FancyTabWidget::SetCurrentIndex(int index) { if (FancyTabBar* bar = qobject_cast(tab_bar_)) { bar->setCurrentIndex(index); } else if (QTabBar* bar = qobject_cast(tab_bar_)) { bar->setCurrentIndex(index); } else { stack_->setCurrentIndex(index); } } void FancyTabWidget::ShowWidget(int index) { stack_->setCurrentIndex(index); emit CurrentChanged(index); } void FancyTabWidget::AddBottomWidget(QWidget* widget) { top_layout_->addWidget(widget); } void FancyTabWidget::SetMode(Mode mode) { // Remove previous tab bar delete tab_bar_; tab_bar_ = NULL; use_background_ = false; // Create new tab bar switch (mode) { case Mode_None: default: qDebug() << "Unknown fancy tab mode" << mode; // fallthrough case Mode_LargeSidebar: { FancyTabBar* bar = new FancyTabBar(this); side_layout_->insertWidget(0, bar); tab_bar_ = bar; foreach (const Item& item, items_) { if (item.type_ == Item::Type_Spacer) bar->addSpacer(item.spacer_size_); else bar->addTab(item.tab_icon_, item.tab_label_); } bar->setCurrentIndex(stack_->currentIndex()); connect(bar, SIGNAL(currentChanged(int)), SLOT(ShowWidget(int))); use_background_ = true; break; } case Mode_Tabs: MakeTabBar(QTabBar::RoundedNorth, true, false, false); break; case Mode_IconOnlyTabs: MakeTabBar(QTabBar::RoundedNorth, false, true, false); break; case Mode_SmallSidebar: MakeTabBar(QTabBar::RoundedWest, true, true, true); use_background_ = true; break; case Mode_PlainSidebar: MakeTabBar(QTabBar::RoundedWest, true, true, false); break; } tab_bar_->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); mode_ = mode; emit ModeChanged(mode); update(); } void FancyTabWidget::contextMenuEvent(QContextMenuEvent* e) { if (!menu_) { menu_ = new QMenu(this); QSignalMapper* mapper = new QSignalMapper(this); QActionGroup* group = new QActionGroup(this); AddMenuItem(mapper, group, tr("Large sidebar"), Mode_LargeSidebar); AddMenuItem(mapper, group, tr("Small sidebar"), Mode_SmallSidebar); AddMenuItem(mapper, group, tr("Plain sidebar"), Mode_PlainSidebar); AddMenuItem(mapper, group, tr("Tabs on top"), Mode_Tabs); AddMenuItem(mapper, group, tr("Icons on top"), Mode_IconOnlyTabs); menu_->addActions(group->actions()); connect(mapper, SIGNAL(mapped(int)), SLOT(SetMode(int))); } menu_->popup(e->globalPos()); } void FancyTabWidget::AddMenuItem(QSignalMapper* mapper, QActionGroup* group, const QString& text, Mode mode) { QAction* action = group->addAction(text); action->setCheckable(true); mapper->setMapping(action, mode); connect(action, SIGNAL(triggered()), mapper, SLOT(map())); if (mode == mode_) action->setChecked(true); } void FancyTabWidget::MakeTabBar(QTabBar::Shape shape, bool text, bool icons, bool fancy) { QTabBar* bar = new QTabBar(this); bar->setShape(shape); bar->setDocumentMode(true); bar->setUsesScrollButtons(true); if (shape == QTabBar::RoundedWest) { bar->setIconSize(QSize(22, 22)); } if (fancy) { bar->setStyle(proxy_style_.data()); } if (shape == QTabBar::RoundedNorth) top_layout_->insertWidget(0, bar); else side_layout_->insertWidget(0, bar); foreach (const Item& item, items_) { if (item.type_ != Item::Type_Tab) continue; QString label = item.tab_label_; if (shape == QTabBar::RoundedWest) { label = QFontMetrics(font()).elidedText(label, Qt::ElideMiddle, 100); } int tab_id = -1; if (icons && text) tab_id = bar->addTab(item.tab_icon_, label); else if (icons) tab_id = bar->addTab(item.tab_icon_, QString()); else if (text) tab_id = bar->addTab(label); bar->setTabToolTip(tab_id, item.tab_label_); } bar->setCurrentIndex(stack_->currentIndex()); connect(bar, SIGNAL(currentChanged(int)), SLOT(ShowWidget(int))); tab_bar_ = bar; } knowthelist-2.3.0/src/collectionwidget.cpp0000775000175000017500000002175012423536022017732 0ustar mariomario/* Copyright (C) 2005-2014 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #include "collectionwidget.h" #include "collectiontree.h" #include "collectionupdater.h" #include "progressbar.h" #include "modeselector.h" #include "track.h" #include #include #include #include #include #include #include #include class CollectionWidgetPrivate { public: QMenu *actionsMenu; QAction* actionScan; CollectionTree *collectiontree; ProgressBar *progress; CollectionUpdater *updater; QTimer *timer; QToolButton *button; SearchEdit *searchEdit; ModeSelector *modeSelect; }; CollectionWidget::CollectionWidget( QWidget* parent ): QWidget(parent) { p = new CollectionWidgetPrivate; QPushButton *pushRandom =new QPushButton(); QPixmap pixmap2(":shuffle.png"); pushRandom->setIcon(QIcon(pixmap2)); pushRandom->setIconSize(QSize(27,27)); pushRandom->setMaximumWidth(40); pushRandom->setStyleSheet("QPushButton { border: none; padding: 0px; margin-left: 10px;max-height: 20px; margin-right: 4px;}"); pushRandom->setToolTip(tr( "Random Tracks" )); p->searchEdit = new SearchEdit(); p->searchEdit->setToolTip(tr( "Enter space-separated terms to filter collection" )); QVBoxLayout *mainLayout = new QVBoxLayout; QWidget *headWidget = new QWidget(this); headWidget->setMaximumHeight(38); QHBoxLayout *headWidgetLayout = new QHBoxLayout; headWidgetLayout->setMargin(0); headWidgetLayout->setSpacing(1); headWidgetLayout->addSpacerItem(new QSpacerItem(10, 0, QSizePolicy::Fixed, QSizePolicy::Expanding)); headWidgetLayout->addWidget(p->searchEdit); headWidgetLayout->addWidget(pushRandom); headWidget->setLayout(headWidgetLayout); p->updater = new CollectionUpdater(); p->timer = new QTimer( this ); p->timer->setInterval(300); p->timer->setSingleShot(true); p->collectiontree = new CollectionTree(this); p->modeSelect = new ModeSelector(p->collectiontree); headWidget->raise(); mainLayout->addWidget(headWidget); mainLayout->setMargin(0); mainLayout->setSpacing(0); connect(pushRandom,SIGNAL(clicked()), p->collectiontree,SLOT(triggerRandomSelection()) ); connect ( p->modeSelect , SIGNAL(modeChanged(ModeSelector::modeType)), this, SLOT(onModeSelected(ModeSelector::modeType))); connect( p->searchEdit, SIGNAL( textChanged( const QString& ) ), this, SLOT( onSetFilterTimeout() ) ); connect( p->searchEdit, SIGNAL( trackDropped(QString)), this, SIGNAL( trackDropped(QString)) ); connect( p->collectiontree, SIGNAL(selectionChanged(QList)), this, SIGNAL(selectionChanged(QList))); connect( p->collectiontree, SIGNAL(wantLoad(QList,QString)), this, SIGNAL(wantLoad(QList,QString))); connect( p->updater, SIGNAL(changesDone()), p->collectiontree, SLOT(createTrunk())); connect( p->collectiontree, SIGNAL(rescan()), p->updater, SLOT(scan())); connect( p->timer, SIGNAL(timeout()), SLOT(onSetFilter()) ); setFocusProxy( p->collectiontree ); //default object to get focus setMaximumWidth(400); //Pogressbar for re-read collection p->progress = new ProgressBar(this); p->progress->setValue(0); p->progress->setStyleSheet("* { margin-bottom: 3px; }"); mainLayout->addWidget(p->collectiontree); // Read config values QSettings settings; p->modeSelect->setMode( static_cast(settings.value("TreeMode",ModeSelector::MODENONE).toUInt())); p->collectiontree->createTrunk(); setLayout(mainLayout); connect(p->updater, SIGNAL(progressChanged(int)), p->progress,SLOT(setValue(int))); connect(p->progress, SIGNAL(stopped()), p->updater,SLOT(stop())); p->modeSelect->show(); } CollectionWidget::~CollectionWidget() { QSettings settings; settings.setValue("TreeMode",p->collectiontree->treeMode); delete p; } void CollectionWidget::scan() { if (p->progress->isHidden()){ QSettings settings; p->updater->setDirectoryList( settings.value("Dirs").toStringList(), true ); } } void CollectionWidget::onModeSelected(ModeSelector::modeType value) { p->collectiontree->treeMode = static_cast(value); p->collectiontree->createTrunk(); } void CollectionWidget::onSetFilterTimeout() { if ( p->timer->isActive() ) p->timer->stop(); p->timer->start(); } void CollectionWidget::onSetFilter() { p->collectiontree->setFilter( p->searchEdit->text() ); p->collectiontree->createTrunk(); } void CollectionWidget::onSetClicked() { p->actionsMenu->popup(QCursor::pos(),0); } bool CollectionWidget::hasItems() { return (p->collectiontree->topLevelItemCount() > 0); } void CollectionWidget::loadSettings() { QSettings settings; p->updater->setDoMonitor( settings.value("Monitor").toBool() ); p->updater->setDirectoryList( settings.value("Dirs").toStringList()); } void CollectionWidget::setFilterText( QString strFilter ){ p->searchEdit->setText( strFilter ); onSetFilter(); } QString CollectionWidget::filterText() { return p->searchEdit->text() ; } void CollectionWidget::resizeEvent(QResizeEvent *) { QRect rec = p->collectiontree->geometry(); #if defined(Q_OS_DARWIN) int y = 39; #else int y = 41; #endif p->progress->setGeometry(0,y,rec.width()-20,20); p->modeSelect->setGeometry(rec.width()-p->modeSelect->width(),0,p->modeSelect->width(),20); } SearchEdit::SearchEdit(QWidget *parent) :QLineEdit(parent){ QPixmap searchIcon(":search.png"); QLabel* lbl = new QLabel(this); lbl->setScaledContents(true); lbl->setPixmap(searchIcon); lbl->setFixedSize(QSize(21,21)); lbl->setStyleSheet("QLabel { border: none; padding: 0px; margin-left: 9px; margin-top: 8px;}"); clearButton = new QToolButton(this); QPixmap pixmap(":clear_left.png"); clearButton->setIcon(QIcon(pixmap)); clearButton->setIconSize(QSize(18,18)); clearButton->setCursor(Qt::ArrowCursor); clearButton->setStyleSheet("QToolButton { border: none; padding: 0px; margin-right: 2px; margin-top: 3px;}"); clearButton->hide(); setAttribute(Qt::WA_MacShowFocusRect, false); connect(clearButton, SIGNAL(clicked()), this, SLOT(clear())); connect(this, SIGNAL(textChanged(const QString&)), this, SLOT(updateCloseButton(const QString&))); int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth); //setStyleSheet(QString("QLineEdit { padding-right: %1px; } ").arg(clearButton->sizeHint().width() + frameWidth + 1)); QSize msz = minimumSizeHint(); setMinimumSize(qMax(msz.width(), clearButton->sizeHint().height() + frameWidth * 2 + 2), qMax(msz.height(), clearButton->sizeHint().height() + frameWidth * 2 + 2)); } SearchEdit::~SearchEdit(){ } void SearchEdit::dragEnterEvent(QDragEnterEvent *event) { if (event->mimeData()->hasFormat("text/playlistitem")) event->accept(); } void SearchEdit::dropEvent( QDropEvent *event ) { if (event->mimeData()->hasFormat("text/playlistitem")) { //decode playlistitem QByteArray itemData = event->mimeData()->data("text/playlistitem"); QDataStream stream(&itemData, QIODevice::ReadOnly); QVector tags; stream >> tags; event->setDropAction(Qt::CopyAction); event->accept(); if ( tags.count() >0 ){ Track *track = new Track(tags[0]); this->setText(track->artist()); } } else event->ignore(); } void SearchEdit::resizeEvent(QResizeEvent *) { QSize sz = clearButton->sizeHint(); int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth); clearButton->move(rect().right() - frameWidth - sz.width(), (rect().bottom() + 2 - sz.height())/2); } // esc key for clean up void SearchEdit::keyPressEvent(QKeyEvent *e) { if( e->key() == Qt::Key_Escape ) this->setText(""); else QLineEdit::keyPressEvent( e ); } void SearchEdit::updateCloseButton(const QString &text) { clearButton->setVisible(!text.isEmpty()); } knowthelist-2.3.0/src/qvumeter.h0000775000175000017500000000566512423536022015717 0ustar mariomario/*************************************************************************** * Copyright (C) 2008 - Giuseppe Cigala * * g_cigala@virgilio.it * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef QVUMETER_H #define QVUMETER_H #include //#include #include class QVUMeter : public QWidget { Q_OBJECT QColor colorBg() const { return colBack; } QColor colorValue() const { return colValue; } QColor colorLow() const { return colLow; } QColor colorHigh() const { return colHigh; } double leftValue() const { return leftVal; } double rightValue() const { return rightVal; } double minValue() const { return min; } double maxValue() const { return max; } int valueDim() const { return dimVal; } public: QVUMeter(QWidget *parent = 0); QSize minimumSizeHint() const; QSize sizeHint() const; Q_SIGNALS: void valueLChanged(double); void valueRChanged(double); public Q_SLOTS: void setColorBg(QColor); void setColorValue(QColor); void setColorHigh(QColor); void setColorLow(QColor); void setValueDim(int); void setLeftValue(double); void setRightValue(double); void setMinValue(double); void setMaxValue(double); protected: void paintEvent(QPaintEvent *); void paintBorder(); void paintBar(); void paintValue(); private: double min; double max; double leftVal; double rightVal; int dimVal; QColor colBack; QColor colValue; QColor colHigh; QColor colLow; }; #endif knowthelist-2.3.0/src/knowthelist.rc0000775000175000017500000000010612423536022016560 0ustar mariomarioIDI_ICON1 ICON DISCARDABLE "../dist/headset.ico" knowthelist-2.3.0/src/stackdisplay.h0000775000175000017500000000240312423536022016525 0ustar mariomario/* Copyright (C) 2014 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #ifndef STACKDISPLAY_H #define STACKDISPLAY_H #include class StackDisplay : public QWidget { Q_OBJECT public: explicit StackDisplay(QWidget *parent = 0); ~StackDisplay(); void setCount ( int value ); void setSelected( int value ); void setMargin( int value); void setBarColor ( QColor color ); signals: public slots: private: void resizeEvent( QResizeEvent* e ); void paintEvent(QPaintEvent *); void drawBars(); class StackDisplayPrivate *p; }; #endif // STACKDISPLAY_H knowthelist-2.3.0/src/vumeter.h0000775000175000017500000000441012423536022015521 0ustar mariomario/* Copyright (C) 2005-2014 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #ifndef VUMETER_H #define VUMETER_H #include #include #include // helper functions const float LEVEL_MIN= 1.f/(1<<20); // minimal positive sample for 20 bit resolution inline float levelToDB(float level) { if (level This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #ifndef DJFILTERWIDGET_H #define DJFILTERWIDGET_H #include #include #include "filter.h" namespace Ui { class DjFilterWidget; } class DjFilterWidget : public QWidget { Q_OBJECT public: DjFilterWidget(QWidget *parent = 0); ~DjFilterWidget(); void setFilter(Filter *filter); Filter* filter(); void setID(QString value); void slideCloseWidget(bool open); void setAllGenres(QStringList &values); void setAllArtists(QStringList values); protected: void changeEvent(QEvent *event); void mousePressEvent(QMouseEvent* event); void keyPressEvent(QKeyEvent *e); Q_SIGNALS: void deleted(); private: Ui::DjFilterWidget* ui; QTimer* timer; struct DjFilterWidgetPrivate* p; private slots: void on_pushActivate_clicked(); void on_txtPath_textChanged(QString ); void on_cmbGenres_editTextChanged(QString ); void on_cmbArtists_editTextChanged(QString ); void on_sliFilterValue_valueChanged(int value); void slotSetFilter(); void onFilterStatusChanged(bool b); void onFilterCountChanged(); void onFilterUsageChanged(); void onFilterMaxUsageChanged(); void on_lbl1_linkActivated(const QString &link); void timerSlide_timeOut(); void on_pushClose_clicked(); }; #endif // DJFILTERWIDGET_H knowthelist-2.3.0/src/fancytabwidget.h0000775000175000017500000001332512423536022017032 0ustar mariomario/************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** Commercial Usage ** ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at http://qt.nokia.com/contact. ** **************************************************************************/ #ifndef FANCYTABWIDGET_H #define FANCYTABWIDGET_H #include #include #include #include #include #include //#include class QActionGroup; class QMenu; class QPainter; class QSignalMapper; class QStackedLayout; class QStatusBar; class QVBoxLayout; namespace Core { namespace Internal { class FancyTabProxyStyle : public QProxyStyle { Q_OBJECT public: void drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const; void polish(QWidget* widget); void polish(QApplication* app); void polish(QPalette& palette); protected: bool eventFilter(QObject* o, QEvent* e); }; class FancyTab : public QWidget{ Q_OBJECT Q_PROPERTY(float fader READ fader WRITE setFader) public: FancyTab(QWidget *tabbar); float fader() { return m_fader; } void setFader(float value); QSize sizeHint() const; void fadeIn(); void fadeOut(); QIcon icon; QString text; protected: void enterEvent(QEvent *); void leaveEvent(QEvent *); private: QPropertyAnimation animator; QWidget *tabbar; float m_fader; }; class FancyTabBar : public QWidget { Q_OBJECT public: FancyTabBar(QWidget *parent = 0); ~FancyTabBar(); void paintEvent(QPaintEvent *event); void paintTab(QPainter *painter, int tabIndex) const; void mousePressEvent(QMouseEvent *); bool validIndex(int index) const { return index >= 0 && index < m_tabs.count(); } QSize sizeHint() const; QSize minimumSizeHint() const; void addTab(const QIcon &icon, const QString &label); void addSpacer(int size = 40); void removeTab(int index) { FancyTab *tab = m_tabs.takeAt(index); delete tab; } void setCurrentIndex(int index); int currentIndex() const { return m_currentIndex; } void setTabToolTip(int index, const QString& toolTip); QString tabToolTip(int index) const; QIcon tabIcon(int index) const {return m_tabs.at(index)->icon; } QString tabText(int index) const { return m_tabs.at(index)->text; } int count() const {return m_tabs.count(); } QRect tabRect(int index) const; signals: void currentChanged(int); public slots: void emitCurrentIndex(); private: static const int m_rounding; static const int m_textPadding; int m_currentIndex; QList m_tabs; QTimer m_triggerTimer; QSize tabSizeHint(bool minimum = false) const; }; class FancyTabWidget : public QWidget { Q_OBJECT public: FancyTabWidget(QWidget* parent = 0); // Values are persisted - only add to the end enum Mode { Mode_None = 0, Mode_LargeSidebar = 1, Mode_SmallSidebar = 2, Mode_Tabs = 3, Mode_IconOnlyTabs = 4, Mode_PlainSidebar = 5, }; struct Item { Item(const QIcon& icon, const QString& label) : type_(Type_Tab), tab_label_(label), tab_icon_(icon), spacer_size_(0) {} Item(int size) : type_(Type_Spacer), spacer_size_(size) {} enum Type { Type_Tab, Type_Spacer, }; Type type_; QString tab_label_; QIcon tab_icon_; int spacer_size_; }; void AddTab(QWidget *tab, const QIcon &icon, const QString &label); void AddSpacer(int size = 40); void SetBackgroundPixmap(const QPixmap& pixmap); void AddBottomWidget(QWidget* widget); int current_index() const; Mode mode() const { return mode_; } public slots: void SetCurrentIndex(int index); void SetMode(Mode mode); void SetMode(int mode) { SetMode(Mode(mode)); } signals: void CurrentChanged(int index); void ModeChanged(FancyTabWidget::Mode mode); protected: void paintEvent(QPaintEvent *event); void contextMenuEvent(QContextMenuEvent* e); private slots: void ShowWidget(int index); private: void MakeTabBar(QTabBar::Shape shape, bool text, bool icons, bool fancy); void AddMenuItem(QSignalMapper* mapper, QActionGroup* group, const QString& text, Mode mode); Mode mode_; QList items_; QWidget* tab_bar_; QStackedLayout* stack_; QPixmap background_pixmap_; QWidget* side_widget_; QVBoxLayout* side_layout_; QVBoxLayout* top_layout_; bool use_background_; QMenu* menu_; //boost::scoped_ptr proxy_style_; QScopedPointer proxy_style_; }; } // namespace Internal } // namespace Core Q_DECLARE_METATYPE(QPropertyAnimation*); using Core::Internal::FancyTab; using Core::Internal::FancyTabBar; using Core::Internal::FancyTabWidget; #endif // FANCYTABWIDGET_H knowthelist-2.3.0/src/stylehelper.cpp0000775000175000017500000001740112423536022016731 0ustar mariomario/************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** Commercial Usage ** ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at http://qt.nokia.com/contact. ** **************************************************************************/ #include "stylehelper.h" #include #include #include #include #include #include #include #include // Clamps float color values within (0, 255) static int clamp(float x) { const int val = x > 255 ? 255 : static_cast(x); return val < 0 ? 0 : val; } namespace Utils { qreal StyleHelper::sidebarFontSize() { #if defined(Q_WS_MAC) return 10; #else return 7.5; #endif } QColor StyleHelper::panelTextColor(bool lightColored) { if (!lightColored) return Qt::white; else return Qt::black; } // Invalid by default, setBaseColor needs to be called at least once QColor StyleHelper::m_baseColor; QColor StyleHelper::m_requestedBaseColor; QColor StyleHelper::baseColor(bool lightColored) { if (!lightColored) return m_baseColor; else return m_baseColor.lighter(230); } QColor StyleHelper::highlightColor(bool lightColored) { QColor result = baseColor(lightColored); if (!lightColored) result.setHsv(result.hue(), clamp(result.saturation()), clamp(result.value() * 1.16)); else result.setHsv(result.hue(), clamp(result.saturation()), clamp(result.value() * 1.06)); return result; } QColor StyleHelper::shadowColor(bool lightColored) { QColor result = baseColor(lightColored); result.setHsv(result.hue(), clamp(result.saturation() * 1.1), clamp(result.value() * 0.70)); return result; } QColor StyleHelper::borderColor(bool lightColored) { QColor result = baseColor(lightColored); result.setHsv(result.hue(), result.saturation(), result.value() / 2); return result; } // We try to ensure that the actual color used are within // reasonalbe bounds while generating the actual baseColor // from the users request. void StyleHelper::setBaseColor(const QColor &newcolor) { m_requestedBaseColor = newcolor; QColor color; color.setHsv(newcolor.hue(), newcolor.saturation() * 0.7, 64 + newcolor.value() / 3); if (color.isValid() && color != m_baseColor) { m_baseColor = color; foreach (QWidget *w, QApplication::topLevelWidgets()) w->update(); } } static void verticalGradientHelper(QPainter *p, const QRect &spanRect, const QRect &rect, bool lightColored) { QColor highlight = StyleHelper::highlightColor(lightColored); QColor shadow = StyleHelper::shadowColor(lightColored); QLinearGradient grad(spanRect.topRight(), spanRect.topLeft()); grad.setColorAt(0, highlight.lighter(117)); grad.setColorAt(1, shadow.darker(109)); p->fillRect(rect, grad); QColor light(255, 255, 255, 80); p->setPen(light); p->drawLine(rect.topRight() - QPoint(1, 0), rect.bottomRight() - QPoint(1, 0)); QColor dark(0, 0, 0, 90); p->setPen(dark); p->drawLine(rect.topLeft(), rect.bottomLeft()); } void StyleHelper::verticalGradient(QPainter *painter, const QRect &spanRect, const QRect &clipRect, bool lightColored) { if (StyleHelper::usePixmapCache()) { QString key; QColor keyColor = baseColor(lightColored); key.sprintf("mh_vertical %d %d %d %d %d", spanRect.width(), spanRect.height(), clipRect.width(), clipRect.height(), keyColor.rgb());; QPixmap pixmap; if (!QPixmapCache::find(key, pixmap)) { pixmap = QPixmap(clipRect.size()); QPainter p(&pixmap); QRect rect(0, 0, clipRect.width(), clipRect.height()); verticalGradientHelper(&p, spanRect, rect, lightColored); p.end(); QPixmapCache::insert(key, pixmap); } painter->drawPixmap(clipRect.topLeft(), pixmap); } else { verticalGradientHelper(painter, spanRect, clipRect, lightColored); } } // Draws a cached pixmap with shadow void StyleHelper::drawIconWithShadow(const QIcon &icon, const QRect &rect, QPainter *p, QIcon::Mode iconMode, int radius, const QColor &color, const QPoint &offset) { QPixmap cache; QString pixmapName = QString("icon %0 %1 %2").arg(icon.cacheKey()).arg(iconMode).arg(rect.height()); if (!QPixmapCache::find(pixmapName, cache)) { QPixmap px = icon.pixmap(rect.size()); cache = QPixmap(px.size() + QSize(radius * 2, radius * 2)); cache.fill(Qt::transparent); QPainter cachePainter(&cache); if (iconMode == QIcon::Disabled) { QImage im = px.toImage().convertToFormat(QImage::Format_ARGB32); for (int y=0; ydrawPixmap(targetRect.topLeft() - offset, cache); } } // namespace Utils knowthelist-2.3.0/src/vumeter.cpp0000775000175000017500000001455212423536022016064 0ustar mariomario/* Copyright (C) 2005-2011 Mario Stephan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #include "vumeter.h" #include #include #include VUMeter::VUMeter(QWidget *parent) : QWidget(parent) { setOrientation( Qt::Vertical ); BackgroundColor.setRgb ( 40,40,40 ); LevelColorNormal.setRgb ( 0,200,0 ); LevelColorHigh.setRgb ( 200,0,0 ); LevelColorOff.setRgb(80,120,120); QPalette pal = palette(); pal.setColor(QPalette::Window, BackgroundColor); setPalette(pal); valueLeft= valueRight = 0; peakLeft = peakRight = 0; m = 1; sh = 1; space = 1; step = sh + space; secStep = 2; pStep = 2; ph = 4; colBack = QColor(60, 60, 60); colValue = Qt::white; } VUMeter::~VUMeter() { } void VUMeter:: setOrientation( Qt::Orientation o) { orient = o; } void VUMeter::reset() { peakLeft = peakRight = 0; valueLeft = valueRight = 0; update(); } void VUMeter::resizeEvent( QResizeEvent* e ) { Q_UNUSED(e); w = (orientation() == Qt::Vertical) ? width() : height(); sw = ((w - 3*m)/2); h = (((orientation() == Qt::Vertical) ? height() : width() ) / (sh + step)) * (sh + step) +m ; //QWidget::resizeEvent( e ); //repaint(); } void VUMeter::checkPeakTime() { if ( peakTime.elapsed() >= 1000 ) { peakLeft = 0; peakRight = 0; peakTime.restart(); update(); } } void VUMeter::setValueLeft ( float f ) { float fl = 1.0f + levelToDB( f )/120; if (fl<0.f) fl= 0.f; if ( fl > peakLeft ) { peakLeft = fl; peakTime.start(); } if (valueLeft != fl){ valueLeft = fl; if (valueLeft==0) peakLeft=0; update(); checkPeakTime(); } } void VUMeter::setPercentage( float f ) { //qDebug() << "Level: "<< f; valueRight = valueLeft = f ; update(); } void VUMeter::setValueRight ( float f ) { float fr = 1.0f + levelToDB( f )/120; if (fr<0.f) fr= 0.f; if ( fr > peakRight ) { peakRight = fr; peakTime.start(); } if (valueRight != fr ){ valueRight = fr ; if (valueRight==0) peakRight=0; update(); checkPeakTime(); } } void VUMeter::setLinesPerSegment( int i ){ sh = i; step = sh + space; } void VUMeter::setSpacesBetweenSegments( int i ) { space = i; step = sh + space; } void VUMeter::setSpacesInSegments( int i ) { secStep = i-1; if ( secStep<1 ) secStep=1; } void VUMeter::setLinesPerPeak( int i ){ ph = i; } void VUMeter::setSpacesInPeak( int i ) { pStep = i-1; if ( pStep<1 ) pStep=1; } void VUMeter::setMargin( int i ){ m = i; } void VUMeter::paintEvent(QPaintEvent *) { drawMeter(); QStyleOption opt; opt.init(this); QPainter p(this); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); } void VUMeter::paintBorder() { QPainter painter(this); painter.setWindow(0, 0, 100, 540); painter.setRenderHint(QPainter::Antialiasing); QColor light = Qt::white; QColor dark = colBack.darker(140); painter.setPen(QPen(colBack, 3, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); QLinearGradient linGrad(5, 250, 10, 250); linGrad.setColorAt(0, light); linGrad.setColorAt(1, colBack); linGrad.setSpread(QGradient::PadSpread); painter.setBrush(linGrad); QRectF border(5, 5, 90, 530); painter.drawRoundRect(border, 30, 5); QLinearGradient linGrad1(85, 250, 95, 250); linGrad1.setColorAt(0, colBack); linGrad1.setColorAt(1, dark); linGrad1.setSpread(QGradient::PadSpread); painter.setBrush(linGrad1); QRectF border1(20, 5, 75, 530); painter.drawRoundRect(border1, 30, 5); // paint label painter.setPen(QPen(colValue, 2)); QRectF Left(20, 505, 25, 20); QRectF Right(55, 505, 25, 20); QFont valFont("Arial", 12, QFont::Bold); painter.setFont(valFont); painter.drawText(Left, Qt::AlignCenter, "L"); painter.drawText(Right, Qt::AlignCenter, "R"); } void VUMeter::drawMeter() { QPainter painter(this); int value = 0; int peak = 0; int x1, x2; for ( int i=1;i<3;i++ ) { //Left value if ( i==1 ) { value = (int)(h/step * valueLeft)*step; peak = (int)(h/step * peakLeft)*step; x1 = m; x2 = m + sw; } //Right value else { value = (int)(h/step * valueRight)*step; peak = (int)(h/step * peakRight)*step; x1 = w - m - sw; x2 = w - m; } for( int sec=0; sec < h+m; sec+=step ){ if ( sec < value && (sec <= .75*h) ) painter.setPen ( LevelColorNormal ); else if ( sec < value && (sec > .75 * h) ) painter.setPen ( LevelColorHigh ); else painter.setPen ( LevelColorOff ); if ( orientation() == Qt::Vertical ) for ( int led=0; led= .75*h ) painter.setPen ( LevelColorHigh ); else painter.setPen ( LevelColorNormal ); if ( orientation() == Qt::Vertical ){ for (int led=0; ledasBIT|dIDATx]Mܶ~$&l8؅CKE{@{riSr@.>Ndg%ՃJCI$_JH/J89^R$vLΘ}Z/ph(ooEޞZ 6I汍2fyFٖ~ڠ4,p~l\K={[y2gggeYիW-@IPci;,[C('?'k9*>75h0)@N9SbC=U8%c,~ᇿ7ul iիW3E5UFr#Ao]Im|__EQӧ3q`i.\FbasdYf-MTd"N9]0Le˥8`?{0 }m I~}ߋ2,Q It6*:6~lT$dmeDj\.ch##6yլk}׎/b/r ME\U|WPTt҆$I0/#tysBN{ 8G/TzP j$ @9G;P&t֭wu6%cf+yrCcH$o$r`KY:b]Cc!Խm 鮆/ H$Ku58AASB6AS2x4JuA$ٟI#! '"BȐ46\sr}"/ 9Iij4e1C# *;prB2i}0Pӱm@}6p^@!ЮrTLP@[#}7FCkT!s/ @XFSW__H) Jµ6wI H$:=eP?t,k|i QSP9Vn`sG0̮&0j(xM60W^։l`B޸PBZp@L#UT$]BP52s 4Zv& 9 hn`:tɴD}^b|#5OWא=S]OfԮ~ 5~n6kOdm zJLf!Hʇ|7$OT Rh'Pn9F0yH-0| sc$7PG۵ʷ}5&_P0|=l-oi"`6o :2 fqv Pktgad} !N ľ 꼋t;v:]!1q4@eh#^&CSmGٟ)fY1E"c z1J01\Jͮ"2L J}gwߟ/\nhm1vLPWiȥ15Й m@a J nO/:}w) +kkdjx4ޥNLL @x*RnVygxw+\U46 ` {.Ww C3ȥ^ue(q>!jo\ Z P>n! GɘP}N|=~chf CC 1:l@owh|&X~BL1>ȕĶ!V V"PLmk&\TK7vj74{6 pQf !ƗC : BZ$P]_NF>ĺLsd"%@0jhJ"@!_0j}ȱRߕ|9H!P*G0z$ڠOs."k`sw!t{1J>9Vo Fk}L"ks^ߊ" /+29& yuGЬ d\EC^c v13@)dom6-$e:5ģGc&gl)}}Z|W*Ռ\78HAuB ^ֶy[f[s:|.$6 v00c`8'Rrr)0%!:bYgmq Upe7W흞rן[pKvy!P2wp&1+ph^̉&M3Iޞ|cʨɡ`) &mTY<>qxxA5eH ) f[峊UɈo"W7ό~ lue\s|0V}fyQP`o^'''{" %_"(x+,gyH'O Aƃn >+PNzpWsE~K.Yxp4@[ (Lt| `pN%ڽ+;\EN556||;w<%3(6@(Ceto'ų"1dW_'p<n>2U7*N$eH w 5sX,_CEYsiC yshD~?3EY5yh|9֚Ҁ4mPz\_{믿1ׯڵk_x&Go)w&ؒ/.ƤP>駟bvxFMLY2BMUE_u/x^&-~T1qjG>JH~,N# >4g}X,Z-! _9(k+`lN&s>}?Vнw6w&*/P2\u'?2E7n/ÇO??k|XB>\v$,䫬*c | nܸ{!Iqڵu z$roeܼ7Hz}< x^ GQ%)81B w[9< qttbcooݹs/C~C nd$~)B*C׎4eYl?Wggg~=qhkwc\.~.Fx@+OW\$K!J7IRQNg!P@[-RCY;.T<!^Gw.ϫTj7?\SS} \',ϰ&1 :z٠^^1:gSf)o9qsLdE*IENDB`knowthelist-2.3.0/images/backward.png0000664000175000017500000000022712423536022016622 0ustar mariomarioPNG  IHDRN'^IDAT(K @!Ќ!qKd!Rdtf(d@|g)y a|jT׳3HIENDB`knowthelist-2.3.0/images/volume.png0000664000175000017500000001044512423536022016356 0ustar mariomarioPNG  IHDR@@iqIDATx[pU]$zA(!͘I$L쀝8xR&xpe\bg' p0n BP/Hל_!>"g}}ݳ{>;7|8 zH TB\s#0Z&x88cprrr q$nH': HҞ@\FFO;H3R9V9;;7vc\@@'`38(>3#z^V Ʌy{s !k$$(zÇrMz;;; HKK444cd755ߏyqJݡ8f:L_8bĈaÆ t>RZ[[Kccʓ.\x@w*RñXB(&00p4,*(V$88X%$$DA Zϟ?3{{[/~*XLw_ VBo???۫T@T#<<=imYI&Ɍ3C痗;w.;~^9d@(]U;|Zyȑ.aa/O/qO2zxTWHEEȂ Yٳg+o$~bK=3C{NT>q℔JxD$'Ș1j}*qZ{z{4A %??_Ν=YFsKJJ5Uas !~, Ddv, ;3In}ޓ8.QݘӪT(HnÀ ]]Pe0Z[N.ɂ0Ze?(`K`5Q@@D߷ozvرR]S-uuu$4$TC%!@=5M $@uR֩ĮiimO>Q3g̜9SΜ9{ D"ֳ `V_A;J#hPPc PZ ^^2k,*˨Q1OSa*ϼX EgJ%&SNŋ%>>^7''g#< ɢ2:,9mX=<97Ill~TdJq4J[x CW){y~@/hPb?ӗQ$qOZ= r,M2}t:m.(**JIBb*7JP  /Jj!WڵKZ["ɓ{@xn~a`C!`!Ia񒚖ESܔ)jyS̵p`Qs%8p@\PXoYgQO@auJKJ5 E¬ \ gL$t});2׭[WO܂   y822>*OؿDEGɢEǍ')SSd8R7ʛQ"k׮B M{=4s/I}TbҥsΓI}+>s&AAA#%pdpaCyR")dHwfe˖=g/  L[j |>(wb8q܁t*m ͪ|RRVǚ[^@ ?wҗ@I/qԣtMMMU]ny򰺆]aa+o>ٷgxzxip $UUPP͌?_M(I L&xN?%)vn'`"ť 'F"xe~tmggTX$Np<Ƽ.eeJnne;X\<1oHVdHHC 7\L^ɕKKԨֶUyŗ]"T*F%KW&o=oߎ6JYLo`;> K2[`BA'?~x n1 AgvP+  t*x4񁻒;7dC**+$vLdffGXB$ aXLq. texTde+C#nP!a`h}^v;,Xp7H!?|c6֗u% 3>X#Aq!<ΛAaADqcCŬ@ N)x*JS֡,9vvGg$ox:@g4]`@:zجFO [=> *j+#NΒg_1>5 9˝APlp2 ?~\'M-O h]^Sl#Ne.`;zntxB5pF_}Wy"+)ò,}7d^`CD#K0^ \4 "WHi}r [7O$T ?󜑀7p9ۡ|q%xB>XoCJeh] - KZ.*c^qֶV+d!C=ɤP؄x|^_ 6&BRfBy0d2V}uc2bg475rc9\&l¼mbk_σSi#TJd~ F`tˌ @^%Fy [{  _3B!3(P&Rgmx\bzZ9d/\~]2H{)oJ3c|/txn?96.׉?▣v)k_Eq48H\/KBj|1S!$9/op|Xl _WeV3p'n Kj/{?e 5#|#;ȯG 6%7 o ^Po ?_IENDB`knowthelist-2.3.0/images/stop.png0000664000175000017500000000013612423536022016030 0ustar mariomarioPNG  IHDRN'%IDAT(c@`Pxfd````"QC_!# GCIENDB`knowthelist-2.3.0/images/search.png0000664000175000017500000000347512423536022016321 0ustar mariomarioPNG  IHDR@@iqtEXtSoftwareAdobe ImageReadyqe<hiTXtXML:com.adobe.xmp 5}jkIDATx[gQ>Y e|aB #T }O!C٧'Q:㦓l2Q6fdsd|o }s{{(!YF.!E -Mv:g0أE w0i`i:0Iv'|HfOr@6d:rShw&<< s7Tc}A>57}t>4b"XD@YҌљe}}EV\z{׷6u@ZGio+l]AΘ9]Fk̗`5XgaR_2{mQgΜ~c|N5G/l3:XP}AN֐KG&'=I$ ;NuLTm #( d, j$̖%3À٢d1w!  2d5y?u@LXLՀ(LGS3@f˩Ƕ9Y#[3Ȇ.H-tDtW1M;&{Jl n9 bؖś^Z9ڝ8#mvʽ9 MeXT.G[ּJ;d{`u ցwE}͈1ߚh0Dfj8]>Y%27-EΩ2ِ2Y Q&eE [d"G9B!u.bb"ܠ|'Cfi,FSKSoRע.]v"Œ}~9̓wzqaa*D!";TEXD ̺Lč[w(7y&sIENDB`knowthelist-2.3.0/images/pause.png0000664000175000017500000000014112423536022016154 0ustar mariomarioPNG  IHDR'Ն(IDAT(c@`"R Y` Un3bSQ#G!#S8Y's<=>;ccc01/$%$   !"!"""''&/0.111231777:::=>;???AAAAB?DECEEEGGGJJJJKHKKKMNKNNNNOMPPPSSSTTTVVUVWTXYVYYY[[[ddcdfbfhdhhhjjjjkgqqquuuyyyzzzuJtRNS..??TTee IDATm۶mv[{#=@5. SbA7}`+3bRo\Uy5Ltx<[!b GB$SS Xmt=t:q);,#*F/ԛ6j Mh \r+/IENDB`knowthelist-2.3.0/images/licenses.txt0000664000175000017500000000273412423536022016711 0ustar mariomarioheadset.icns + headset.ico + knowthelist.png --------------------------------------- Icon Author: Iconshock - Icon Sets HomePage: http://www.iconshock.com License: Commercial usage: Not allowed clear_left.png + database.png + settings.png + volume.png + slider.png ------------------------------------------ Artist: Oxygen Team Iconset: Oxygen Icons License: GNU Lesser General Public License folder.png ------------------------------------------ License: Free for commercial use By: Media Design - http://mediadesign.deviantart.com Icon set: Hydro Pro vinyl.png ------------------------------------------ Artist: Nando Design Studio Iconset: Be the DJ Icons License: Free for personal desktop use only. Commercial usage: Not allowe DJ.png ------------------------------------------ Artist: TurboMilk Iconset: Gadgets Icons License: Free for non-commercial use. Commercial usage: Not allowed search.png ------------------------------------------ Icon Pack:Batch Designer:adamwhitcroft.com License:Freeware shuffle.png ------------------------------------------ Icon Pack:The Clean Desk Designer:Alfred Pereira License:Freeware list.png ------------------------------------------ Symbolpaket:Human-O2 Designer:schollidesign Lizenz:GNU/GPL play.png + pause.png + backward.png + forward.png + stop.png ------------------------------------------ Designer:mstephan Lizenz:GNU/GPL down.png ------------------------------------------ Designer:Qing Li Lizenz:Creative Commons http://ijungle.net/knowthelist-2.3.0/images/forward.png0000664000175000017500000000023212423536022016504 0ustar mariomarioPNG  IHDRN'aIDAT( P0.dƑO )vW. @,xAtK(2HSjFo1nh\IENDB`knowthelist-2.3.0/images/folder.png0000775000175000017500000004624512423536022016334 0ustar mariomarioPNG  IHDR>a pHYs  ~ IDATx fU^:ݳ{fgd, A1V0 C !IHQB"@ QHc=[{UW׾|k}{mcVrs{_Qv9p9p9p9p9p9p8Pj¾vTǗ3Ojz_o, SOO,-5;ν[,+ܹ^¯h4^?00gnRy]gTI)(|\S3 rTGţ}Eޢf)ZZqtOjczx>U]hmZ!H! >; s|JEZBAyBGFFPjܗJjЏ}^~[6Q>6($bv~_(Nݞm;nq[/N֊Ѿݢ{=}pGc#iH?"aLU2jorp U%b&mTF)kCvfqqqjǎJ .+%QG~XœozxWccEOQ` Zm],H bvn5;RT4$N8/8QI N˱к*t+rdakE*߂ʙQ"[*5y{Y+#E_CCcwU<,bA-72:RHXPZѧViJ] F7bZ,/IAXY]sRE) ʱ\,-/# ga')+BH$hMXhSs/hAbx??-[ݻؾm[Ue+凘K+w| ڃ5gwN--`K33l+$sjz8wB~FUq۷[9I)k?c gT+(F[WSFF[؏646hHFk^̬/GZ~m_qޭ\90522VOoht{Hb?+ܧ9nUTbbBU /oBnh界-iY-"*QH.PAGPl淨%N\#4w. 'Č%;^cUqffcI)$1=91Udž[1HFSUpgJ~;F5@L_wkz`ɷ4/ͬ`Qr+"nn`` FD.Ե:<}+DV[4>?[2J?O}2 }pTwVB\IؓPE qI1SYRٴHf\5kiB}{*[enQK˱ڈbXA$"fZZVDݾ4G=n)gZoy6lC fR( y20A9P&%~ f K=`fWcw*7n~hܾ[+_Ņ \jU6o{2'T?bXywdpMi09Z_ض}-?xBBq9NeS|k"q:xrf1lԵ"E Ҭ22u  <|Hk[,UK hT=0B_\(N9k % +v)X,i)D?+fBoZlޥFbFDmm4b^9H,3>.RRgCA FRRtDwk%W0G&??cyh6VW$dc`#kZ] Jarbqϝ-8%bLCl=^N g( ],ĩS'ZW۾](^qų/ԿI Vļ4Y+M #a*M;A=Je>*:)FR.=gqY`TUH[g\&Nx]S SYF1;bX-&Pςjg%% 0_G'?t?bߞsGO{kY-2c徉*Rvggnb‰Uk+L#4VuWl5~#[^ʑț.>v1~Et `zqJ %Bi%Y33~QAOSW(( `ӬS*"͂ "@dr1V5/0FLѪB䶷?mYş2,i30:X2 >Y1YTbdKDUPN:S/+9yk~ :LoI 4XŤa#)'Lh> ̞t_9KVBb`N0(熉Ofg*L_9tʲLDj*NJ˂דA;Z %^k,iT &+-)Uɾ) F9tc$AlG .wjd{. Z`;}gV ȴg5.p&OPPv%QM8E K.*i,B9bPxe%!'MWF^q@M_迓]Ak5*}YƠ 1)gT['r9<`c'%9Lt9G̯92,澖*hPuѽ1d5֭G΀d{f@ dOJ'-@XĪh\tX4y8 gmW~DAuN A>z 8̰D%0fVXZ]m*_om ]6Qb:XSL?%*K%SzO~,v|E Û!4TS`:X[Q* "aBa0؄ H7#XeE^Rr妑VbE\.;n"UwSiܩVAu$Z%2Q4, 7П!Qe\̈Hb '`.z6YxYd,\kJ*@*4imBW%(/#id)x!, lT I_1Sʕ06D-d2e 1.3f%%wA_T056>8´'Cs.OZ WJ7s -U&_0PU;Q>؀1]E1Df4@:T^NU@UIP:[(VG%i((A ([dHRXf0HhkٻTP?#aQTo.6ʘ`IKX1_?*+5N,;. ~}/- [YkJE$Gٽ.p2=pDF)x!5 vujG rlo)b(I"dzQwR @c`TCs  KpE,U JhXxYT2`xG^l (\hSGΔ _`/:x*St0iiLY`ud .s-HCp5+CdI~]bq ޤi wsh~}ϠM{5"ژZ3Y@I)Jp'da:/ PV&eW*NqnbyA"ll bQ,F-O\J'TjH~( Gl":)A'!w`8: \_% D# gPNd ,w?}B']^k^ټ,kF<ү׹=t]۵c)f;uM)ǚON@굕ѧg5]di7mİA,1R v'X`m^U$y2M9pN*.]Αڪ "c? У΅0ٛh9ִ&4mp@rjZen{jwkݞ:spϺƋѻwouסΥ5􁆮޷ NrmѨeHV̒ `Qla-rJP[&#AxXb@ܥSlLɼ,"1;\S#"`Ume25K'Y#GX xJ֌me(Xf !BS(Ђ 7x*)$nN#GX6y y4둣G_.vrBm߾}Ç(>|8tNVc3ۧ^zVwU.7Q2%E}E;jNW{s ^L qAQ_?I):Y ۠h$:֥֊!y?zlA<-89e S|p *"Q>)W5JI$*(:ʡ@\0T04O%J.N^>bR7]fq|n~ƥȁ"LgL./8+ҢW}A\ /[ ZO8}BqL/,PK`8I_8iݟ-ZD,L/KXF!x|GO.زm)aJA>6oT9D`@AsApFGUU}Db]ԝ5Wa Xx{8_~7`F$X_eEV]ιFk/n.SZ Hۖb& Q"S8 8<(XÇIv0Wh]m+Դ:]@/hJQxK|`a\]ca\+2qMf!G)h|,b^sKL4uE0zXYt3ďCޯOԱͭRu;~m0nL"gJHœe Bk#<` I8O?^Cz4u&I^ӳu[ P*otT4{50qIU&dGCb6YҪ=fU^XAD3]e n(S]3A@tSS56BxY*9bAy)D(Ŭ6^أinT*9x )k)#K e6堈|@eM\F P4fN>œK["Hc3Hql-k*()1 Pʉ#Vwkyr'Sߵ ) e`$pzZ'Oۢ`7'xMl')xc6F5 bBesL,bbiZaeNA(S3:*ޕQILJE0xE3}c˼*jc帊0߳% o9"8: Yy9DZ?/vY3ڮUC+0H<++ZhYL|6Z BDPR/Ѕ&]ǢOM U+b J&hɸB~f&o-\RzDR@s?/jCcÏNfyޖ#UCVQe+=)LG| 8p(<; t}sll|XVVOt˫M&ua$̍Bn]@4iZPI||0 p3yPtR*%k/ @4y*Xzc1HSb:R(nV%Aqdge)^ԗ5W!K(nA( Y۬Wylb10c|@BSRu!˚u,h}u[ f$65)nSx7H #ٴc :;vsFhP?|Y@bBW۴>0`{9<T[ HkTq(Hc [ÄP9$ߺ2,FeZcNM_VMqǑ/ꑔ/q|5,ڲNRfx%7;~WYX N~}eh|`8 Rm=}J, 垡Ef3/K#O?^ /q o*r=wy0(Z2_ZxM_cӱQed0!| FLNl_q(pPh*8TcM&\[OMoC WU+FyLv7t^S_qneD꧉T3- B13$dOJ|/lᬔPn**xK Ytb)h|VGYZS[ꏿQ/џ}饠#Y HO&n#h>wܘ}gzvtt!%h'7Z0D%8PـiX㤘23*F_)Tt@)aF'\ ĹJ JEdGuJ%^&b?C;.w@k"[uT}m}ld1+v]NjG^u}uGʤ63մ7=z01Mվ4n.,Z>%Sr(̔OA0o4>Z&fڔH_݈'dhrx#! b-ΓC!mMu7K˼`y/̸mUv\[ۤz:[m21'9}WO71w!gCU "ׇENj/+8`AIA7ؓόSs%jWvdp@㰑 3OIIz*֭kׯV5L*W_lh)n-EOcrQ>ؘw+\0RL XFLSAnS*=,LQH,c ި??)?SԾx@<8Oe ke$@>,R㊛@QWoןԫ-`YYю-96N#h<HLeo@!%S}ع{ TsBG^-)\KX> VOZUң\yCJf =*+RV*.6Ӓy*9]vd#%mO1h<+%=piVfF:Ή>k~6zlӟ"3d¥םv]S<"8#Ό#s׺ΜUkvfiX|ۚ7xuvIFH|u}x @ҥ`@<Ȓ?TIv."PnH/P墬(IKI)(4>ia6!iJO2eK@v  t^OpzE^lM/gF"!\⩯`wM E`t^^SH&o/DbVXpL+ /wN R0/tg\{sE<֡&yk[lq薟0bɴ:BuD\C0' TWTyCCB@"L@!L?!wbAvܥWWKZئ5rCb!̳@txf7,LE4 H ȗszOI'zEE7Q+xzPpR`xcmNqu] /` CU!8xt_MWlE)2+-ݪdgٱ#h7$}ix-LpG{$m 8>j()BP?=5O݃>x+*0ג9Vl!ZVj_*DBȘy~(p8GxMz/s$|(*1TM45!;pR/ƒ/wlOu4ګ>Sj]X\^/k/UZ# N g{+2,ALb9嫩J82WIOY°U16'ٳe!TQ A)awwdWQz7XF&*3 " OJ1()@Gx%})F.3Ki65$U`jvvR6z6 tsEM<-6mcwguSyi=e1pʦha)@3R/h9Urh!|%wk€VKAvP7HoDL$Jf.ZE&P :Pc:ru#&(c2[Kt ~s` pR'JYmL5j%]V6GGki"FjU~̣|1ٕ,xřg;\SkپC?2FSJ;x3Ƹ q!%@_vN-Jy-&Q:%0`65eZze8;ܵ6CMnЛ lG޴9@=R2k=ŋ/6|9 J$QeW?zA ) §!WO 1 B}PD"G&sR4x)GJ*?3l p|)dN@Yy1rGG}%NF2t_齺:w3 OI.U[gEk"1]N/ջ'"+///Қ~Җ =GJUZqP>x{f|av/! 8izz=b$űjYuc &u!@'ׯ!+'o/Bx,%28ǑN4dP~9]GXHb71PGvJ r(v5l[$]]Sp<>^s x-mϕ¨t`= 2ZO7d%>9nM+ة)VMfլ'%LR[30=9fF#:ad/HG^s~F4aB$=@goP'~֟l#ހ,k. $}k╠Mk*q ӯ׍uȱGn&"، e"GyI#T%CxH`R>!:w攖Z6!)"|"TtV`gD;)I jr +wMdfiAH#iVG1WZTktvGDC"\vMX^]:~My'__ad q^jWʬ ײy,&/h1pj0JűGtkПya!v;yY!~A!LpJ/ˑJ66C("qV2^GW.7 u, xS@/-׫Kxgv UE8樥ڙۉ wfՂrb%S9,an-B+ ^K*X5"ʎLdLAyOf5ZX07n0ht(K8F(ACn rR/`YlL՗.3bk`=z_;=2<֢&1dQQScZ {U5{ ި 4Ӻuih/ aحCE(!JdP79+)TJ˛<[o -%lpRh{ (:QOIrzfS1Q6}n(Rv˩^BcGE3)NlI z\SErabb HշX G0%QRX}TL\s%=F.4/pxr,#(GY2|!!TKƩ ;֜l&Ȓ2:dl_xr4HB[sRJˈ1̜ 4:Rv;&fʹgRԦQf_/&iC+@Ij 0VAr!C':Sج-7+OdXol\I+Yľ =))E¯NԃCKPIp=is5 AkMbOXO=HFJ $]Z҇mFX 8~יzIMS&٬ p,&R81"<. fr@[Y-gkJcbFr܍(y;/JcppQ~wQK|Od\6O{/[\aX KXZXR%mD+PQJ'aJɴ)*VIw%_:yAըݮ RQ 1]W^4%Wq74ߍ*@B pkaSo#&~g[Y@gVk/5ae^x "QFR$ؤ6U.?eOVRNwUy?V遮}`^A`ʴrLQVw(,%(ߢY+Uב̋2/2#3a]R "D>s6J$GXk Ӂϊ0艤( `^|*=b#:eoIry ^҅a9YAJ֔4ґ&]tWb104@Qb]UaGi2a|H{Sq"([KX˼{\A 6A'Q/ӒJɋ: bdb;u3/S;_&_[w.x&\`!N[i!<)JC Z9XrkI$Q /Y>uZBIK^pGMGܘ NfR%y4d1)mVP\O wu;ש>ėa}쏼gv I)"Dx"lpW&''ec1C **xzm+@ڌk|^WGܩ+Joߦk^yJLV9bJ2:o6섅HηA( *gY| n^1 aդpQW$X9to__ bo˰F%kah"RxBjRv)Q(S:׋+ %B)(qC@o }OqEMY2uzx ?"muFBP.)% SEi+_xy;~HZ׾96/(I@f jJn^?QWſuXqI},E~ K7 Kb"\ߎtZrNyYY3_Z\7 kRE?e i'4C։K(ܳNI)nIwBym><1!qK|[5{8ֿd'Z[5Ka  Ni6V4`Z?l?YO n+@č=$hAd7HRopj E)pIѠCC/ּrurpm~v~Ut\zAG% "ma3x 2xi~JCe)XwxiPRd'Z GQew[_)t zH[$'_+^]rOЇ/~VQ]tuŨImw9p9p71f)/"IENDB`knowthelist-2.3.0/images/down.png0000664000175000017500000000031312423536022016007 0ustar mariomarioPNG  IHDRasBIT|d pHYs  mIDAT8= `G! x:jc,>'ҷݙq" .Kt.Ĩf"NBd\+yaHFd{G4=IENDB`knowthelist-2.3.0/images/shuffle.png0000664000175000017500000000306112423536022016477 0ustar mariomarioPNG  IHDR((mIDATXmhSWIijI_ֶ /(V7)qpPtlL0\c2*(*A'ۊmYUKVil%{s{{Ͼnin~Ηsd.cY{G*~\t ÇdY>eZN={`ӦMp\UUJ`4qXUճ~bb"r/\N@Z8 @!G)p8kkk#L"ɠ>JTyyɭ~NLD~yRJuS@!$$Iv:ƍ( 4( $I򗔔+Wlb_OLDH.'@S2e۷ofC"! uFQ?T!6J]!@ٛS; ˲o,Acc#A@:F$%)xE| drIENDB`knowthelist-2.3.0/images/play.png0000664000175000017500000000022512423536022016007 0ustar mariomarioPNG  IHDR'Ն\IDAT(һ 0*?) 1p5H i1'o\,sf덉8&F)QO0F Q\.F,IENDB`knowthelist-2.3.0/images/knowthelist.png0000664000175000017500000003533212423536022017424 0ustar mariomarioPNG  IHDR>a:IDATx]|+!$$zM:қ ('D"M)TQP@Z轇${f/~rN}j_zIK%ӿxdrwOttW>$]pb ,gF/ 8Y!..Nrrr [2755UL899\]]FnDDϗ#^N(RH"Cnݺŋo nX[2,2V KIIy 1ߞ|~xNT)<~)x<5ľjժ]sthظqOڵ)( >O>-i*'O܍o AA RΝ;%CBBj!hj5[pЦҥKXBtgnnnP"dWEivGHǐ&ND/3ǀB(Wq9۷,tҥ2njfdOnGtB -*޸qAȴccc 1p¤ %]| Ő1eQb"~ 5B n?m4o޼>Ç}:}&><<<}TL[nmK#(E]O-,'@邃ܾ}Fm|B9A mhѢܶ~p8C`ƽAI@+5i 2(J di;իW?ݻ̹vy<0ɓtBu{VY}ibrsӧ{v"WX12oŠ\C7!CC髋K.]zy78@b^<<ѣ!o_~%y+"6xy/ AQOÏ;wD)4gŋ (A*ThĠAS AmSڵkExV R 3ӧϭ\>;g7j#G ;r w}xo`}UV3fZav:t1G4"(\QFWB .e:>1{lJD$D[O0$k7ptlzƠ󡡡1ݝ,[|C GYn'\masfn޼yRݺun JVAܚw'sr]vzE,v OF?рSwšDcFӓ䔘ի]zc#bBt7ng5/_ ͨM6t}ʔ\C_Y =H`'c5`ΝUA7C7svv:d26`y0T Gy{^*UcmaÆ?B=df͛7'Zlo̚5k9ݻOް'^hvK֭{g߾}{/;NTuqqo2UwҺdfȑ0=FP\`~n\.`K{~~~~WѷCBBbTETpq_Q=vD;مuZd?55.cqۇJ- KHHLCfBN>=rɒ%;2J*upQϽѣG/A/'z>mLMMqΝ.G8 :Y2yܸ0/v'羱3@{ի/I&M+XDfhrg}6r6lYڵ-Ȝ8cw޽{b dɒ=zǾ}Zׯ_{(oQJ K^D`0Ea 4˖)z3r/^$::wN:5CPlll9sj"2{)[tС3'N޼y.)8P+22޽{h0C&dG6? [h: WT$}rұ30=~B,|UٲegԩSءCʕk ߻woM6C]D7nXvϓIyITϞ=aLA?zP߿ǏDZ ;HRm??%5k@o__^juڪzM&qpm &˳(S6ϧk?m鴓W̛`zٲeb ꫯlF;okjΡ٫t($I甲@^/2*U$/_-11IU>>޽;txflx"+pwңߠ[eD=Bŕ33 8x43I"$7NcMƳj$ DqtQW7!q嗣3gΌE:2;Fp9iHeB$F9$jhk"WwD,-\ŋg;vv34{0:u_X{)K4jԨ8QbQFUB_jhh+VTgݺ5Sj=cؽ(u12W5wyIǫLW<]]]L.\2`&?>}zzO?tObbbC%ДzB^*/^T!55<>,OhѻO4xA鏃+c+Gnu" '_A :|gϞ ?P B3p ,,?BvŜ9_Dy04v®c?FC^ wSjsk 46n85k0$nݺj gjo0D,7n܇nDN~A鸽עB7,;8qb3tI_^ CpG_I/ 雲;%`89o^)Vz~,"Hnnnpe`4fa(]ޖ-[~ptەS& I!&M^F[wTƳ\ETrd8PCCˈaN&%%E]MG9ӳ})S6;J{R:鞛t1$&$KH0LGs܎6F0ԩSϞ=B5T #NvwЩ%S>[ *:>}zb޼y'˹xq'4/*0~Xz/gэx^;P 5h(…  p.iȏ>b\\\Њ+:"O( [@ӷ5k+;vl'`Tn%_ɓ'bbb.~W봱c~ xaFU0f̘6fw^k9g?݈۶}un%ƍ9/^i-~a P~1]ѐR)켾`L&M6jWdE?iSN#<}Yw=00Qxx˗/stۘT0r7QT3f8ܠA:EjaGUi6֤J j4A㷠< mݺ]m5'QhHNIAmpݺuN:svrt,ϩ尡C[!l.B)Pl1ѣE=*M2XKROET#j\N%''\p 7F7o"QbŞ㩭 J@Mpl̙'O< >Rؿn*`4R1%%&j%[G/_zg)Yuhh a aai!&:XdBFEE7o^?GH})~M;)ܼu#%*oٲ%hX%D 1]ǏY3YZfLOTL gR-%|VG?Aڂ>}OMI=^l>-zu hR۶m+.YUJfO}ԩS{9YsHV#l[" ]t%$&vر}{˗/?-5@>^/ K҄ b>1;R;YSC ѱ7m >'a^)Ξ={d̟܋M @g044 R<ݍ|.^qѣG_EgN= 6L$2~A /(}z?)h4B95 rIY/Z]MutlBk.;""#;޾}[|f\ݡD,d*bbb${G{\{IYђ%t@33q{)<XZ$s%K.ib# Hs-|СC5rV *ULBFOw(P@~r y }b$_+13|@,Ch.:L:P9qP[{aڐj>eڴi ɢ?@LwwɴD- <8HXm3HsC}[ERK~֓?0bD OAO\z57iﴊ4EFMr,mϝ{RTdfSѨ0@P.81(TMډ$Q#''бJ泩 Gc02O6|#^I-i2Q4P{J7P|F^rQ'O~H (ݻw7KP4S@Zjdsm^T7nj׮IS1/%/S J6)GNN uƍ=ٴEdNx`ዢioSmqݺuQ^Y|(Ғ בiӧWd39!I+{əḟ$$쿜ı|: -+s5P1 o޼n6ת0^MՋڒ:_tZ>m gWyjGl\,DGE[4l?aPEDyL7\2Cŋ[R\~xpKT|u_SRRR{Ҟ%Nף{0d ܺ*</2]lA|Ӧ.wqq,:|, h*#ibw{ZC"U%`=VZPT)ٞGO_dUZU:Dt}.{Oc{*mIβLk)b1bD)|ܨdwwۅ z 5(*-uCRf-x"ٳ @lK V*U%X(*aÆ\>?5Is6nB eȏlYӈkoAT'y P2|+?q4~瘟K~#6:>IZʜ^j421F$4-4Ugj&H @ŊkoTb9m8 ߔ#f?+Ej&&iiK&8w'͹oAQNCf^Vv "VM:thBZo Oa2OLreS&(D|W!((BCBzqF"gWn"Ԣje ǝ4!IB?5Q+~["Pɧ34MC 4;g`ݫ5ܖ6_XC,ZQ_`+Ԗm@/tʕg^Aތ`Y Y\rX d>笟4VPByi#S)^{+kς`:);?I3A8| .2z?/3ռ4+y#MQ1摒jv#jլ 8@vٲeXɆJ-+P# V]lYz}jWjժI\T R EyHheZ>2Ghߥ{ff})`ATQzuv„sċj4:KChpuve((i2\MC@t2<@=, /D߈A+C^icVSG ̟#-7C4D拝%JU0nܧ^)Zz^tbGG=U.X4K^MQٳgw u AvTpAILrF(+Ur)d`P*T~ ht?+tÍJQt؁6iٲ%ßҤXgə[.j@.aKXbŋIۊ > (VLrϞ= ^^ [~񽐐ZBq%(DS  &d&+L(BMJ a 5GyO@2e =NR4 f$lnǟ' WmҴiSwvTzt?ze%o y5]+2*CܹsG2GuܹsTL`ʳJ0(D-&_,:M Ŋ+f @eNRBj`L;(U9HH+3h:N@$m)SSRǂU/%/qY+Ҿ *z 1yd >La0YGW~V@` *g`"Xҭ/9nKTѡNNh b)"PQQ{+4ş#Z/M>3GbSQ1"ڒ _ OcիkϤ1k׮ޕ+:tݻR1(|PnX@dy6:XSHr"Exヒ(̠Vȸ)N yzKy ZTJbbvti-~.5*:Hү_b؎r4@g\JY8oZ[X4-tM{quq4\WɃh! mm QAD;pG< `̌bH5p9v3`P  @ZɍG)jA?~3NbP99U΢fQ?ꁖ"9$#xZlRH x7o最2W)I 2hK&D EV V9sE ZǢx19@v4z']i$\qt Uh{A$&njyN^KlK>sVVxCf/T F%? Q,#^4iXb6OA AbN 1i0J9#9&2\Ǝ9}EJb:* ,KIj̃'c٪UxRm#iO/4()%zghָ.8R9u$N:',3!eHĊ#YCۜ Z IC%8!d}Q/q7B{2JJ DILR_*Hz fuӧwA>Cs4gȅ)DbOlaO|F45+8b2KCV--S"[?< :Tf]z2gH 3 1jo_ܭɞrES8$eҐy9}{̀ 0}(W9! BIreEKtZQwǎw=||1eU8Ix 4Ъf jE !!EM4U?=< ,~oa1#kv*oIL͖Pkb'#HgpgP3ϵR2RQ.]"RZrĒ*^z}_pfR,df$hFuJ6uA3H/X~%PNMd]xczbt<Ç3mCBf4X]mEJߤY\,Jh"Hr)#.۬@9pi֬K.qوi4lsϞ=~/ije<cGiFt7I &V ҌP98W@?4~!`>x[~o}Zx28na%+fB|Z$!EqvcfSc)&pILU4l鸬| xKOSaBP;=AQ~mڵkשl2s Vo<(Uҏܡqayh;BAb%V7/A?Cipm]"d$tv%X3WKg:J4Ӳ43\yhA8~& @M/J uIh,]oJ8wk x(8zCjఏgE'hxȇLGӗᤛ UM;Ѡ Kzj'pw›w@"`i25^WL⮁$1C;mS &޳&H ` K0]0ybkTHy=J\bMBΜ9h-fZ+lѢwnHp?yODV h|Z+_!tt}4|8Ԫ%?b: $q>3=|Z7r -bZ:Z-IiW)M3P2(JU;ٮmfxjxrH9B?IEŤHz*\rEF>ɨPa(3j߾}E)b=V})^O"Q/ "2_ 8X.YZjժCŊzkny3>NZX `ⷨ܌KxKr= TGv&B'۷fx[$ Q Sha:8Y!O̧ a4h"8GrG k &{KZ,c&2m@Radt|R|t {ZQ)r͛7-njsF䇓3$%GES'2]v#fv9P dUƄ sи@-&if:q\r ^QGu8]Fk֬)!$'%Ṡ`>Ga&;pVLj1 vc&E!M[ؾ3SZImpQn8*ue2Cji.X 8CfGP@R6Ծ#\.栍uhXW#{4tLN$|R|iCt}*5iܸa׈$S`.0RS4J0s*DƠ%u&U|3dモ-Ұ^t|~q:lgX AXQ\Q2 }B(8-n3[LsBfQ]=)@''0Iٴ'211ҽ0P'hs h99e x{Ȟى,hBM"$ }ǒ;wdE*UB~,Ӗ`ڔ/y@HYcl! R󫖄g pA@oM:$м~$Hc̢90{ꥆ&tyۛ|IdPR؇0qpDŚ`]bб,4߀$;vL2i(&_8M J+fk 3>2|КmH0޳㭀 uz~8$ Fb;w^is yXcL}E*;z Aȯ2sIEHbfömۤY\`ؔxtr4_r*2*g;|@l,Di%{Des q( D+kTc:LTVZmku !_0B Ufc"ugςmF_Au-9_KO\$G]>}ȑ0u'pK:93j{`NCb5{< h״,{Rļ=|0LU['PK}wh5͜+b kԬ#kHY@^ Gi\nTo#Lb(Y hSжg$pvҥ(^0j&๓yi0ˊ|n29h/{$"*ɲ DW:5l\' 1//Wvze˖H2qr8bs?mc -PQ W'>PZR,4*W"H$K@ܺu+L<Zֹ?uQnג2\=%x@*9Hue mn4u:IeӠAEVҽ5VD껟1BQ!jt&h= _UװÆ {2E*jOq.U=<6j)xbţ?[#;w)?P)fz ӈ$BF:fMaw;M`22RK>E?|=ZC%/ZP"C,T N d2k·+FU@qk3m vcD*[ ;L]eEd'5)WsE&+`]ʪI֯@R4I11K xV ROCޞ:X= W6m cF^CX 5krwB\ҿsa 1T1ybTKXNhm~=8ABf\gLYf>5<7ST@ ZA <9q0gzn߾ݻw_rhl>P@͛턊%qlRޫg͒9g*ad m)Z Q6Q9:y`,yvڵg9 FSY:DpPh}h7 ~EÖ=I >|8JȴiFa-J?'~a~0{7+e}D%C'?y@$7Q`^0nWkq#;iom[Tdڃ4yq,kT @X2C+OBQQqȑ#r` GORߥKBI [lG­]Sd?vKF @FCFk:dn{M7IۗJ3ΣyQA LqD$jFt度su?@w3j]4p4CZ%K=zHo,4,|5غe#$'FlMWjAey@b=hFV 9*ū-7otuyg ILQߢv|;v!C ˻u իU5kJ+iOM UN>5zk{')'CiDq7ZG@y]qjVJR.੶N&jۦ^ 1EJ5$%Hnգ:EYsC?PZj56+V;C^p0,\OJtqZ =C4fT^jj 3*豋ӑݻ`Lt_79AݚH= ύ?ĩޓ0ӱ#@UH}٠ɓ'7?d&Z`t>vqϚO/x1 {2|& "gzJqS%ƚ`NH=DF-Q66[P!ieFK(GYA~ܺuS4}f<3^EH)uԩ@Lt%X3\&.4o}[![k'MjMFr߾}f"RTF DJG̟xe}X̂? -[MOKC^yð"WWm:u"L7oJ5y%J$')0S'B-ca OjzI9~b>-2]dm45jS+?@U9iJ~r7=|/3޷o=d\0}lyxK/ 5nx`xT˗85;LygYS`P'yi zCR82~?2b~Vj˽*3yN/5kV6555 wܵ d;`. (}Cmk=i`ӦS :Q\bNuȉ;Ṵ!/2]sz)@ԸQW]bs)yT*Cb1xlTkpI̿bO1VmvME6]~]N%Qf`P&H3@t@sGmr0NGT^zvy`ZBR5񷞴*Qk'%̿yV׷uJ>ʼnq^J߽[Ō}/_j鲱M&!9}K .?Rt0䖨s G)' %&tb-EvtrnG?Fz{^!V?grE<wq^G? N{(yC^<冂y  KN% IENDB`knowthelist-2.3.0/images/DJ.png0000775000175000017500000000307712423536022015352 0ustar mariomarioPNG  IHDR szztEXtSoftwareAdobe ImageReadyqe<IDATxڬ{LWRگEhKI˻q8'S㜏8pA-&@b6c:(.Y%E "l(HKi;SHPNrw=Qnm"h].wl60j tO*B@p* e||&&&`ffl6 xihh̑JZ*oHNN&@ϟϧm=zFӹ#""*j*''s_բaPw;v|fss[[VXlذ UBJKK"XLߎ@oRyAW@\\ :j8{ɑx@˥PTTEKP^^F=^*|6\]8E u봘U":44sŋMHq]|eJ5ME ؊Ut3!`jY훷l Bؾm $8S+<z7[Z`V]Hw:bGTʧU;*OrZWM8pϞ0 tD"1F ]?G9bst ֮ɉjhtqV&nwt•sTF&3o{p#^2gN-bf*&Rc3΋7dw Wav6mcZ:=P-a'L^{ ?ZhhZYfv]B8'(k<#^L<@%{ E)67 )* 8ISsTJw\@QBƖy'@tXtػɚ EBX]%p:|x,צ& ri,ܹ FMF^L7GGd6#c?dӠv?tw`^zGQ8M_'hb|kQi}RhbbbJDpWRmZ,}GiB>}Z S9l+оA-Ѵ@(n 6 U6$2 Z=|~"<>q6 {<~D` <1<,\x'=`_@2IENDB`knowthelist-2.3.0/images/star-off.png0000664000175000017500000000076612423536022016575 0ustar mariomarioPNG  IHDRaIDAT8RARQ3#ZC\QEuSmjQ-cOr!֒HC=_ޅ.;|~! Q-k4{toyɸ'$]B^Wun]̾ $LU "(l60J(WsD"KUk$ou ?HVշdr*RZ>Sɖwt8^>Ifgh4pE+ E(:yH~Z.z~[Jr+͞I`9|cT̨ry43')f30UݿDpy|gfSg2( R?$Af0LZ}9'.GrI>v'ѢiV!"76$Z͸? 61BIENDB`knowthelist-2.3.0/images/settings.png0000775000175000017500000000432012423536022016705 0ustar mariomarioPNG  IHDR szz pHYs7\7\ǤbKGDBIDATxڭW PSg>]|*bΔ _](<@! cDPUPlj*-ZI48LwfEfL94I QbŠneURbp]X2>ȥ^"?p/((GQ 6 ͛|WˬXffh3Sedĉ[s75z@ |Ҕ ƲeKa;,X8fς~+[c>wN>qm:|0߷oOb񒅰nǍ? >N* zj*U+>|tܩqGșHLC"cc#$AL|7;nS`{eii df-L *M^-YT#["zTXtSoftwarex+//.NN,H/J6XS\IENDB`knowthelist-2.3.0/images/star-on.png0000664000175000017500000000125512423536022016431 0ustar mariomarioPNG  IHDRasBIT|d pHYs B4tEXtSoftwareAdobe Fireworks CS4Ӡ'IDAT8?La^k{׻-`$ł C&T7eqra¤ qrs#Nf#dѥiMt"ZJDۆ;*ρ?C賽yoȤS3TO#ڈp@i= ÑH4I) Ny(T&2z2K at)|ޞI@&J4Fٯ:H)4 ǩRukض  $st(Z'mmmg@Jmۨtu`&G/қ7bB86RrP86啷c#pƕeŅ&n~UG$Z UQ)o|3^+DGJxp]."eֹͭ5655%a[^@ :V89 1t!~BbZ&BN{|eUuAP`P9LJ*bIssKHO {ڧɧ3+l鈚[}D+K=͎%hhnxhD{IENDB`knowthelist-2.3.0/images/vinyl.png0000775000175000017500000002254112423536022016213 0ustar mariomarioPNG  IHDRi7@bKGD̿ pHYsHHFk> vpAg01$IDATxym]p{խnB$$q('\@!S!I\P(LQ* TRƉ\qc+$P6PN%@H@ZVoÙCkkeda߳~#;gt1/y-ѵz#[04jJZC Zĉ|276`]R\a3hIoNu7Oz(gIRƿ KzQE}y7'6O|HOer?m{Qtͱ\&ԆesFbS~?1ERK &|]!PW" WߪXVVގJa]U;~_ n!!<1ujdtuJxW[ZZ+¥xzsnx%%>=LڗůpS#]2BۚG$,MLT^ !s˗lcJױCB,ӓH Ranfnn@#44,wre#@hd>v?+=@%vHbRT$ @>"rKFs|U Y3ˠ$2]W7&zRR3r'ri RY*NsH*vąRW_j,sukXP_,-^@)v"12Pg&*\W.(y\GWPHj\!R3Fw_4bL_ԎdM%bDRްfeB+)̍+ M+Ŗolbaw~CzROXH"`l,qH2S2,x ZNXJsCZg o~t%Y_B5ޣo}TsCC" CDOOT"\w Llah*s$QZP;ĹS+clbEа~׫ZGjpYP814:UkL[ ;a_c f"T#648Tr]S?62SLۢz sZrpcbHad)w/ /bb)*ssL"3q.5o-KcZ/|o|=$?o~s4P -;vDLgap!SƖeg˲BB^ CK2XRj;qE떻٩b?W@_}h5jV (XJǖj3J]: F,ѓbfR#,-uLEXH!YXQu4ߑث_ Ky2XLj*ZMt-zT!+,+KU,AGdl6&͂6ûO4AHt7V*>FJ]R78KKYHg0DD*7W;ԓJDZ*ils g{ @Uݣc槒r5r3TlpPK,\* uuttuC$U!U+e2` SB[cnw>H 'o|~F[ڠ%Rs=TDjC]ªg9D#)j\l,fB5gWn /@,5^DiŵFQL#V(u*IHfP4ao5_Q8S" PYJj3RX4Z};:Eu_q=,Dl^zޛCIX|`j.;Q' ߉aX6,K a1,_TҠA!26Rl8=8 xK^uW{G~G2<0LP-! $o""rebDX)Vf!4߻ڼ#n64^ȑGAc@kmY4I,%R\)C:Փ`-! K Z-\[(th[l–7k<}]/9^s@78mX\x}i̩3p\ωcG: *ܚ]g#l} zz ݚHt>*)q@4YOV`5j#CmOOx@WBq֋;lkz&o_<mxo={ll6WBX:0祐{L[WxH'\mO_>x+N܍ьwVKję?Nl8?(xC 6KICn]}Sf^}wnz*`6)}.4̝Ok0٘Dב08ln+V$ǧ+N8{.Oz7(pZ-z?᭞w%^8W}ݺ}U YqFPyymX[Ƹ^{<%rͫ!I*#~~3G*(,}_%A!OB\k+~"9FF! tQ}?C&rE]vL_$ɶ8 ǹMo/W_&=3/zܟ6~V+3NAkW6FIyu TяĻu+ek}A얱:!r[x:&cQ)~Ѽ M"}[[)6 ɥiNz!z۝&hާa. *ei7Jkջn#ߨf=fzCB3~PwD~ *1YpkưDG^ |]z33 2~yv'GHX 8r=]E 0U^Ov_k~yL\mFG=]lcp V7h-i|Izcv+({chRd_d?^0])Nnº 64c^mi>wVB3WgZb[L煎 {tf>~z& K+Ht>82l^en!z)_krk7^>NͯPՕd{/x&4xǣTeoq[=ڜ;qC~]WE of7Gl{6R[M. x&kҦĩk8mP: q ro׺?W sopjK]@#=K7¶<WH7u@,q(j[&#ɧ`6D.pv\7Rer/ "@/]Ϧ[B*MzUė`-;WcJ= @$ҋ#W!zN73=5;1b ϖ3_}WZOU\⳩ֻ;.MXn8 L`\$>鋌/ٔzб{pyӯ tt 6 !o6?V?)SrC8\՗`lV텯9:ܽ z/?6Ղ.Ƒ/~rv%lowX2 V3m ] A1nRlc&-bc79LPj.g 69`;< u{yW{Xdfj[} 3?^HaD'{Mq qTk ֿ'nI|Xĥ˾0 +N/V%*]M}YU[yvU`p ?V_9 m~*sa2W˶j*V〫x;[mVQZ bϛ:TNt\vŚzDoBQIo Ÿ}ظ]5 ASǫ.;s}Ȣ7JIn Ezg e{ ~h)?̪:`xa5/ׇy12B얏JVd9`khXF0C>i=ugvsoLmxR,Pn-YsާP=ӱ/c-}m^i,+s6nAu|o]ˍq?g,T#DvYrb~>nWMW,}gSy@3jskVlƶڶs"Wes>}:`8]7d#U72WGeۏXGw/Sަv-7f9ښ־2̳7{70v3Tn `ĮHW<>ySj;C\Y{xe$79hag;Flʴ_'^ų'M~)_̕؇ڿ 魤2q|\8v5{MX= 6Mir59qKٶe5a|t^|Xģ~7zq2Yf#Uc=B)rD;3TKTX53BjֺKjyi3\^m~/lKok7Mh! ⰓpfȑZan6~$ҕHER&SաgR"پ_lrc* h&Ku10h>ڀ "DhNCM*\P*hv/A~) )7}vb<1UFqpFV!P<$MC"҅BTb. :]|]mmdھW)5G+=j}KK}7QTW7l-J<$13U`.7nZٓ-Վ 4*_ i6w7l6DNͥr\djCOkTXDi.of R7:2c롷ȹLl&PCXaUSɧpmsw"ؘJ)Gv$beh-o{2 J]df.tdu:,kM4SUn OAؿ*J\bQY2KuB4ߌBin8|ѳ4Ri2slivO>;ڦHʠw.L~ݏ{vw4 @ 2)dIO6*tַkCߑBuRDb G=g ̔Fг`Z}hAhgl=B8DQ;O@#VXH9Kݴt20)q(\_:1Fs8SYBb;<=n3-nKR$ { 3" ,Pem [HB3C 18Г-^Џڂ ۑB/7񂥛NL\wKaJfhP*cC/  ?X_\sӷ{wwDj=ʅ‘ڑS.5ӕ]f/"HL)uԉCFrZis> "V@ \A0R"C ="︴&4t3CfffffuKCK @ B\f#ב{̓^f!f̹S/`rfM/`X%~jmtG{sr#RZ,R{uEK|_9ٓYxr @{"]7`׷n;r%mԺcv =Ͻڙ/!& Jz%tEXtdate:create2010-02-10T04:44:17-06:00 ߩ%tEXtdate:modify2005-06-28T02:35:12-05:00DjIENDB`knowthelist-2.3.0/images/icons.qrc0000775000175000017500000000127712423536022016171 0ustar mariomario clear_left.png DJ.png database.png settings.png folder.png vinyl.png search.png shuffle.png play.png pause.png slider.png volume.png stop.png backward.png forward.png list.png down.png star-on.png star-off.png knowthelist.png knowthelist-2.3.0/images/database.png0000775000175000017500000000237712423536022016623 0ustar mariomarioPNG  IHDR ssRGB pHYsu85tIME 39م$bKGD̿IDATKoT}#JPP5H4>U]vUݴdJHU*DA 6jib =c{z1 W~'Z`' N|'J\9Ň2 0)RJ)2iL/>rwfMIO4LE*SizZi75ͫ\z)  IJIR* E/qWw _gr,rQ DJB!hvt"nOJd )()O!^I  9N $I$!Vx9َ=J Q@RJ[oF @cqA֌+NiP,jaFNV Қ5G QPKFl[SV<6V|4.rUUUUUUUU / |Tˬ|{7mҔIuSkmUlO~"߮ݳfg ik8gf-޴8Dxղe=Ism]-}=kºrox ZrY]t5R7iZ%r4eˎzAN'~kІ :]UjJD2bf*3(mrÜEs^Ϝ9 BCݔE_:gu?vWaז`薊k˼*tտ<02:Z82u:_;85YfYoUqw{UHڦDIENDB`knowthelist-2.3.0/images/slider.png0000664000175000017500000001166612423536022016337 0ustar mariomarioPNG  IHDR@@iq}IDATx[ipG~{B IP!Iv׋u_  ImUjK$ɵdש~ lؠ :{{YsHH #iޛ=3=R!w>,^|nu4+u8ͺFi},>:?:Gbu]N ~?fafY/̝c  }29Uoo߿z_yZڼXx^n@F<H@aX$J._`l|5ڨ̓)8󿛚ާli?ѱ154͞%qRU2D$'B_2'mµ]78E39'3ی nLˢ"! ~|^KNq&4,$ <0aQ  o8>;hݹsoz5|iZyⷶB{tR6$mFzA !3(<Dwԧ[oxgLLL@sq[ ѰqF8s ##t~om 7P=ecYy~> F Ce P N_ݐ0g$4!Ex̨m!tܽw>ncmpeoZp܉tm: v>=M rhh(~k9,\{A]c tJ \gKK#? 'HNB LRzزH bzw$nc{K,8*p:vJ/:KONkPUA៪02:_ \',ueUD>$ 11kq|X+h/Y&W^ _+g^Ҳìik)`!Maju1$x ֭]),Ug9j'1ҷC<?/$D8 ܪP\h.f_JKM3P̢hD>=2OoucS=8ce} tI&''`-cGbgaM q@Cs %9[uytg*If[Tft:Tiƶoz@\\<0-[@cs;t^(U(80죩XrY$98>3øb9Z~K訄*$d (3.q`S r q٧h"5%'NݤrctvP?spM,cZ||<3WEL4d4O:N$lܰ23e? 2ny-i (U3 'Uוsh:7#-xD!66.\{_BttS8f!n *Y!K ,NTv2Ó˽,ٳr&4>d p;?x-,=00o<p45: 6@q•^hi=]"@,bぉ񎑠2H-rK@OO7oA.fxTwŊַ !tM$ ʄ @FF՟* :^8F=CfvZOf8#..%$~=q<0"! [pW 5eo<E/0,  ]\hb X}ӦDt7]\'0%|>$~%f̔[\9D9[rpDhlc9ظ8@Du{@zrUaCc-k'I؋$g :}yXx1' }r~?Ú51kv@ o6$d D/E 11)BU8b) =DǪNohˌg۲EF;ja-逗^ʔ؟?Km5͂@ #?))Y\L6rc1dR/(Qh{) ˆ%Ekj).*gݍ8 cYZYI5A .Й~xؑ dONJpQrQ__cpim= N(Rlu|b \Xu%@",)FrPWWm,ܲ%"$.Aӓ"*C@kI(,e0(U*[S!;\Vsn,k|@<#iuoܨE@ǘ'X;qr8i(+D|jJlUWo-9_My {_QT #3˕pݽ 1v0DY!YSmsB$\:T"Y~71t C2 52,9Ddr@%ss])w'K ?yY&ŋ@NN,8/uva8! xc_lfFHsQ--,G0-p@jI4s`bI!w;bJbbb,pr'4okr>J\72BGyRT # HJQ ?}N%>o߾b g&Wo~&rE%/uPU:XeG)^)U1@ _%)}:݉ء!IFEEeˬo kbZ NhlV(YD@ZuYa6Hms 0eGlN E2\{ _聒=,"N1rJK鑘Us]&x8[ #Khsr5(*ک̺sׯ_䟐aR~OO3ϣa:sٺ@Ϝx]]dBXJm=eK#p%(c;h)dWm>¦͉h5c@f6:x+$hB)k /9:>p]b-q # y@ii!*\8AB 7n@6fp+V4Rl3 F򳡬>wV>F,ny]jGh)!1,F%aBKm,( 3hl Я@W+ZK & ѫ*$&;?#XVY@R0Sr ȪkJF5!&holkBTh5!57$•R!+BG 3hl!,Zy޲27/l4~w$H- YDV;>m=-:w/wus * Copyright (C) 2007 Pioneers of the Inevitable * * gstdirectsoundplugin.c: * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301, USA. * * * The development of this code was made possible due to the involvement * of Pioneers of the Inevitable, the creators of the Songbird Music player * */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "gstdirectsoundsink.h" static gboolean plugin_init (GstPlugin * plugin) { if (!gst_element_register (plugin, "directsoundsink", GST_RANK_PRIMARY, GST_TYPE_DIRECTSOUND_SINK)) return FALSE; return TRUE; } GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR, directsound, "Direct Sound plugin library", plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) knowthelist-2.3.0/gst/directsound/gstdirectsoundsink.h0000664000175000017500000000626312423536022022316 0ustar mariomario/* GStreamer * Copyright (C) 2005 Sebastien Moutte * Copyright (C) 2007 Pioneers of the Inevitable * Copyright (C) 2010 Fluendo S.A. * Copyright (C) 2014 Mario Stephan * * gstdirectsoundsink.h: * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301, USA. * * The development of this code was made possible due to the involvement * of Pioneers of the Inevitable, the creators of the Songbird Music player * * Patched version of GStreamer sink plugin for Windows to enable selection of audio output device */ #ifndef __GST_DIRECTSOUNDSINK_H__ #define __GST_DIRECTSOUNDSINK_H__ #include #include #include #include #include #include #include #include #include G_BEGIN_DECLS #define GST_TYPE_DIRECTSOUND_SINK (gst_directsound_sink_get_type()) #define GST_DIRECTSOUND_SINK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DIRECTSOUND_SINK,GstDirectSoundSink)) #define GST_DIRECTSOUND_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DIRECTSOUND_SINK,GstDirectSoundSinkClass)) #define GST_IS_DIRECTSOUND_SINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DIRECTSOUND_SINK)) #define GST_IS_DIRECTSOUND_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DIRECTSOUND_SINK)) typedef struct _GstDirectSoundSink GstDirectSoundSink; typedef struct _GstDirectSoundSinkClass GstDirectSoundSinkClass; #define GST_DSOUND_LOCK(obj) (g_mutex_lock (&obj->dsound_lock)) #define GST_DSOUND_UNLOCK(obj) (g_mutex_unlock (&obj->dsound_lock)) struct _GstDirectSoundSink { GstAudioSink sink; /* directsound object interface pointer */ LPDIRECTSOUND pDS; /* directsound sound object interface pointer */ LPDIRECTSOUNDBUFFER pDSBSecondary; /* directSound buffer size */ guint buffer_size; /* offset of the circular buffer where we must write next */ guint current_circular_offset; guint bytes_per_sample; /* current volume setup by mixer interface */ glong volume; gboolean mute; gchar * device_id; gchar * device_name; GstCaps *cached_caps; /* lock used to protect writes and resets */ GMutex dsound_lock; gboolean first_buffer_after_reset; GstAudioRingBufferFormatType type; }; struct _GstDirectSoundSinkClass { GstAudioSinkClass parent_class; }; GType gst_directsound_sink_get_type (void); G_END_DECLS #endif /* __GST_DIRECTSOUNDSINK_H__ */ knowthelist-2.3.0/gst/directsound/gstdirectsoundsink.c0000664000175000017500000007201112423536022022303 0ustar mariomario/* GStreamer * Copyright (C) 2005 Sebastien Moutte * Copyright (C) 2007 Pioneers of the Inevitable * Copyright (C) 2010 Fluendo S.A. * Copyright (C) 2014 Mario Stephan * * gstdirectsoundsink.c: * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301, USA. * * * The development of this code was made possible due to the involvement * of Pioneers of the Inevitable, the creators of the Songbird Music player * * Patched version of GStreamer sink plugin for Windows to enable selection of audio output device */ /** * SECTION:element-directsoundsink * * This element lets you output sound using the DirectSound API. * * Note that you should almost always use generic audio conversion elements * like audioconvert and audioresample in front of an audiosink to make sure * your pipeline works under all circumstances (those conversion elements will * act in passthrough-mode if no conversion is necessary). * * * Example pipelines * |[ * gst-launch-1.0 -v audiotestsrc ! audioconvert ! volume volume=0.1 ! directsoundsink * ]| will output a sine wave (continuous beep sound) to your sound card (with * a very low volume as precaution). * |[ * gst-launch-1.0 -v filesrc location=music.ogg ! decodebin ! audioconvert ! audioresample ! directsoundsink * ]| will play an Ogg/Vorbis audio file and output it. * */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "gstdirectsoundsink.h" #include #include #ifdef __CYGWIN__ #include #ifndef _swab #define _swab swab #endif #endif #define DEFAULT_MUTE FALSE GST_DEBUG_CATEGORY_STATIC (directsoundsink_debug); #define GST_CAT_DEFAULT directsoundsink_debug static void gst_directsound_sink_finalize (GObject * object); static void gst_directsound_sink_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); static void gst_directsound_sink_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); static GstCaps *gst_directsound_sink_getcaps (GstBaseSink * bsink, GstCaps * filter); static GstBuffer *gst_directsound_sink_payload (GstAudioBaseSink * sink, GstBuffer * buf); static gboolean gst_directsound_sink_prepare (GstAudioSink * asink, GstAudioRingBufferSpec * spec); static gboolean gst_directsound_sink_unprepare (GstAudioSink * asink); static gboolean gst_directsound_sink_open (GstAudioSink * asink); static gboolean gst_directsound_sink_close (GstAudioSink * asink); static gint gst_directsound_sink_write (GstAudioSink * asink, gpointer data, guint length); static guint gst_directsound_sink_delay (GstAudioSink * asink); static void gst_directsound_sink_reset (GstAudioSink * asink); static GstCaps *gst_directsound_probe_supported_formats (GstDirectSoundSink * dsoundsink, const GstCaps * template_caps); static gboolean gst_directsound_sink_query (GstBaseSink * pad, GstQuery * query); static void gst_directsound_sink_set_volume (GstDirectSoundSink * sink, gdouble volume, gboolean store); static gdouble gst_directsound_sink_get_volume (GstDirectSoundSink * sink); static void gst_directsound_sink_set_mute (GstDirectSoundSink * sink, gboolean mute); static gboolean gst_directsound_sink_get_mute (GstDirectSoundSink * sink); static gboolean gst_directsound_sink_is_spdif_format (GstAudioRingBufferSpec * spec); static GstStaticPadTemplate directsoundsink_sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS ("audio/x-raw, " "format = (string) S16LE, " "layout = (string) interleaved, " "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ]; " "audio/x-raw, " "format = (string) U8, " "layout = (string) interleaved, " "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ];" "audio/x-ac3, framed = (boolean) true;" "audio/x-dts, framed = (boolean) true;")); enum { PROP_0, PROP_VOLUME, PROP_MUTE, PROP_DEVICE, PROP_DEVICE_NAME }; #define gst_directsound_sink_parent_class parent_class G_DEFINE_TYPE_WITH_CODE (GstDirectSoundSink, gst_directsound_sink, GST_TYPE_AUDIO_SINK, G_IMPLEMENT_INTERFACE (GST_TYPE_STREAM_VOLUME, NULL) ); static gchar * guid_to_string (LPGUID in) { WCHAR buffer[256]; if (StringFromGUID2 (in, buffer, sizeof buffer / sizeof buffer[0]) == 0) return NULL; return g_utf16_to_utf8 ((const gunichar2 *) buffer, -1, NULL, NULL, NULL); } static LPGUID string_to_guid (const gchar * str) { HRESULT ret; gunichar2 * wstr; LPGUID out; wstr = g_utf8_to_utf16 (str, -1, NULL, NULL, NULL); if (!wstr) return NULL; out = g_malloc (sizeof (GUID)); ret = CLSIDFromString ((LPOLESTR) wstr, out); g_free (wstr); if (ret != NOERROR) { g_free (out); return NULL; } return out; } static void gst_directsound_sink_finalize (GObject * object) { GstDirectSoundSink *dsoundsink = GST_DIRECTSOUND_SINK (object); g_mutex_clear (&dsoundsink->dsound_lock); G_OBJECT_CLASS (parent_class)->finalize (object); } static void gst_directsound_sink_class_init (GstDirectSoundSinkClass * klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GstBaseSinkClass *gstbasesink_class = GST_BASE_SINK_CLASS (klass); GstAudioSinkClass *gstaudiosink_class = GST_AUDIO_SINK_CLASS (klass); GstAudioBaseSinkClass *gstaudiobasesink_class = GST_AUDIO_BASE_SINK_CLASS (klass); GstElementClass *element_class = GST_ELEMENT_CLASS (klass); GST_DEBUG_CATEGORY_INIT (directsoundsink_debug, "directsoundsink", 0, "DirectSound sink"); gobject_class->finalize = gst_directsound_sink_finalize; gobject_class->set_property = gst_directsound_sink_set_property; gobject_class->get_property = gst_directsound_sink_get_property; gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_directsound_sink_getcaps); gstbasesink_class->query = GST_DEBUG_FUNCPTR (gst_directsound_sink_query); gstaudiobasesink_class->payload = GST_DEBUG_FUNCPTR (gst_directsound_sink_payload); gstaudiosink_class->prepare = GST_DEBUG_FUNCPTR (gst_directsound_sink_prepare); gstaudiosink_class->unprepare = GST_DEBUG_FUNCPTR (gst_directsound_sink_unprepare); gstaudiosink_class->open = GST_DEBUG_FUNCPTR (gst_directsound_sink_open); gstaudiosink_class->close = GST_DEBUG_FUNCPTR (gst_directsound_sink_close); gstaudiosink_class->write = GST_DEBUG_FUNCPTR (gst_directsound_sink_write); gstaudiosink_class->delay = GST_DEBUG_FUNCPTR (gst_directsound_sink_delay); gstaudiosink_class->reset = GST_DEBUG_FUNCPTR (gst_directsound_sink_reset); g_object_class_install_property (gobject_class, PROP_VOLUME, g_param_spec_double ("volume", "Volume", "Volume of this stream", 0.0, 1.0, 1.0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (gobject_class, PROP_MUTE, g_param_spec_boolean ("mute", "Mute", "Mute state of this stream", DEFAULT_MUTE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (gobject_class, PROP_DEVICE, g_param_spec_string ("device", "Device", "DirectSound playback device as a GUID string", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (gobject_class, PROP_DEVICE_NAME, g_param_spec_string ("device-name", "Device name", "Human-readable name of the audio device", NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); gst_element_class_set_static_metadata (element_class, "Direct Sound Audio Sink", "Sink/Audio", "Output to a sound card via Direct Sound", "Sebastien Moutte "); gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&directsoundsink_sink_factory)); } static void gst_directsound_sink_init (GstDirectSoundSink * dsoundsink) { dsoundsink->volume = 100; dsoundsink->mute = FALSE; dsoundsink->pDS = NULL; dsoundsink->cached_caps = NULL; dsoundsink->pDSBSecondary = NULL; dsoundsink->current_circular_offset = 0; dsoundsink->buffer_size = DSBSIZE_MIN; dsoundsink->volume = 100; g_mutex_init (&dsoundsink->dsound_lock); dsoundsink->first_buffer_after_reset = FALSE; dsoundsink->device_id = NULL; dsoundsink->device_name = NULL; } static void gst_directsound_sink_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { GstDirectSoundSink *sink = GST_DIRECTSOUND_SINK (object); switch (prop_id) { case PROP_VOLUME: gst_directsound_sink_set_volume (sink, g_value_get_double (value), TRUE); break; case PROP_MUTE: gst_directsound_sink_set_mute (sink, g_value_get_boolean (value)); break; case PROP_DEVICE: if (sink->device_id) { g_free (sink->device_id); sink->device_id = NULL; } if (sink->device_name) { g_free (sink->device_name); sink->device_name = NULL; } sink->device_id = g_strdup (g_value_get_string (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void gst_directsound_sink_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { GstDirectSoundSink *sink = GST_DIRECTSOUND_SINK (object); switch (prop_id) { case PROP_VOLUME: g_value_set_double (value, gst_directsound_sink_get_volume (sink)); break; case PROP_MUTE: g_value_set_boolean (value, gst_directsound_sink_get_mute (sink)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static GstCaps * gst_directsound_sink_getcaps (GstBaseSink * bsink, GstCaps * filter) { GstElementClass *element_class; GstPadTemplate *pad_template; GstDirectSoundSink *dsoundsink = GST_DIRECTSOUND_SINK (bsink); GstCaps *caps; if (dsoundsink->pDS == NULL) { GST_DEBUG_OBJECT (dsoundsink, "device not open, using template caps"); return NULL; /* base class will get template caps for us */ } if (dsoundsink->cached_caps) { caps = gst_caps_ref (dsoundsink->cached_caps); } else { element_class = GST_ELEMENT_GET_CLASS (dsoundsink); pad_template = gst_element_class_get_pad_template (element_class, "sink"); g_return_val_if_fail (pad_template != NULL, NULL); caps = gst_directsound_probe_supported_formats (dsoundsink, gst_pad_template_get_caps (pad_template)); if (caps) dsoundsink->cached_caps = gst_caps_ref (caps); } if (caps && filter) { GstCaps *tmp = gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST); gst_caps_unref (caps); caps = tmp; } if (caps) { gchar *caps_string = gst_caps_to_string (caps); GST_DEBUG_OBJECT (dsoundsink, "returning caps %s", caps_string); g_free (caps_string); } return caps; } static gboolean gst_directsound_sink_acceptcaps (GstBaseSink * sink, GstQuery * query) { GstDirectSoundSink *dsink = GST_DIRECTSOUND_SINK (sink); GstPad *pad; GstCaps *caps; GstCaps *pad_caps; GstStructure *st; gboolean ret = FALSE; GstAudioRingBufferSpec spec = { 0 }; if (G_UNLIKELY (dsink == NULL)) return FALSE; pad = sink->sinkpad; gst_query_parse_accept_caps (query, &caps); GST_DEBUG_OBJECT (pad, "caps %" GST_PTR_FORMAT, caps); pad_caps = gst_pad_query_caps (pad, NULL); if (pad_caps) { gboolean cret = gst_caps_is_subset (caps, pad_caps); gst_caps_unref (pad_caps); if (!cret) { GST_DEBUG_OBJECT (dsink, "Caps are not a subset of the pad caps, not accepting caps"); goto done; } } /* If we've not got fixed caps, creating a stream might fail, so let's just * return from here with default acceptcaps behaviour */ if (!gst_caps_is_fixed (caps)) { GST_DEBUG_OBJECT (dsink, "Caps are not fixed, not accepting caps"); goto done; } spec.latency_time = GST_SECOND; if (!gst_audio_ring_buffer_parse_caps (&spec, caps)) { GST_DEBUG_OBJECT (dsink, "Failed to parse caps, not accepting"); goto done; } /* Make sure input is framed (one frame per buffer) and can be payloaded */ switch (spec.type) { case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_AC3: case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_DTS: { gboolean framed = FALSE, parsed = FALSE; st = gst_caps_get_structure (caps, 0); gst_structure_get_boolean (st, "framed", &framed); gst_structure_get_boolean (st, "parsed", &parsed); if ((!framed && !parsed) || gst_audio_iec61937_frame_size (&spec) <= 0) { GST_DEBUG_OBJECT (dsink, "Wrong AC3/DTS caps, not accepting"); goto done; } } default: break; } ret = TRUE; GST_DEBUG_OBJECT (dsink, "Accepting caps"); done: gst_query_set_accept_caps_result (query, ret); return TRUE; } static gboolean gst_directsound_sink_query (GstBaseSink * sink, GstQuery * query) { gboolean res = TRUE; switch (GST_QUERY_TYPE (query)) { case GST_QUERY_ACCEPT_CAPS: res = gst_directsound_sink_acceptcaps (sink, query); break; default: res = GST_BASE_SINK_CLASS (parent_class)->query (sink, query); } return res; } static gboolean gst_directsound_sink_open (GstAudioSink * asink) { GstDirectSoundSink *dsoundsink = GST_DIRECTSOUND_SINK (asink); HRESULT hRes; LPGUID id=NULL; if (dsoundsink->device_id) id = string_to_guid( dsoundsink->device_id); /* create and initialize a DirecSound object */ if (FAILED (hRes = DirectSoundCreate (id, &dsoundsink->pDS, NULL))) { GST_ELEMENT_ERROR (dsoundsink, RESOURCE, OPEN_READ, ("gst_directsound_sink_open: DirectSoundCreate: %s", DXGetErrorString9 (hRes)), (NULL)); return FALSE; } if (FAILED (hRes = IDirectSound_SetCooperativeLevel (dsoundsink->pDS, GetDesktopWindow (), DSSCL_PRIORITY))) { GST_ELEMENT_ERROR (dsoundsink, RESOURCE, OPEN_READ, ("gst_directsound_sink_open: IDirectSound_SetCooperativeLevel: %s", DXGetErrorString9 (hRes)), (NULL)); return FALSE; } return TRUE; } static gboolean gst_directsound_sink_is_spdif_format (GstAudioRingBufferSpec * spec) { return spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_AC3 || spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_DTS; } static gboolean gst_directsound_sink_prepare (GstAudioSink * asink, GstAudioRingBufferSpec * spec) { GstDirectSoundSink *dsoundsink; HRESULT hRes; DSBUFFERDESC descSecondary; WAVEFORMATEX wfx; dsoundsink = GST_DIRECTSOUND_SINK (asink); /*save number of bytes per sample and buffer format */ dsoundsink->bytes_per_sample = spec->info.bpf; dsoundsink->type = spec->type; /* fill the WAVEFORMATEX structure with spec params */ memset (&wfx, 0, sizeof (wfx)); if (!gst_directsound_sink_is_spdif_format (spec)) { wfx.cbSize = sizeof (wfx); wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nChannels = spec->info.channels; wfx.nSamplesPerSec = spec->info.rate; wfx.wBitsPerSample = (spec->info.bpf * 8) / wfx.nChannels; wfx.nBlockAlign = spec->info.bpf; wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; /* Create directsound buffer with size based on our configured * buffer_size (which is 200 ms by default) */ dsoundsink->buffer_size = gst_util_uint64_scale_int (wfx.nAvgBytesPerSec, spec->buffer_time, GST_MSECOND); /* Make sure we make those numbers multiple of our sample size in bytes */ dsoundsink->buffer_size += dsoundsink->buffer_size % spec->info.bpf; spec->segsize = gst_util_uint64_scale_int (wfx.nAvgBytesPerSec, spec->latency_time, GST_MSECOND); spec->segsize += spec->segsize % spec->info.bpf; spec->segtotal = dsoundsink->buffer_size / spec->segsize; } else { #ifdef WAVE_FORMAT_DOLBY_AC3_SPDIF wfx.cbSize = 0; wfx.wFormatTag = WAVE_FORMAT_DOLBY_AC3_SPDIF; wfx.nChannels = 2; wfx.nSamplesPerSec = 48000; wfx.wBitsPerSample = 16; wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels; wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; spec->segsize = 6144; spec->segtotal = 10; #else g_assert_not_reached (); #endif } // Make the final buffer size be an integer number of segments dsoundsink->buffer_size = spec->segsize * spec->segtotal; GST_INFO_OBJECT (dsoundsink, "GstAudioRingBufferSpec->channels: %d, GstAudioRingBufferSpec->rate: %d, GstAudioRingBufferSpec->bytes_per_sample: %d\n" "WAVEFORMATEX.nSamplesPerSec: %ld, WAVEFORMATEX.wBitsPerSample: %d, WAVEFORMATEX.nBlockAlign: %d, WAVEFORMATEX.nAvgBytesPerSec: %ld\n" "Size of dsound circular buffer=>%d\n", spec->info.channels, spec->info.rate, spec->info.bpf, wfx.nSamplesPerSec, wfx.wBitsPerSample, wfx.nBlockAlign, wfx.nAvgBytesPerSec, dsoundsink->buffer_size); /* create a secondary directsound buffer */ memset (&descSecondary, 0, sizeof (DSBUFFERDESC)); descSecondary.dwSize = sizeof (DSBUFFERDESC); descSecondary.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_GLOBALFOCUS; if (!gst_directsound_sink_is_spdif_format (spec)) descSecondary.dwFlags |= DSBCAPS_CTRLVOLUME; descSecondary.dwBufferBytes = dsoundsink->buffer_size; descSecondary.lpwfxFormat = (WAVEFORMATEX *) & wfx; hRes = IDirectSound_CreateSoundBuffer (dsoundsink->pDS, &descSecondary, &dsoundsink->pDSBSecondary, NULL); if (FAILED (hRes)) { GST_ELEMENT_ERROR (dsoundsink, RESOURCE, OPEN_READ, ("gst_directsound_sink_prepare: IDirectSound_CreateSoundBuffer: %s", DXGetErrorString9 (hRes)), (NULL)); return FALSE; } gst_directsound_sink_set_volume (dsoundsink, dsoundsink->volume, FALSE); return TRUE; } static gboolean gst_directsound_sink_unprepare (GstAudioSink * asink) { GstDirectSoundSink *dsoundsink; dsoundsink = GST_DIRECTSOUND_SINK (asink); /* release secondary DirectSound buffer */ if (dsoundsink->pDSBSecondary) { IDirectSoundBuffer_Release (dsoundsink->pDSBSecondary); dsoundsink->pDSBSecondary = NULL; } return TRUE; } static gboolean gst_directsound_sink_close (GstAudioSink * asink) { GstDirectSoundSink *dsoundsink = NULL; dsoundsink = GST_DIRECTSOUND_SINK (asink); /* release DirectSound object */ g_return_val_if_fail (dsoundsink->pDS != NULL, FALSE); IDirectSound_Release (dsoundsink->pDS); dsoundsink->pDS = NULL; gst_caps_replace (&dsoundsink->cached_caps, NULL); return TRUE; } static gint gst_directsound_sink_write (GstAudioSink * asink, gpointer data, guint length) { GstDirectSoundSink *dsoundsink; DWORD dwStatus; HRESULT hRes; LPVOID pLockedBuffer1 = NULL, pLockedBuffer2 = NULL; DWORD dwSizeBuffer1, dwSizeBuffer2; DWORD dwCurrentPlayCursor; dsoundsink = GST_DIRECTSOUND_SINK (asink); GST_DSOUND_LOCK (dsoundsink); /* get current buffer status */ hRes = IDirectSoundBuffer_GetStatus (dsoundsink->pDSBSecondary, &dwStatus); /* get current play cursor position */ hRes = IDirectSoundBuffer_GetCurrentPosition (dsoundsink->pDSBSecondary, &dwCurrentPlayCursor, NULL); if (SUCCEEDED (hRes) && (dwStatus & DSBSTATUS_PLAYING)) { DWORD dwFreeBufferSize; calculate_freesize: /* calculate the free size of the circular buffer */ if (dwCurrentPlayCursor < dsoundsink->current_circular_offset) dwFreeBufferSize = dsoundsink->buffer_size - (dsoundsink->current_circular_offset - dwCurrentPlayCursor); else dwFreeBufferSize = dwCurrentPlayCursor - dsoundsink->current_circular_offset; if (length >= dwFreeBufferSize) { Sleep (100); hRes = IDirectSoundBuffer_GetCurrentPosition (dsoundsink->pDSBSecondary, &dwCurrentPlayCursor, NULL); hRes = IDirectSoundBuffer_GetStatus (dsoundsink->pDSBSecondary, &dwStatus); if (SUCCEEDED (hRes) && (dwStatus & DSBSTATUS_PLAYING)) goto calculate_freesize; else { dsoundsink->first_buffer_after_reset = FALSE; GST_DSOUND_UNLOCK (dsoundsink); return 0; } } } if (dwStatus & DSBSTATUS_BUFFERLOST) { hRes = IDirectSoundBuffer_Restore (dsoundsink->pDSBSecondary); /*need a loop waiting the buffer is restored?? */ dsoundsink->current_circular_offset = 0; } hRes = IDirectSoundBuffer_Lock (dsoundsink->pDSBSecondary, dsoundsink->current_circular_offset, length, &pLockedBuffer1, &dwSizeBuffer1, &pLockedBuffer2, &dwSizeBuffer2, 0L); if (SUCCEEDED (hRes)) { // Write to pointers without reordering. memcpy (pLockedBuffer1, data, dwSizeBuffer1); if (pLockedBuffer2 != NULL) memcpy (pLockedBuffer2, (LPBYTE) data + dwSizeBuffer1, dwSizeBuffer2); // Update where the buffer will lock (for next time) dsoundsink->current_circular_offset += dwSizeBuffer1 + dwSizeBuffer2; dsoundsink->current_circular_offset %= dsoundsink->buffer_size; /* Circular buffer */ hRes = IDirectSoundBuffer_Unlock (dsoundsink->pDSBSecondary, pLockedBuffer1, dwSizeBuffer1, pLockedBuffer2, dwSizeBuffer2); } /* if the buffer was not in playing state yet, call play on the buffer except if this buffer is the fist after a reset (base class call reset and write a buffer when setting the sink to pause) */ if (!(dwStatus & DSBSTATUS_PLAYING) && dsoundsink->first_buffer_after_reset == FALSE) { hRes = IDirectSoundBuffer_Play (dsoundsink->pDSBSecondary, 0, 0, DSBPLAY_LOOPING); } dsoundsink->first_buffer_after_reset = FALSE; GST_DSOUND_UNLOCK (dsoundsink); return length; } static guint gst_directsound_sink_delay (GstAudioSink * asink) { GstDirectSoundSink *dsoundsink; HRESULT hRes; DWORD dwCurrentPlayCursor; DWORD dwBytesInQueue = 0; gint nNbSamplesInQueue = 0; DWORD dwStatus; dsoundsink = GST_DIRECTSOUND_SINK (asink); /* get current buffer status */ hRes = IDirectSoundBuffer_GetStatus (dsoundsink->pDSBSecondary, &dwStatus); if (dwStatus & DSBSTATUS_PLAYING) { /*evaluate the number of samples in queue in the circular buffer */ hRes = IDirectSoundBuffer_GetCurrentPosition (dsoundsink->pDSBSecondary, &dwCurrentPlayCursor, NULL); if (hRes == S_OK) { if (dwCurrentPlayCursor < dsoundsink->current_circular_offset) dwBytesInQueue = dsoundsink->current_circular_offset - dwCurrentPlayCursor; else dwBytesInQueue = dsoundsink->current_circular_offset + (dsoundsink->buffer_size - dwCurrentPlayCursor); nNbSamplesInQueue = dwBytesInQueue / dsoundsink->bytes_per_sample; } } return nNbSamplesInQueue; } static void gst_directsound_sink_reset (GstAudioSink * asink) { GstDirectSoundSink *dsoundsink; LPVOID pLockedBuffer = NULL; DWORD dwSizeBuffer = 0; dsoundsink = GST_DIRECTSOUND_SINK (asink); GST_DSOUND_LOCK (dsoundsink); if (dsoundsink->pDSBSecondary) { /*stop playing */ HRESULT hRes = IDirectSoundBuffer_Stop (dsoundsink->pDSBSecondary); /*reset position */ hRes = IDirectSoundBuffer_SetCurrentPosition (dsoundsink->pDSBSecondary, 0); dsoundsink->current_circular_offset = 0; /*reset the buffer */ hRes = IDirectSoundBuffer_Lock (dsoundsink->pDSBSecondary, dsoundsink->current_circular_offset, dsoundsink->buffer_size, &pLockedBuffer, &dwSizeBuffer, NULL, NULL, 0L); if (SUCCEEDED (hRes)) { memset (pLockedBuffer, 0, dwSizeBuffer); hRes = IDirectSoundBuffer_Unlock (dsoundsink->pDSBSecondary, pLockedBuffer, dwSizeBuffer, NULL, 0); } } dsoundsink->first_buffer_after_reset = TRUE; GST_DSOUND_UNLOCK (dsoundsink); } /* * gst_directsound_probe_supported_formats: * * Takes the template caps and returns the subset which is actually * supported by this device. * */ static GstCaps * gst_directsound_probe_supported_formats (GstDirectSoundSink * dsoundsink, const GstCaps * template_caps) { HRESULT hRes; DSBUFFERDESC descSecondary; WAVEFORMATEX wfx; GstCaps *caps; GstCaps *tmp, *tmp2; LPDIRECTSOUNDBUFFER tmpBuffer; caps = gst_caps_copy (template_caps); /* * Check availability of digital output by trying to create an SPDIF buffer */ #ifdef WAVE_FORMAT_DOLBY_AC3_SPDIF /* fill the WAVEFORMATEX structure with some standard AC3 over SPDIF params */ memset (&wfx, 0, sizeof (wfx)); wfx.cbSize = 0; wfx.wFormatTag = WAVE_FORMAT_DOLBY_AC3_SPDIF; wfx.nChannels = 2; wfx.nSamplesPerSec = 48000; wfx.wBitsPerSample = 16; wfx.nBlockAlign = 4; wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; // create a secondary directsound buffer memset (&descSecondary, 0, sizeof (DSBUFFERDESC)); descSecondary.dwSize = sizeof (DSBUFFERDESC); descSecondary.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_GLOBALFOCUS; descSecondary.dwBufferBytes = 6144; descSecondary.lpwfxFormat = &wfx; hRes = IDirectSound_CreateSoundBuffer (dsoundsink->pDS, &descSecondary, &tmpBuffer, NULL); if (FAILED (hRes)) { GST_INFO_OBJECT (dsoundsink, "AC3 passthrough not supported " "(IDirectSound_CreateSoundBuffer returned: %s)\n", DXGetErrorString9 (hRes)); tmp = gst_caps_new_empty_simple ("audio/x-ac3"); tmp2 = gst_caps_subtract (caps, tmp); gst_caps_unref (tmp); gst_caps_unref (caps); caps = tmp2; tmp = gst_caps_new_empty_simple ("audio/x-dts"); tmp2 = gst_caps_subtract (caps, tmp); gst_caps_unref (tmp); gst_caps_unref (caps); caps = tmp2; } else { GST_INFO_OBJECT (dsoundsink, "AC3 passthrough supported"); hRes = IDirectSoundBuffer_Release (tmpBuffer); if (FAILED (hRes)) { GST_DEBUG_OBJECT (dsoundsink, "(IDirectSoundBuffer_Release returned: %s)\n", DXGetErrorString9 (hRes)); } } #else tmp = gst_caps_new_empty_simple ("audio/x-ac3"); tmp2 = gst_caps_subtract (caps, tmp); gst_caps_unref (tmp); gst_caps_unref (caps); caps = tmp2; tmp = gst_caps_new_empty_simple ("audio/x-dts"); tmp2 = gst_caps_subtract (caps, tmp); gst_caps_unref (tmp); gst_caps_unref (caps); caps = tmp2; #endif return caps; } static GstBuffer * gst_directsound_sink_payload (GstAudioBaseSink * sink, GstBuffer * buf) { if (gst_directsound_sink_is_spdif_format (&sink->ringbuffer->spec)) { gint framesize = gst_audio_iec61937_frame_size (&sink->ringbuffer->spec); GstBuffer *out; GstMapInfo infobuf, infoout; gboolean success; if (framesize <= 0) return NULL; out = gst_buffer_new_and_alloc (framesize); if (!gst_buffer_map (buf, &infobuf, GST_MAP_READWRITE)) { gst_buffer_unref (out); return NULL; } if (!gst_buffer_map (out, &infoout, GST_MAP_READWRITE)) { gst_buffer_unmap (buf, &infobuf); gst_buffer_unref (out); return NULL; } success = gst_audio_iec61937_payload (infobuf.data, infobuf.size, infoout.data, infoout.size, &sink->ringbuffer->spec, G_BYTE_ORDER); if (!success) { gst_buffer_unmap (out, &infoout); gst_buffer_unmap (buf, &infobuf); gst_buffer_unref (out); return NULL; } gst_buffer_copy_into (out, buf, GST_BUFFER_COPY_ALL, 0, -1); /* Fix endianness */ _swab ((gchar *) infoout.data, (gchar *) infoout.data, infobuf.size); gst_buffer_unmap (out, &infoout); gst_buffer_unmap (buf, &infobuf); return out; } else return gst_buffer_ref (buf); } static void gst_directsound_sink_set_volume (GstDirectSoundSink * dsoundsink, gdouble dvolume, gboolean store) { glong volume; volume = dvolume * 100; if (store) dsoundsink->volume = volume; if (dsoundsink->pDSBSecondary) { /* DirectSound controls volume using units of 100th of a decibel, * ranging from -10000 to 0. We use a linear scale of 0 - 100 * here, so remap. */ long dsVolume; if (dsoundsink->volume == 0) dsVolume = -10000; else dsVolume = 100 * (long) (20 * log10 ((double) dsoundsink->volume / 100.)); dsVolume = CLAMP (dsVolume, -10000, 0); GST_DEBUG_OBJECT (dsoundsink, "Setting volume on secondary buffer to %d from %d", (int) dsVolume, (int) dsoundsink->volume); IDirectSoundBuffer_SetVolume (dsoundsink->pDSBSecondary, dsVolume); } } gdouble gst_directsound_sink_get_volume (GstDirectSoundSink * dsoundsink) { return (gdouble) dsoundsink->volume / 100; } static void gst_directsound_sink_set_mute (GstDirectSoundSink * dsoundsink, gboolean mute) { if (mute) gst_directsound_sink_set_volume (dsoundsink, 0, FALSE); else gst_directsound_sink_set_volume (dsoundsink, dsoundsink->volume, FALSE); } static gboolean gst_directsound_sink_get_mute (GstDirectSoundSink * dsoundsink) { return FALSE; } knowthelist-2.3.0/gst/gst.pro0000664000175000017500000000255212423536022015210 0ustar mariomario# # Knowthelist # Copyright (C) 2014 Mario Stephan # License: LGPL-3.0+ # # Patched version of GStreamer sink plugin for Windows to enable selection of audio output device DEFINES += PACKAGE="\\\"knowthelist\\\"" \ VERSION="\\\"1.0\\\"" \ GST_PACKAGE_NAME="\\\"knowthelist\\\"" \ GST_PACKAGE_ORIGIN="\\\"gst-plugins-good\\\"" \ TARGET = libgstdirectsoundsink TEMPLATE = lib CONFIG += dll DESTDIR = $${OUT_PWD}/../ win32 { GST_HOME = $$quote($$(GSTREAMER_1_0_ROOT_X86)) isEmpty(GST_HOME) { message(\"GSTREAMER_1_0_ROOT_X86\" not detected ...) } else { message(\"GSTREAMER_1_0_ROOT_X86\" detected in \"$${GST_HOME}\") } INCLUDEPATH += $${GST_HOME}\include\gstreamer-1.0 \ $${GST_HOME}\include\glib-2.0 \ $${GST_HOME}\lib\glib-2.0\include \ $${GST_HOME}\include \ LIBS += $${GST_HOME}\lib\libgstreamer-1.0.dll.a \ $${GST_HOME}\lib\glib-2.0.lib \ $${GST_HOME}\lib\gobject-2.0.lib \ $${GST_HOME}\lib\libgstaudio-1.0.dll.a \ $${GST_HOME}\lib\libgstbase-1.0.dll.a \ -ldsound \ -lwinmm \ -ldxerr9 \ -lole32 } HEADERS += \ directsound/gstdirectsoundsink.h SOURCES += \ directsound/gstdirectsoundplugin.c \ directsound/gstdirectsoundsink.c knowthelist-2.3.0/locale/0000775000175000017500000000000012423536022014327 5ustar mariomarioknowthelist-2.3.0/locale/knowthelist_fr.ts0000664000175000017500000013500512423536022017745 0ustar mariomario CollectionSetupModel Select folders for music collection Sélectionner les dossiers de votre bibliothèque de musique CollectionTree Artist Artiste Genre Genre Year Année Add to PlayList&1 Ajouter à la liste de lecture&1 Add to PlayList&2 Ajouter à la liste de lecture&2 Re-scan collection Réanalyser la bibliothèque Title Titre Album Album Location Emplacement Meta Information Méta Information CollectionTreeItem All Tous CollectionWidget Random Tracks Pistes aléatoires Enter space-separated terms to filter collection Entrer des termes séparés par des espaces pour filtrer la bibliothèque Core::Internal::FancyTabWidget Large sidebar Grande barre latérale Small sidebar Petite barre latérale Plain sidebar Barre latérale Tabs on top Onglets du haut Icons on top Icônes du haut DjBrowser Add a new AutoDj Ajouter un nouveau AutoDj Add a new record case for current AutoDj Ajouter un nouvel enregistrement à l'AutoDJ courant DjFilterWidget Form Formulaire Record Case Enregistrement <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Lucida Grande'; font-size:13pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt;">count of records which fit to this filter(s)</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt; text-decoration: underline;"></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Lucida Grande'; font-size:13pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt;">nombre d'enregistrements qui correspondent à ce(s) filtre(s)</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt; text-decoration: underline;"></p></body></html> 0 0 1 1 how many records per turn combien d'enregistrements par tour Activate this record case Activer cet enregistrement set set Alt+J Alt+J Count Nombre Remove this record case Supprimer cet enregistrement x x <html><head/><body><p><a href="#"><span style=" text-decoration: underline; color:#e1e1e1;">Path</span></a></p></body></html> <html><head/><body><p><a href="#"><span style=" text-decoration: underline; color:#e1e1e1;">Emplacement</span></a></p></body></html> Genre Genre Artist Artiste <html><head/><body><p>Confirm the remove</p></body></html> <html><head/><body><p>Confirmer la suppression</p></body></html> Delete Supprimer of sur DjSettings Form Formulaire 0 0 DjWidget Form Formulaire AutoDJ AutoDj <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="#"><span style=" font-size:8pt; text-decoration: underline; color:#d0fff8;">DJ Main</span></a></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="#"><span style=" font-size:8pt; text-decoration: underline; color:#d0fff8;">DJ Principal</span></a></p></body></html> Start a session of this DJ Démarrer une session pour ce DJ Remove this DJ Supprimer ce DJ x x TextLabel Texte de l'étiquette <html><head/><body><p>Confirm the remove</p></body></html> <html><head/><body><p>Confirmer la suppression</p></body></html> Delete Supprimer This Dj plays: Ce Dj joue: cases événements case événement tracks pistes hours heures Knowthelist Knowthelist Knowthelist Fader Fondu AutoD&J AutoD&J Alt+J Alt+J Set Set FadeNo&w Fondr&e (Fader) Alt+W Alt+W Gain Volume AGC AGC Low Graves Mid Médiums High Aigus 0:00.0 0:00.0 -0:00.0 -0:00.0 MonitorPlayer Lecteur Audio <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="settings"><span style=" font-size:8pt; color:#df0000;">No 2nd soundcard selected!</span></a></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="settings"><span style=" font-size:8pt; color:#df0000;">Pas de seconde carte son sélectionnée!</span></a></p></body></html> Settings Réglages Collection Bibliothèque AutoDJ AutoDJ Folder Dossier Lists Listes ModeSelector Frame Image View: Artist > Album Vue: Artiste > Album View: Year > Artist > Album Vue: Année > Artiste Album Y A View: Genre > Artist > Album Vue: Genre > Artiste > Album G G PlayerWidget Form Formulaire texttexttextt textetextetexte TextLabel Texte de l'étiquette 00:00 00:00 .00 .00 <html><head/><body><p><span style=" color:#ffffff;">Time remain</span></p></body></html> <html><head/><body><p><span style=" color:#ffffff;">Durée restante</span></p></body></html> -00:00 -00:00 <html><head/><body><p><span style=" color:#ffffff;">Seconds of silence at the end </span></p></body></html> <html><head/><body><p><span style=" color:#ffffff;">Secondes de silence à la fin</span></p></body></html> -00 -00 Jump to the point where the music starts mainly Sauter le blanc du début de la musique Jump to start position Aller à la position de départ Cue CUE Tracks Pistes Track Piste Hours Heures No track Aucune piste Playlist Url Url No Played Joué Artist Artiste Title Titre Album Album Year Année Genre Genre Track Piste Length Durée Rate Note Add to PlayList&1 Ajouter à la liste de lecture&1 Add to PlayList&2 Ajouter à la liste de lecture&2 &Load &Charger Load as &Next Chargement &Suivant &Prelisten Track &Pré-écouter la piste &Search for: '%1' &Rechercher:'%1' &Remove Selected &Supprimer la sélection &Open File Location &Ouvrir l'emplacement du fichier &View Tag Information &Afficher les informations du Tag Location Emplacement Meta Information Méta information PlaylistBrowser Save loaded player lists into a file Sauvegarder dans un fichier les listes de lecture chargées Add a new list and store current tracks Ajouter une nouvelle liste et stocker les pistes en cours Top Tracks Top titres Most played tracks Titres les plus joués Last Tracks Derniers titres Recently played tracks Titres récemment joués Favorites Tracks Titres favoris High rated tracks Titres les mieux notés tracks pistes hours heures Save Play List Sauvegarder la liste de lecture Enter a name for the new list Entrer un nom pour la nouvelle liste Playlists (*.xspf);;All Files (*) Listes de lecture (*.xspf);;Tous les fichiers (*) PlaylistWidget Frame Image Click here to show the content of this list Cliquez ici pour afficher le contenu de cette liste <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="charts"><span style=" font-size:8pt; text-decoration: underline; color:#d0fff8;">Most Played</span></a></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="charts"><span style=" font-size:8pt; text-decoration: underline; color:#d0fff8;">Les plus jouées</span></a></p></body></html> TextLabel Texte de l'étiquette Load all tracks of this list directly into player playlists Charger tous les titres directement dans les listes de lecture Remove this list Supprimer cette liste Remove this playlist Supprimer cette liste de lecture x x <html><head/><body><p>Confirm the remove</p></body></html> <html><head/><body><p>Confirmer la suppression</p></body></html> Delete Supprimer QObject Unable to load database Impossible de charger la base de données This application needs the QT5 SQLITE driver (libqt5-sql-sqlite) Cette application requiert le pilote QT5 SQLite (qt5-database-plugin-sqlite) This application needs the QT4 SQLITE driver (libqt4-sql-sqlite) Cette application requiert le pilote QT4 SQLite (qt4-database-plugin-sqlite) Unknown Inconnu Title Titre Artist Artiste Album Album Genre Genre Year Année Location Emplacement SettingsDialog Settings Réglages New Row Nouvelle Ligne Neue Zeile Nouvelle Ligne New Column Nouvelle Colonne Fader Fondu (Fader) Collection Bibliothèque Audio devices Périphériques Audio AutoDJ AutoDJ Playlists Listes de lecture File browser Explorateur de fichiers Common Général Fader settings Réglages du fondu (Fader) Start fading before song end Commencer le fondu avant la fin du morceau 12s 12s Fader Time Durée du fondu Skip silent at start (AutoCue) Supprimer le silence au démarrage (AutoCue) Skip silent at the end supprimer le silence à la fin Scan for new files and update the music collection Analyser les nouveaux fichiers et mettre à jour la bibliothèque de musique Watch folders for changes Surveiller les changements des dossiers Scan Now Analyser Scan folders for songs Analyser les dossiers pour les chansons Play Counter Statistics Statistiques du nombre de lectures Reset Réinitialiser Monitor Player Carte(s) Son Device Settings Réglages des périphériques AutoDJ settings Réglages de l'AutoDJ Minimum tracks within each playlist Nombre minimum de pistes dans chaque liste de lecture DJ Count Nombre de DJs DJ Names Noms des DJs Filter Count Nombre de filtres Increment play counter for AutoDj selected tracks Incrémenter le compteur de lecture pour les pistes AutoDj sélectionnées Auto Remove Played Tracks Supprimer automatiquement les pistes jouées Playlist Settings Réglages des listes de lecture Playlist Folder Dossier de la liste de lecture ... ... Browser Root Navigateur File Browser Settings Réglages des explorateurs de fichiers Language Langue Common Settings Réglages Général Change the language of the application (needs restart) Changer la langue de l'application (nécessite un redémarrage) About À Propos About Knowthelist À Propos de Knowthelist <h3>Knowthelist</h3><br />Copyright (C) 2005-2014 Mario Stephan <br /><a href='mailto:mstephan@shared-files.de'>mstephan@shared-files.de</a><br /><br /><a href='http://knowthelist.github.io/knowthelist'>http://knowthelist.github.io/knowthelist</a> <h3>Knowthelist</h3><br />Copyright (C) 2005-2014 Mario Stephan <br /><a href='mailto:mstephan@shared-files.de'>mstephan@shared-files.de</a><br /><br /><a href='http://knowthelist.github.io/knowthelist'>http://knowthelist.github.io/knowthelist</a> knowthelist-2.3.0/locale/knowthelist_hu.ts0000664000175000017500000013603412423536022017755 0ustar mariomario CollectionSetupModel Select folders for music collection Válassz mappákat a gyüjteményhez CollectionTree Artist Előadó Genre Műfaj Year Év Add to PlayList&1 &1-es lejátszólistához Add to PlayList&2 &2-es lejátszólistához Re-scan collection Gyüjtemény frissítése Title Cím Album Album Location Hely Meta Information Meta adatok CollectionTreeItem All minden CollectionWidget yy Év Random Tracks Véletlenszerű lejátszás Enter space-separated terms to filter collection Szóközzel elválasztott kifejezések a gyüjtemény szűréséhez Core::Internal::FancyTabWidget Large sidebar Nagy oldalsáv Small sidebar Kis oldalsáv Plain sidebar Egyszerű oldalsáv Tabs on top Lapok felül Icons on top Ikonok felül DjBrowser Add a new AutoDj Add a new record case for current AutoDj DjFilterWidget Form Form 1 1 Record Case Lemezborító Remove this record case x <html><head/><body><p><a href="#"><span style=" text-decoration: underline; color:#e1e1e1;">Path</span></a></p></body></html> <html><head/><body><p><a href="#"><span style=" text-decoration: underline; color:#e1e1e1;">Útvonal</span></a></p></body></html> 0 0 Activate this record case Lemezborító aktiválása set beállítások is over long set Alt+J Alt+J Count Szám <html><head/><body><p>Confirm the remove</p></body></html> Delete töröl how many records per turn Hány felvétel fordulónként Path Útvonal Genre Műfaj Artist Előadó <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Lucida Grande'; font-size:13pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt;">count of records which fit to this filter(s)</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt; text-decoration: underline;"></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Lucida Grande'; font-size:13pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt;">szűrőnek megfelelő felvételek száma</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt; text-decoration: underline;"></p></body></html> ? ? select directory Válassz mappát ^ ^ of a DjSettings Form Form 0 0 DjWidget Form Form AutoDJ AutoDJ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="#"><span style=" font-size:8pt; text-decoration: underline; color:#d0fff8;">DJ Main</span></a></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="#"><span style=" font-size:8pt; text-decoration: underline; color:#d0fff8;">DJ Main</span></a></p></body></html> Start a session of this DJ Remove this DJ x <html><head/><body><p>Confirm the remove</p></body></html> Delete töröl <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="fdadfaf"><span style=" font-size:8pt; text-decoration: underline; color:#d0fff8;">DJ Main</span></a></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="fdadfaf"><span style=" font-size:8pt; text-decoration: underline; color:#d0fff8;">DJ Main</span></a></p></body></html> TextLabel Szövegcimke tracks Sáv hours Óra cases Eset This Dj plays: case Eset Knowthelist Knowthelist Knowthelist Fader Fader AutoD&J AutoD&J Alt+J Alt+J Set Beállítások over long Set FadeNo&w Fade mos&t Alt+W Alt+T Gain Hangerő AGC AGC Low Mély Mid Közepes High Magas MonitorPlayer Lejátszóeszköz 0:00.0 0:00.0 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="settings"><span style=" font-size:8pt; color:#df0000;">No 2nd soundcard selected!</span></a></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="settings"><span style=" font-size:8pt; color:#df0000;">Nincs második hangkártya</span></a></p></body></html> -0:00.0 -0:00.0 Settings Beállítások Collection Gyüjtemény AutoDJ AutoDJ Folder Mappa Lists ModeSelector Frame no need to translate View: Artist > Album látvány: Előadó > Album View: Year > Artist > Album látvány: Év > Előadó > Album Y É View: Genre > Artist > Album látvány: Műfaj > Előadó > Album G M PlayerWidget Form Form texttexttextt TextLabel Szövegcimke 00:00 00:00 <html><head/><body><p><span style=" color:#ffffff;">Time remain</span></p></body></html> Jump to the point where the music starts mainly Cueval Cueval .00 .00 texttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttext texttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttext -00:00 -00:00 <html><head/><body><p><span style=" color:#ffffff;">Seconds of silence at the end </span></p></body></html> -00 -00 Cue Jel Tracks Sáv Track Sáv Hours óra No track Nincs sáv Playlist Trackname Sáv No No Artist Előadó Title Cím Url Played Album Album Year Év Rate Comment Megjegyzés Genre Műfaj Track Sáv Directory Könyvtár Length Hossz Bitrate Bitráta Add to PlayList&1 &1-es lejátszólistához Add to PlayList&2 &2-es lejátszólistához &Load Betö&ltés Load as &Next Betöltés következő&nek &Prelisten Track &Szám előnézet &View Tag Information... &Tag információk... &Search for: '%1' &Keresés erre:'%1' &Remove Selected &Kiválasztott törlése &Open File Location &View Tag Information Location Hely Meta Information Meta adatok PlaylistBrowser Add a new list and store current tracks Top Tracks Most played tracks Last Tracks Recently played tracks Favorites Tracks High rated tracks tracks Sáv hours Óra Save Play List Enter a name for the new list PlaylistWidget Frame Click here to show the content of this list <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="charts"><span style=" font-size:8pt; text-decoration: underline; color:#d0fff8;">Most Played</span></a></p></body></html> TextLabel Szövegcimke Load all tracks of this list directly into player playlists Remove this list x <html><head/><body><p>Confirm the remove</p></body></html> Delete töröl QObject Unable to load database Adatbázis nem tölthető be This application needs the QT5 SQLITE driver (libqt5-sql-sqlite) Ehhez az alkalmazáshoz szükséges a QT4 SQLITE driver (libqt4-sql-sqlite) {5 ?} {5-?} This application needs the QT4 SQLITE driver (libqt4-sql-sqlite) Ehhez az alkalmazáshoz szükséges a QT4 SQLITE driver (libqt4-sql-sqlite) Unknown Title Cím Artist Előadó Album Album Genre Műfaj Year Év Location Hely SettingsDialog Settings Beállítások New Row Új sor Neue Zeile Neue Zeile New Column Új oszlop Fader Fader Collection Gyüjtemény Audio devices Audio eszközök AutoDJ AutoDJ Playlists Lejátszólisták File browser Fájlböngésző Common Fader settings Fader beállítások Start fading before song end Halkítás indítása a szám vége előtt 12s 12s Fader Time Lehalkítás hossza Skip silent at start (AutoCue) Csend kihagyása kezdésnél (AutoCue) Skip silent at the end Csend kihagyása a szám végénél Scan for new files and update the music collection Új fájlok keresése és a gyüjtemény frissítése Watch folders for changes Mappák változásának figyelése Scan Now Keresés most Scan folders for songs Play Counter Statistics Reset Monitor Player Lejátszóeszköz Device Settings AutoDJ settings AutoDJ beállítások Minimum tracks within each playlist Minimum sáv File Browser Settings Language Common Settings Change the language of the application (needs restart) About Minimum Tracks Minimum sáv DJ Count DJ számláló DJ Names DJ név Filter Count szűrő számláló Increment play counter for AutoDj selected tracks Auto Remove Played Tracks Lejátszott sávok automatikus eltávolítása Playlist Settings Lejátszólista beállítások Browser Root Root mappa ... ... About Knowthelist knowthelist-2.3.0/locale/knowthelist_ru.ts0000664000175000017500000012117312423536022017765 0ustar mariomario CollectionSetupModel Select folders for music collection CollectionTree Artist Genre Year Add to PlayList&1 Add to PlayList&2 Re-scan collection Title Album Location Meta Information CollectionTreeItem All CollectionWidget Random Tracks Enter space-separated terms to filter collection Core::Internal::FancyTabWidget Large sidebar Small sidebar Plain sidebar Tabs on top Icons on top DjBrowser Add a new AutoDj Add a new record case for current AutoDj DjFilterWidget Form Record Case <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Lucida Grande'; font-size:13pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt;">count of records which fit to this filter(s)</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt; text-decoration: underline;"></p></body></html> 0 1 how many records per turn Activate this record case set Alt+J Count Remove this record case x <html><head/><body><p><a href="#"><span style=" text-decoration: underline; color:#e1e1e1;">Path</span></a></p></body></html> Genre Artist <html><head/><body><p>Confirm the remove</p></body></html> Delete of DjSettings Form 0 DjWidget Form AutoDJ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="#"><span style=" font-size:8pt; text-decoration: underline; color:#d0fff8;">DJ Main</span></a></p></body></html> Start a session of this DJ Remove this DJ x TextLabel <html><head/><body><p>Confirm the remove</p></body></html> Delete This Dj plays: cases case tracks hours Knowthelist Knowthelist Fader AutoD&J Alt+J Set FadeNo&w Alt+W Gain AGC Low Mid High 0:00.0 -0:00.0 MonitorPlayer <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="settings"><span style=" font-size:8pt; color:#df0000;">No 2nd soundcard selected!</span></a></p></body></html> Settings Collection AutoDJ Folder Lists ModeSelector Frame View: Artist > Album View: Year > Artist > Album Y View: Genre > Artist > Album G PlayerWidget Form texttexttextt TextLabel 00:00 .00 <html><head/><body><p><span style=" color:#ffffff;">Time remain</span></p></body></html> -00:00 <html><head/><body><p><span style=" color:#ffffff;">Seconds of silence at the end </span></p></body></html> -00 Jump to the point where the music starts mainly Tracks Track Hours No track Playlist Url No Played Artist Title Album Year Genre Track Length Rate Add to PlayList&1 Add to PlayList&2 &Load Load as &Next &Prelisten Track &Search for: '%1' &Remove Selected &Open File Location &View Tag Information Location Meta Information PlaylistBrowser Add a new list and store current tracks Top Tracks Most played tracks Last Tracks Recently played tracks Favorites Tracks High rated tracks tracks hours Save Play List Enter a name for the new list PlaylistWidget Frame Click here to show the content of this list <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="charts"><span style=" font-size:8pt; text-decoration: underline; color:#d0fff8;">Most Played</span></a></p></body></html> TextLabel Load all tracks of this list directly into player playlists Remove this list x <html><head/><body><p>Confirm the remove</p></body></html> Delete QObject Unable to load database This application needs the QT5 SQLITE driver (libqt5-sql-sqlite) This application needs the QT4 SQLITE driver (libqt4-sql-sqlite) Unknown Title Artist Album Genre Year Location SettingsDialog Settings Fader Collection Audio devices AutoDJ Playlists File browser Common Fader settings Start fading before song end 12s Fader Time Skip silent at start (AutoCue) Skip silent at the end Scan for new files and update the music collection Watch folders for changes Scan Now Scan folders for songs Play Counter Statistics Reset Monitor Player Device Settings AutoDJ settings Minimum tracks within each playlist DJ Count DJ Names Filter Count Increment play counter for AutoDj selected tracks Auto Remove Played Tracks Playlist Settings ... Browser Root File Browser Settings Language Common Settings Change the language of the application (needs restart) About About Knowthelist knowthelist-2.3.0/locale/knowthelist_it.ts0000664000175000017500000012117312423536022017753 0ustar mariomario CollectionSetupModel Select folders for music collection CollectionTree Artist Genre Year Add to PlayList&1 Add to PlayList&2 Re-scan collection Title Album Location Meta Information CollectionTreeItem All CollectionWidget Random Tracks Enter space-separated terms to filter collection Core::Internal::FancyTabWidget Large sidebar Small sidebar Plain sidebar Tabs on top Icons on top DjBrowser Add a new AutoDj Add a new record case for current AutoDj DjFilterWidget Form Record Case <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Lucida Grande'; font-size:13pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt;">count of records which fit to this filter(s)</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt; text-decoration: underline;"></p></body></html> 0 1 how many records per turn Activate this record case set Alt+J Count Remove this record case x <html><head/><body><p><a href="#"><span style=" text-decoration: underline; color:#e1e1e1;">Path</span></a></p></body></html> Genre Artist <html><head/><body><p>Confirm the remove</p></body></html> Delete of DjSettings Form 0 DjWidget Form AutoDJ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="#"><span style=" font-size:8pt; text-decoration: underline; color:#d0fff8;">DJ Main</span></a></p></body></html> Start a session of this DJ Remove this DJ x TextLabel <html><head/><body><p>Confirm the remove</p></body></html> Delete This Dj plays: cases case tracks hours Knowthelist Knowthelist Fader AutoD&J Alt+J Set FadeNo&w Alt+W Gain AGC Low Mid High 0:00.0 -0:00.0 MonitorPlayer <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="settings"><span style=" font-size:8pt; color:#df0000;">No 2nd soundcard selected!</span></a></p></body></html> Settings Collection AutoDJ Folder Lists ModeSelector Frame View: Artist > Album View: Year > Artist > Album Y View: Genre > Artist > Album G PlayerWidget Form texttexttextt TextLabel 00:00 .00 <html><head/><body><p><span style=" color:#ffffff;">Time remain</span></p></body></html> -00:00 <html><head/><body><p><span style=" color:#ffffff;">Seconds of silence at the end </span></p></body></html> -00 Jump to the point where the music starts mainly Tracks Track Hours No track Playlist Url No Played Artist Title Album Year Genre Track Length Rate Add to PlayList&1 Add to PlayList&2 &Load Load as &Next &Prelisten Track &Search for: '%1' &Remove Selected &Open File Location &View Tag Information Location Meta Information PlaylistBrowser Add a new list and store current tracks Top Tracks Most played tracks Last Tracks Recently played tracks Favorites Tracks High rated tracks tracks hours Save Play List Enter a name for the new list PlaylistWidget Frame Click here to show the content of this list <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="charts"><span style=" font-size:8pt; text-decoration: underline; color:#d0fff8;">Most Played</span></a></p></body></html> TextLabel Load all tracks of this list directly into player playlists Remove this list x <html><head/><body><p>Confirm the remove</p></body></html> Delete QObject Unable to load database This application needs the QT5 SQLITE driver (libqt5-sql-sqlite) This application needs the QT4 SQLITE driver (libqt4-sql-sqlite) Unknown Title Artist Album Genre Year Location SettingsDialog Settings Fader Collection Audio devices AutoDJ Playlists File browser Common Fader settings Start fading before song end 12s Fader Time Skip silent at start (AutoCue) Skip silent at the end Scan for new files and update the music collection Watch folders for changes Scan Now Scan folders for songs Play Counter Statistics Reset Monitor Player Device Settings AutoDJ settings Minimum tracks within each playlist DJ Count DJ Names Filter Count Increment play counter for AutoDj selected tracks Auto Remove Played Tracks Playlist Settings ... Browser Root File Browser Settings Language Common Settings Change the language of the application (needs restart) About About Knowthelist knowthelist-2.3.0/locale/knowthelist_de.ts0000664000175000017500000014126612423536022017734 0ustar mariomario CollectionSetupModel Select folders for music collection Wählen Sie Ordner für Ihre Musik Sammlung CollectionTree Artist Interpret Add to PlayList&1 Zur Abspiellist&1 hinzufügen Add to PlayList&2 Zur Abspiellist&2 hinzufügen Re-scan collection Musiksammlung erneuern Title Title Album Album Genre Genre Year Jahr Location Adresse Meta Information Meta Informationen CollectionTreeItem All Alle CollectionWidget yy rr Random Tracks Zufallstitel Enter space-separated terms to filter collection Geben Sie Suchwörter mit Leerzeichen getrennt ein, um in der Musiksammlung zu suchen Core::Internal::FancyTabWidget Large sidebar Großes Panel Small sidebar Kleines Panel Plain sidebar Flaches Panel Tabs on top Tabs oben Icons on top Icons oben DjBrowser Add a new AutoDj neuen AutoDJ hinzufügen Add a new record case for current AutoDj neuen Plattenkoffer für den aktuellen AutoDJ hinzufügen DjFilterWidget Form Form 1 1 Record Case Plattenkoffer Remove this record case Plattenkoffer entfernen x Do not translate <html><head/><body><p><a href="#"><span style=" text-decoration: underline; color:#e1e1e1;">Path</span></a></p></body></html> <html><head/><body><p><a href="#"><span style=" text-decoration: underline; color:#e1e1e1;">Verzeichnis</span></a></p></body></html> 0 0 Activate this record case Diesen Plattenkoffer nutzen set aktiv Alt+J Alt+J Count Anzahl <html><head/><body><p>Confirm the remove</p></body></html> <html><head/><body><p>Entfernen bestätigen</p></body></html> Delete Löschen how many records per turn Wieviele Titel pro Runde abspielen Path Verzeichnis Genre Genre Artist Interpret <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Lucida Grande'; font-size:13pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt;">count of records which fit to this filter(s)</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt; text-decoration: underline;"></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Lucida Grande'; font-size:13pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt;">Anzahl der Titel, die auf diesen Filter passen</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt; text-decoration: underline;"></p></body></html> ? ? select directory Verzeichnis wählen ^ ^ of von DjSettings Form Form 0 0 DjWidget Form Form AutoDJ AutoDJ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="#"><span style=" font-size:8pt; text-decoration: underline; color:#d0fff8;">DJ Main</span></a></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="#"><span style=" font-size:8pt; text-decoration: underline; color:#d0fff8;">DJ Eins</span></a></p></body></html> Start a session of this DJ Session dieses DJ starten Remove this DJ DJ entfernen x do not translate <html><head/><body><p>Confirm the remove</p></body></html> <html><head/><body><p>Entfernen bestätigen</p></body></html> Delete Löschen <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="fdadfaf"><span style=" font-size:8pt; text-decoration: underline; color:#d0fff8;">DJ Main</span></a></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="fdadfaf"><span style=" font-size:8pt; text-decoration: underline; color:#d0fff8;">DJ Main</span></a></p></body></html> TextLabel TextLabel tracks Songs hours Stunden cases Plattenkoffer This Dj plays: Dieser DJ spielt: case Plattenkoffer Knowthelist Knowthelist Knowthelist Fader Blenden AutoD&J AutoD&J Alt+J Alt+J Set Eins. FadeNo&w Blende jetzt Alt+W Alt+W Gain Verst. AGC AGC Low Tiefen Mid Mitten High Höhen MonitorPlayer Monitor Player 0:00.0 0:00.0 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="settings"><span style=" font-size:8pt; color:#df0000;">No 2nd soundcard selected!</span></a></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="settings"><span style=" font-size:8pt; color:#df0000;">Kein zweites Audiogerät gewählt!</span></a></p></body></html> -0:00.0 -0:00.0 Settings Einstellungen Collection Sammlung AutoDJ AutoDJ Folder Ordner Lists Listen ModeSelector Frame No need to translate View: Artist > Album Ansicht: Artist > Album View: Year > Artist > Album Ansicht: Jahr > Artist > Album Y J View: Genre > Artist > Album Ansicht: Genre > Artist > Album G G PlayerWidget Form Form texttexttextt TextLabel TextLabel 00:00 00:00 <html><head/><body><p><span style=" color:#ffffff;">Time remain</span></p></body></html> <html><head/><body><p><span style=" color:#ffffff;">Verbleibende Zeit</span></p></body></html> <html><head/><body><p><span style=" color:#ffffff;">Seconds of silence at the end </span></p></body></html> <html><head/><body><p><span style=" color:#ffffff;">Sekunden Stille am Ende </span></p></body></html> -00 -00 Jump to the point where the music starts mainly Jump to start position Zur Startposition springen -00:00 -00:00 .00 .00 textLabel1 Textový štítek 1 Cue CUE Tracks Titel Track Titel Hours Stunden No track Kein Titel Playlist Trackname Trackname No Artist Interpret Title Name Url Adresse Played Gespielt Album Album Year Jahr Rate Wertung Comment Kommentar Genre Genre Track Track Directory Verzeichnis Length Dauer Bitrate Datenrate Add to PlayList&1 Zur Abspielliste&1 hinzufügen Add to PlayList&2 Zur Abspielliste&2 hinzufügen &Load &Laden Load as &Next Als &Nächstes laden &Prelisten Track Titel vorhören &View Tag Information... Zeige Titel Info &Search for: '%1' &Suche: '%1' &Remove Selected &Entferne markierte &Open File Location &View Tag Information Location Adresse Meta Information Meta Informationen PlaylistBrowser Save loaded player lists into a file Speichern der Spieler Abspielliste in eine Datei Add a new list and store current tracks Neue Liste anlegen und aktuelle Titel darin speichern Top Tracks Beliebte Lieder Most played tracks Oft gespielte Lieder Last Tracks Zuletzte gespielte Lieder Recently played tracks Zuletzt gespielte Titel Favorites Tracks Favoriten Titel High rated tracks Hoch bewertete Titel tracks Titel hours Stunden Save Play List Playlist speichern Enter a name for the new list Geben Sie einen Namen für die neue Liste an Playlists (*.xspf);;All Files (*) Playlisten (*.xspf);;Alle Dateien (*) PlaylistWidget Frame No need to translate Click here to show the content of this list Hier klicken, um den Inhalt der Liste an zuzeigen <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="charts"><span style=" font-size:8pt; text-decoration: underline; color:#d0fff8;">Most Played</span></a></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="charts"><span style=" font-size:8pt; text-decoration: underline; color:#d0fff8;">Oft gespielt</span></a></p></body></html> TextLabel TextLabel Load all tracks of this list directly into player playlists Alle Titel dieser Liste direkt in die Abspiellisten laden Remove this list Liste entfernen Remove this playlist Liste entfernen x <html><head/><body><p>Confirm the remove</p></body></html> <html><head/><body><p>Entfernen bestätigen</p></body></html> Delete Löschen QObject Unable to load database Datenbank Ladefehler This application needs the QT5 SQLITE driver (libqt5-sql-sqlite) Diese Applikation benötigt QT5 SQLITE (libqt5sql5-sqlite) This application needs the QT4 SQLITE driver (libqt4-sql-sqlite) Diese Applikation benötigt QT4 SQLITE (libqt4-sql-sqlite) Select folders for music collection Wählen Sie die Ordner für Ihre Musik Sammlung Unknown Unbekannt Title Titel Artist Interpret Album Album Genre Genre Year Jahr Location Adresse SettingsDialog Settings Einstellungen Fader Überblender Collection Musiksammlung Audio devices Audiogeräte AutoDJ AutoDJ Playlists Abspiellisten File browser Dateiverzeichnis Common Allgemein Fader settings Überblender Einstellungen Start fading before song end Starte Blende vor Ende 12s 12 s Fader Time Überblenddauer Skip silent at start (AutoCue) Stille am Anfang überspringen (AutoCue) Skip silent at the end Stille am Ende ignorieren Scan for new files and update the music collection Nach neuen Dateien suchen und zur Sammlung hinzufügen Watch folders for changes Veränderungen überwachen Scan Now Jetzt durchsuchen Scan folders for songs Verzeichnisse nach Liedern durchsuchen Play Counter Statistics Zähler für gespielte Titel zurücksetzen Reset Zurücksetzen Monitor Player Monitor Player Device Settings Geräte Einstellungen AutoDJ settings AutoDJ Einstellungen Minimum tracks within each playlist Mindestanzahl Songs pro Plalist File Browser Settings Datei Suche Einstellungen Language Sprache Common Settings Allgemeine Einstellungen Change the language of the application (needs restart) Ändern der Programm-Sprache (nach Neustart) About Über Minimum Tracks Mindestanzahl Titel DJ Count Anzahl DJs DJ Names DJ Namen Filter Count Anzahl Filter Increment play counter for AutoDj selected tracks Zähler für gespielte Titel auch für vom AutoDj gewählte Titel erhöhen Auto Remove Played Tracks Gespielte Titel automatisch entfernen Playlist Settings Einstellungen Abspielliste Playlist Folder Abspiellisten Ordner Browser Root Verzeichnis Start ... ... About Knowthelist Über Knowthelist knowthelist-2.3.0/locale/knowthelist_cs.ts0000664000175000017500000014130412423536022017742 0ustar mariomario CollectionSetupModel Select folders for music collection Vyberte složky pro hudební sbírku CollectionTree Artist Umělec Add to PlayList&1 Přidat do seznamu skladeb &1 Add to PlayList&2 Přidat do seznamu skladeb &2 Re-scan collection Obnovit hudební sbírku Title Název Album Album Genre Žánr Year Rok Location Umístění Meta Information Popisné informace CollectionTreeItem All celek CollectionWidget yy rr Random Tracks Náhodné skladby Enter space-separated terms to filter collection Zadejte mezerou oddělená hledaná slova pro filtrování sbírky Core::Internal::FancyTabWidget Large sidebar Velký postranní panel Small sidebar Malý postranní panel Plain sidebar Prostý postranní panel Tabs on top Karty nahoře Icons on top Ikony nahoře DjBrowser Add a new AutoDj Přidat nového automatického diskžokeje Add a new record case for current AutoDj Přidat nový kufr s deskami pro nynějšího automatického diskžokeje DjFilterWidget Form Formulář 1 1 Record Case Kufr s deskami Remove this record case Odstranit tento kufr s deskami x x <html><head/><body><p><a href="#"><span style=" text-decoration: underline; color:#e1e1e1;">Path</span></a></p></body></html> <html><head/><body><p><a href="#"><span style=" text-decoration: underline; color:#e1e1e1;">Adresář</span></a></p></body></html> 0 0 Activate this record case Použít tento kufr s deskami set set Alt+J Alt+J Count Počet <html><head/><body><p>Confirm the remove</p></body></html> <html><head/><body><p>Potvrdit odstranění</p></body></html> Delete Smazat how many records per turn Kolik nahrávak přehrát v jednom kole Path Adresář Genre Žánr Artist Umělec <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Lucida Grande'; font-size:13pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt;">count of records which fit to this filter(s)</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt; text-decoration: underline;"></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Lucida Grande'; font-size:13pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt;">Počet záznamů odpovídajících filtru (filtrům)</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt; text-decoration: underline;"></p></body></html> ? ? select directory Vybrat adresář ^ ^ of z DjSettings Form Formulář 0 0 DjWidget Form Formulář AutoDJ Diskžokej <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="#"><span style=" font-size:8pt; text-decoration: underline; color:#d0fff8;">DJ Main</span></a></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="#"><span style=" font-size:8pt; text-decoration: underline; color:#d0fff8;">DJ Main</span></a></p></body></html> Start a session of this DJ Zahájení zasedání tohoto diskžokeje Remove this DJ Odstranit tohoto diskžokeje x x <html><head/><body><p>Confirm the remove</p></body></html> <html><head/><body><p>Potvrdit odstranění</p></body></html> Delete Smazat <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="fdadfaf"><span style=" font-size:8pt; text-decoration: underline; color:#d0fff8;">DJ Main</span></a></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="fdadfaf"><span style=" font-size:8pt; text-decoration: underline; color:#d0fff8;">DJ Main</span></a></p></body></html> TextLabel no need to translate Textový štítek tracks skladeb hours hodin cases kufrů This Dj plays: Tento diskžokej hraje: case kufr Knowthelist Knowthelist Knowthelist Fader Prolínač AutoD&J Auto&DJ Alt+J Alt+J Set Nastav FadeNo&w Prolínat nyní Alt+W Alt+W Gain Zesílení AGC AGC Low Basy Mid Středy High Výšky MonitorPlayer Sledování přehrávání 0:00.0 0:00.0 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="settings"><span style=" font-size:8pt; color:#df0000;">No 2nd soundcard selected!</span></a></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="settings"><span style=" font-size:8pt; color:#df0000;">Není vybrána žádná druhá zvuková karta!</span></a></p></body></html> -0:00.0 -0:00.0 Settings Nastavení Collection Sbírka AutoDJ Diskžokej Folder Složka Lists Seznamy ModeSelector Frame no need to translate View: Artist > Album Pohled: Umělec >Alba View: Year > Artist > Album Pohled: Rok > Umělec >Alba Y R View: Genre > Artist > Album Pohled: Žánr > Umělec >Alba G Ž PlayerWidget Form Formulář texttexttextt Text TextLabel Textový štítek 00:00 00:00 <html><head/><body><p><span style=" color:#ffffff;">Time remain</span></p></body></html> <html><head/><body><p><span style=" color:#ffffff;">Zbývající čas</span></p></body></html> <html><head/><body><p><span style=" color:#ffffff;">Seconds of silence at the end </span></p></body></html> <html><head/><body><p><span style=" color:#ffffff;">Ticho na konci vyjádřeno počtem sekund </span></p></body></html> -00 -00 Jump to the point where the music starts mainly Jump to start position Skočit na začáteční polohu texttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttext texttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttext -00:00 -00:00 .00 .00 textLabel1 Textový štítek 1 Cue ZNAČKA Tracks skladeb Track skladba Hours hodin No track Žádná skladba Playlist Trackname Název skladby No Čís Artist Umělec Title Název Url Adresa Played Hráno Album Alba Year Rok Rate Hodnocení Comment Poznámka Genre Žánr Track Skladba Directory Adresář Length Délka Bitrate Datový tok Add to PlayList&1 Přidat do seznamu skladeb &1 Add to PlayList&2 Přidat do seznamu skladeb &2 &Load &Nahrát Load as &Next Nahrát jako &další &Prelisten Track &Slyšet skladbu předem &View Tag Information... &Zobrazit informace o skladbě... &Search for: '%1' &Hledat: '%1' &Remove Selected &Odstranit vybrané &Open File Location Otevřít souborové umístění &View Tag Information &Zobrazit informace o skladbě Location Umístění Meta Information Popisné informace PlaylistBrowser Add a new list and store current tracks Přidat nový seznam a uložit nynější skladby Top Tracks Nejlepší skladby Most played tracks Nejhranější skladby Last Tracks Poslední skladby Recently played tracks Nedávno přehrávané skladby Favorites Tracks Oblíbené skladby High rated tracks Vysoce hodnocené skladby tracks skladeb hours hodin Save Play List Uložit seznam skladeb Enter a name for the new list Zadejte název pro nový seznam PlaylistWidget Frame Rámeček Click here to show the content of this list Klepněte sem pro ukázání obsahu tohoto seznamu <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="charts"><span style=" font-size:8pt; text-decoration: underline; color:#d0fff8;">Most Played</span></a></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="charts"><span style=" font-size:8pt; text-decoration: underline; color:#d0fff8;">Nejhranější</span></a></p></body></html> TextLabel Textový štítek Load all tracks of this list directly into player playlists Nahrát všechny skladby tohoto seznamu přímo do seznamů skladeb přehrávače Remove this list Odstranit tento seznam x x <html><head/><body><p>Confirm the remove</p></body></html> <html><head/><body><p>Potvrdit odstranění</p></body></html> Delete Smazat QObject Unable to load database Nelze nahrát databázi This application needs the QT5 SQLITE driver (libqt5-sql-sqlite) Tento program potřebuje ovladač QT4 SQLITE (libqt4-sql-sqlite) {5 ?} {5-?} This application needs the QT4 SQLITE driver (libqt4-sql-sqlite) Tento program potřebuje ovladač QT4 SQLITE (libqt4-sql-sqlite) Select folders for music collection Vyberte složky pro hudební sbírku Unknown Neznámý Title Název Artist Umělec Album Album Genre Žánr Year Rok Location Umístění SettingsDialog Settings Nastavení New Row Nový řádek Neue Zeile Nový řádek New Column Nový sloupec Fader Prolínač Collection Sbírka Audio devices Zvuková zařízení AutoDJ Diskžokej Playlists Seznamy skladeb File browser Prohlížeč souborů Common Obecné Fader settings Nastavení prolínání Start fading before song end Začít s prolínáním před koncem písně 12s 12 s Fader Time Čas prolínání Skip silent at start (AutoCue) Přeskočit ticho na začátku Skip silent at the end Přeskočit ticho na konci Scan for new files and update the music collection Hledat nové soubory a aktualizovat sbírku Watch folders for changes Sledovat změny ve složkách Scan Now Prohledat nyní Scan folders for songs Hledat písně ve složkách Play Counter Statistics Statistika počítadla přehrávání Reset Vynulovat Monitor Player Přehrávání Device Settings Nastavení zařízení AutoDJ settings Nastavení automatického diskžokeje Minimum tracks within each playlist Nejmenší počet skladeb v každém seznamu skladeb File Browser Settings Nastavení prohlížeče souborů Language Jazyk Common Settings Obecná nastavení Change the language of the application (needs restart) Změnit jazyk aplikace (vyžaduje opětovné spuštění programu) About Program Minimum Tracks Nejmenší počet skladeb DJ Count Počet diskžokejů DJ Names Jména diskžokejů Filter Count Počet filtrů Increment play counter for AutoDj selected tracks Čítač přehrávaných skladeb vybraných automatickým diskžokejem Auto Remove Played Tracks Odstranit přehrané skladby automaticky Playlist Settings Nastavení seznamu skladeb Browser Root Výchozí cesta ... ... About Knowthelist O programu Knowthelist knowthelist-2.3.0/locale/knowthelist_es.ts0000664000175000017500000012117312423536022017746 0ustar mariomario CollectionSetupModel Select folders for music collection CollectionTree Artist Genre Year Add to PlayList&1 Add to PlayList&2 Re-scan collection Title Album Location Meta Information CollectionTreeItem All CollectionWidget Random Tracks Enter space-separated terms to filter collection Core::Internal::FancyTabWidget Large sidebar Small sidebar Plain sidebar Tabs on top Icons on top DjBrowser Add a new AutoDj Add a new record case for current AutoDj DjFilterWidget Form Record Case <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Lucida Grande'; font-size:13pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt;">count of records which fit to this filter(s)</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt; text-decoration: underline;"></p></body></html> 0 1 how many records per turn Activate this record case set Alt+J Count Remove this record case x <html><head/><body><p><a href="#"><span style=" text-decoration: underline; color:#e1e1e1;">Path</span></a></p></body></html> Genre Artist <html><head/><body><p>Confirm the remove</p></body></html> Delete of DjSettings Form 0 DjWidget Form AutoDJ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="#"><span style=" font-size:8pt; text-decoration: underline; color:#d0fff8;">DJ Main</span></a></p></body></html> Start a session of this DJ Remove this DJ x TextLabel <html><head/><body><p>Confirm the remove</p></body></html> Delete This Dj plays: cases case tracks hours Knowthelist Knowthelist Fader AutoD&J Alt+J Set FadeNo&w Alt+W Gain AGC Low Mid High 0:00.0 -0:00.0 MonitorPlayer <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="settings"><span style=" font-size:8pt; color:#df0000;">No 2nd soundcard selected!</span></a></p></body></html> Settings Collection AutoDJ Folder Lists ModeSelector Frame View: Artist > Album View: Year > Artist > Album Y View: Genre > Artist > Album G PlayerWidget Form texttexttextt TextLabel 00:00 .00 <html><head/><body><p><span style=" color:#ffffff;">Time remain</span></p></body></html> -00:00 <html><head/><body><p><span style=" color:#ffffff;">Seconds of silence at the end </span></p></body></html> -00 Jump to the point where the music starts mainly Tracks Track Hours No track Playlist Url No Played Artist Title Album Year Genre Track Length Rate Add to PlayList&1 Add to PlayList&2 &Load Load as &Next &Prelisten Track &Search for: '%1' &Remove Selected &Open File Location &View Tag Information Location Meta Information PlaylistBrowser Add a new list and store current tracks Top Tracks Most played tracks Last Tracks Recently played tracks Favorites Tracks High rated tracks tracks hours Save Play List Enter a name for the new list PlaylistWidget Frame Click here to show the content of this list <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="charts"><span style=" font-size:8pt; text-decoration: underline; color:#d0fff8;">Most Played</span></a></p></body></html> TextLabel Load all tracks of this list directly into player playlists Remove this list x <html><head/><body><p>Confirm the remove</p></body></html> Delete QObject Unable to load database This application needs the QT5 SQLITE driver (libqt5-sql-sqlite) This application needs the QT4 SQLITE driver (libqt4-sql-sqlite) Unknown Title Artist Album Genre Year Location SettingsDialog Settings Fader Collection Audio devices AutoDJ Playlists File browser Common Fader settings Start fading before song end 12s Fader Time Skip silent at start (AutoCue) Skip silent at the end Scan for new files and update the music collection Watch folders for changes Scan Now Scan folders for songs Play Counter Statistics Reset Monitor Player Device Settings AutoDJ settings Minimum tracks within each playlist DJ Count DJ Names Filter Count Increment play counter for AutoDj selected tracks Auto Remove Played Tracks Playlist Settings ... Browser Root File Browser Settings Language Common Settings Change the language of the application (needs restart) About About Knowthelist knowthelist-2.3.0/locale/knowthelist_tr.ts0000664000175000017500000012117312423536022017764 0ustar mariomario CollectionSetupModel Select folders for music collection CollectionTree Artist Genre Year Add to PlayList&1 Add to PlayList&2 Re-scan collection Title Album Location Meta Information CollectionTreeItem All CollectionWidget Random Tracks Enter space-separated terms to filter collection Core::Internal::FancyTabWidget Large sidebar Small sidebar Plain sidebar Tabs on top Icons on top DjBrowser Add a new AutoDj Add a new record case for current AutoDj DjFilterWidget Form Record Case <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Lucida Grande'; font-size:13pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt;">count of records which fit to this filter(s)</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt; text-decoration: underline;"></p></body></html> 0 1 how many records per turn Activate this record case set Alt+J Count Remove this record case x <html><head/><body><p><a href="#"><span style=" text-decoration: underline; color:#e1e1e1;">Path</span></a></p></body></html> Genre Artist <html><head/><body><p>Confirm the remove</p></body></html> Delete of DjSettings Form 0 DjWidget Form AutoDJ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="#"><span style=" font-size:8pt; text-decoration: underline; color:#d0fff8;">DJ Main</span></a></p></body></html> Start a session of this DJ Remove this DJ x TextLabel <html><head/><body><p>Confirm the remove</p></body></html> Delete This Dj plays: cases case tracks hours Knowthelist Knowthelist Fader AutoD&J Alt+J Set FadeNo&w Alt+W Gain AGC Low Mid High 0:00.0 -0:00.0 MonitorPlayer <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="settings"><span style=" font-size:8pt; color:#df0000;">No 2nd soundcard selected!</span></a></p></body></html> Settings Collection AutoDJ Folder Lists ModeSelector Frame View: Artist > Album View: Year > Artist > Album Y View: Genre > Artist > Album G PlayerWidget Form texttexttextt TextLabel 00:00 .00 <html><head/><body><p><span style=" color:#ffffff;">Time remain</span></p></body></html> -00:00 <html><head/><body><p><span style=" color:#ffffff;">Seconds of silence at the end </span></p></body></html> -00 Jump to the point where the music starts mainly Tracks Track Hours No track Playlist Url No Played Artist Title Album Year Genre Track Length Rate Add to PlayList&1 Add to PlayList&2 &Load Load as &Next &Prelisten Track &Search for: '%1' &Remove Selected &Open File Location &View Tag Information Location Meta Information PlaylistBrowser Add a new list and store current tracks Top Tracks Most played tracks Last Tracks Recently played tracks Favorites Tracks High rated tracks tracks hours Save Play List Enter a name for the new list PlaylistWidget Frame Click here to show the content of this list <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="charts"><span style=" font-size:8pt; text-decoration: underline; color:#d0fff8;">Most Played</span></a></p></body></html> TextLabel Load all tracks of this list directly into player playlists Remove this list x <html><head/><body><p>Confirm the remove</p></body></html> Delete QObject Unable to load database This application needs the QT5 SQLITE driver (libqt5-sql-sqlite) This application needs the QT4 SQLITE driver (libqt4-sql-sqlite) Unknown Title Artist Album Genre Year Location SettingsDialog Settings Fader Collection Audio devices AutoDJ Playlists File browser Common Fader settings Start fading before song end 12s Fader Time Skip silent at start (AutoCue) Skip silent at the end Scan for new files and update the music collection Watch folders for changes Scan Now Scan folders for songs Play Counter Statistics Reset Monitor Player Device Settings AutoDJ settings Minimum tracks within each playlist DJ Count DJ Names Filter Count Increment play counter for AutoDj selected tracks Auto Remove Played Tracks Playlist Settings ... Browser Root File Browser Settings Language Common Settings Change the language of the application (needs restart) About About Knowthelist knowthelist-2.3.0/locale/locale.qrc0000664000175000017500000000063012423536022016274 0ustar mariomario knowthelist_cs.qm knowthelist_de.qm knowthelist_hu.qm knowthelist_tr.qm knowthelist_ru.qm knowthelist_nl.qm knowthelist_fr.qm knowthelist_es.qm knowthelist_it.qm knowthelist-2.3.0/locale/knowthelist_nl.ts0000664000175000017500000012117312423536022017750 0ustar mariomario CollectionSetupModel Select folders for music collection CollectionTree Artist Genre Year Add to PlayList&1 Add to PlayList&2 Re-scan collection Title Album Location Meta Information CollectionTreeItem All CollectionWidget Random Tracks Enter space-separated terms to filter collection Core::Internal::FancyTabWidget Large sidebar Small sidebar Plain sidebar Tabs on top Icons on top DjBrowser Add a new AutoDj Add a new record case for current AutoDj DjFilterWidget Form Record Case <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Lucida Grande'; font-size:13pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt;">count of records which fit to this filter(s)</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt; text-decoration: underline;"></p></body></html> 0 1 how many records per turn Activate this record case set Alt+J Count Remove this record case x <html><head/><body><p><a href="#"><span style=" text-decoration: underline; color:#e1e1e1;">Path</span></a></p></body></html> Genre Artist <html><head/><body><p>Confirm the remove</p></body></html> Delete of DjSettings Form 0 DjWidget Form AutoDJ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="#"><span style=" font-size:8pt; text-decoration: underline; color:#d0fff8;">DJ Main</span></a></p></body></html> Start a session of this DJ Remove this DJ x TextLabel <html><head/><body><p>Confirm the remove</p></body></html> Delete This Dj plays: cases case tracks hours Knowthelist Knowthelist Fader AutoD&J Alt+J Set FadeNo&w Alt+W Gain AGC Low Mid High 0:00.0 -0:00.0 MonitorPlayer <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="settings"><span style=" font-size:8pt; color:#df0000;">No 2nd soundcard selected!</span></a></p></body></html> Settings Collection AutoDJ Folder Lists ModeSelector Frame View: Artist > Album View: Year > Artist > Album Y View: Genre > Artist > Album G PlayerWidget Form texttexttextt TextLabel 00:00 .00 <html><head/><body><p><span style=" color:#ffffff;">Time remain</span></p></body></html> -00:00 <html><head/><body><p><span style=" color:#ffffff;">Seconds of silence at the end </span></p></body></html> -00 Jump to the point where the music starts mainly Tracks Track Hours No track Playlist Url No Played Artist Title Album Year Genre Track Length Rate Add to PlayList&1 Add to PlayList&2 &Load Load as &Next &Prelisten Track &Search for: '%1' &Remove Selected &Open File Location &View Tag Information Location Meta Information PlaylistBrowser Add a new list and store current tracks Top Tracks Most played tracks Last Tracks Recently played tracks Favorites Tracks High rated tracks tracks hours Save Play List Enter a name for the new list PlaylistWidget Frame Click here to show the content of this list <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="charts"><span style=" font-size:8pt; text-decoration: underline; color:#d0fff8;">Most Played</span></a></p></body></html> TextLabel Load all tracks of this list directly into player playlists Remove this list x <html><head/><body><p>Confirm the remove</p></body></html> Delete QObject Unable to load database This application needs the QT5 SQLITE driver (libqt5-sql-sqlite) This application needs the QT4 SQLITE driver (libqt4-sql-sqlite) Unknown Title Artist Album Genre Year Location SettingsDialog Settings Fader Collection Audio devices AutoDJ Playlists File browser Common Fader settings Start fading before song end 12s Fader Time Skip silent at start (AutoCue) Skip silent at the end Scan for new files and update the music collection Watch folders for changes Scan Now Scan folders for songs Play Counter Statistics Reset Monitor Player Device Settings AutoDJ settings Minimum tracks within each playlist DJ Count DJ Names Filter Count Increment play counter for AutoDj selected tracks Auto Remove Played Tracks Playlist Settings ... Browser Root File Browser Settings Language Common Settings Change the language of the application (needs restart) About About Knowthelist knowthelist-2.3.0/LICENSE0000664000175000017500000001674312423536022014110 0ustar mariomario GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. knowthelist-2.3.0/README.md0000664000175000017500000001014512423536022014350 0ustar mariomarioknowthelist =========== Knowthelist - the awesome party music player - Easy to use for all party guests - Quick search for tracks in collection - Two players with separate playlists - Mixer with fader, 3 channel EQ and gain - Auto fader and auto gain - Trackanalyser search for song start/end and gain setting - Auto DJ function with multiple filters for random play - Monitor player for pre listen tracks (via 2nd sound card e.g. USB) - ... more details can be found on the [Wiki](https://github.com/knowthelist/knowthelist/wiki) Runs under Linux, MacOS and Windows ![](https://github.com/knowthelist/knowthelist/blob/gh-pages/images/knowthelist_2.2_mac_s.png) Needed packages for building: ------------------ - Qt5 or Qt4 core,gui,xml,sql,widgets (Qt5 only) http://qt-project.org - taglib http://taglib.github.io - gstreamer-1.0 http://gstreamer.freedesktop.org - gstreamer-1.0-plugins-* http://docs.gstreamer.com/display/GstSDK/Home - alsa-devel (Linux only) Build: ---------- - cd ~/src - git clone https://github.com/knowthelist/knowthelist.git - cd knowthelist - qmake (for MacOS: qmake -spec macx-g++) - make - ./knowthelist MacOS X: ---------- Knowthelist works well on MacOS X. * OSX 10.6.8 is tested and known to work It can be compiled to a .app bundle, suitable for placing in /Applications. Compiling is incredibly easy using [Homebrew](http://brew.sh). Just run this command: $ cp ./dist/knowthelist.rb /usr/local/Library/Formula $ brew install knowthelist And you're done. An icon for "knowthelist" should now be in your main OSX Applications list, ready to launch. Windows: ---------- A prebuilt package for windows is available in the release section on this page. The only prerequisite is a installed GStreamer runtime. But if you what to build Knowthelist on Windows for your self, you can do this like this: Build dynamic version to debug project: - Install [gstreamer-x86 runtime & devel](http://gstreamer.freedesktop.org/data/pkg/windows) - Install [Qt5 MinGW incl. QtCreator](http://qt-project.org/downloads) Due to different exception handling versions (SJLJ, DWARF) of used MinGW comiler for GStreamer and Qt5, it is neccessary to use an own version of taglib. To get this, do this: - Get [CMake](http://www.cmake.org/cmake/resources/software.html) and install - Get [taglib](http://taglib.github.io) and unzip - Open CMake GUI, select taglib folder, press Configure and build taglib - Add the taglib bin path (e.g. C:\Program Files (x86)\taglib-1.9.1\bin) to PATH variable into the QtCreator project build enviroment settings - Add the GStreamer bin path (e.g. C:\gstreamer\1.0\x86\bin) to PATH variable into the QtCreator project build enviroment settings - Rename libtag.dll and libstdc++-6.dll in GStreamer bin path to _libtag.dll and _libstdc++-6.dll - Build and run knowthelist project within QtCreator (Ctrl-R) Build static version for release: - Install [gstreamer-x86 runtime & devel](http://gstreamer.freedesktop.org/data/pkg/windows) - Build a [Qt static environment](http://qt-project.org/wiki/How-to-build-a-static-Qt-for-Windows-MinGW) - Build knowthelist via QtCreator (qmake, build release) - Copy all dll files of the gstreamer's bin folder (e.g. C:\gstreamer\1.0\x86\bin) into the target folder together with knowthelist.exe - Copy all dll files of the gstreamer's plugin folder (e.g. C:\gstreamer\1.0\x86\lib\gstreamer-1.0) into an new folder named 'plugin' in parallel to knowthelist.exe. - Run knowthelist.exe Install packages: ----------------- Prebuilt packages for Linux can be found here: http://opendesktop.org/content/show.php/Knowthelist?content=165335 **Debian:** Knowthelist is available in Jessie and sid archive **Ubuntu:** $ sudo add-apt-repository "deb http://ppa.launchpad.net/mstephan-r/ppa/ubuntu trusty main " $ sudo apt update $ sudo apt install knowthelist Versions: ---------- - 2.3 (2014-09): Qt5 compatibility and usage of GStreamer 1.x - 2.2 (2014-08): Support for stored lists - 2.1 (2014-05): First public version; removed qt3support - 2.0 (2011) : Qt-only + gstreamer version for multiple OS support - 1.x (2005) : Only for KDE Linux with arts sound framework