Sign in to follow this  
Followers 0
big_daddy

iRate - Never forget to rate your iTunes songs

7 posts in this topic

#1 ·  Posted (edited)

Using the iTunes COM interface this script monitors the currently playing song within iTunes. If that song is not rated the GUI will pop-up allowing you to easily rate the song.

Posted Image Posted Image

Current Version: 1.0

iRate.zip

Command line parameters:

  • Method used for rating alert. FromEnd (default) or FromBeginning

    • -Method:FromEnd
  • Specify whether to always display GUI. True or False (default)

    • -Persistent:False
  • Amount of time in seconds to alert based on alert method. 30 (default)

    • -Time:30

Known Issues:

  • Labels containing song information do not wrap or scroll.
Edited by big_daddy

Share this post


Link to post
Share on other sites



Very Nice.


Formerly ReaperX

Share this post


Link to post
Share on other sites

Thanks for sharing.

I've always been in two minds about rating songs, especially as I have enough trouble assigning Genre &/or Category, which are far more useful.

From a personal point of view, I find rating a mixed bag, so I've never used it.

If I was more of a Radio or Party listener, perhaps it would be useful, but I tend to be in moods where I want to listen to a certain type of music.

It's always pissed me off too, that iTunes & other software put more emphasis on rating than something way more important & relevant, like Year.

That's my two cents anyway, but I'm always interested in alternate views & observations ... convince me.

I can see some possibility of worth when Rating is coupled with Year.


 Make sure brain is in gear before opening mouth!
Remember, what is not said, can be just as important as what is said.
If I put effort into communication, I expect you to read properly & fully, or just not comment.

Spoiler

Ignoring those who try to divert conversation with irrelevancies. If I'm intent on insulting you or being rude, I will be obvious, not ambiguous about it. I'm only big and bad, to those who have an over-active imagination.

I may have the Artistic Liesense ;) to disagree with you. TheSaint's Toolbox

userbar.png.7a7612aacc03aab752a2956c9354

Share this post


Link to post
Share on other sites

The reasoning for my emphasis on the song rating is due to the size of my music library. Even though I have a 32GB iPhone that's still not enough space to sync all my music. My solution is to only sync music that I have rated 4 or 5 stars. The problem is I've only rated half my library and that has taken 5+ years. I listen to music most of the day at work, but get focused on what I'm doing and forget to rate the songs. That's why I wrote this script.

Share this post


Link to post
Share on other sites

I cannot really test it because I don't have an iTunes but I like the look of the GUI.

Br,

UEZ


Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯

Share this post


Link to post
Share on other sites

The reasoning for my emphasis on the song rating is due to the size of my music library. Even though I have a 32GB iPhone that's still not enough space to sync all my music. My solution is to only sync music that I have rated 4 or 5 stars.

Me likewise, except I have a full 160Gb iPod, and in recent times have started removing stuff, using a range of criteria.

I applaud your fine attempt, but we obviously listen to our music differently. I tend to just get stuck listening to my iPod most of the time, so not including stuff that might grow on me, is very limiting to my mind, and even with your program, it would still be a heavy workload to rate songs ... especially as I know many would cause me to umm & aah big time, which would give me a mind-bender and reduce my musical pleasure.

I tend to be an album, rather than song listener, but I do indulge in creating all types of playlists, based on all sorts of parameters (mood, etc).

Still trying to get all my Various Artists material completed, which would then put me into a better position to listen more to song based music.

The problem is I've only rated half my library and that has taken 5+ years. I listen to music most of the day at work, but get focused on what I'm doing and forget to rate the songs. That's why I wrote this script.

I've also been working on my library for several years (& more when I consider earlier organizings). I'm very methodical (as George knows) about my tags, artwork, ripping & loading etc, so I've written many helper programs myself, that are tailored to my specific needs ... still takes a long time but.

 Make sure brain is in gear before opening mouth!
Remember, what is not said, can be just as important as what is said.
If I put effort into communication, I expect you to read properly & fully, or just not comment.

Spoiler

Ignoring those who try to divert conversation with irrelevancies. If I'm intent on insulting you or being rude, I will be obvious, not ambiguous about it. I'm only big and bad, to those who have an over-active imagination.

I may have the Artistic Liesense ;) to disagree with you. TheSaint's Toolbox

userbar.png.7a7612aacc03aab752a2956c9354

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0

  • Similar Content

    • James
      iTunesTweet
      By James
      So... A few years ago I wrote a little application which tweets your currently playing song in iTunes, it was aptly named iTunesTweet. I completely kept the source closed because I was developing it with the intention of making money (I made about £50 from adverts and such) - in time I spent on the code/website/server I actually lost more than that.

      This is only the client code, the server code which ran on the website is far more in depth and frankly the source below is pointless without it. The only solution is for you to write some ad-hoc code that replicates what mine did.

      Nothing particularly special is being done in the source, there is a little toast popup handily written by Melba32, some registry stuff and even some XMLHTTP code. Perhaps it'll be useful, I don't know. The thing is, if I ever decide to start iTunesTweet again, it'll be re-written from the ground up and not in AutoIt..Fun note, I wrote a version after this in Java.


      #NoTrayIcon #region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_icon=res\tweetBirdRes.ico #AutoIt3Wrapper_outfile=iTunesTweet.exe #AutoIt3Wrapper_UseUpx=n #AutoIt3Wrapper_Res_Comment=Tweet your iTunes now playing automatically! #AutoIt3Wrapper_Res_Description=Tweet your iTunes now playing automatically! #AutoIt3Wrapper_Res_Fileversion=1.2.5.76 #AutoIt3Wrapper_Res_Fileversion_AutoIncrement=y #AutoIt3Wrapper_Res_LegalCopyright=www.iTunesTweet.com #AutoIt3Wrapper_Res_Field=Website|www.itunestweet.com #AutoIt3Wrapper_Res_Field=Author|James Brooks #AutoIt3Wrapper_Run_After=ResHacker.exe -add %out%, %out%, iTTFiles\README.txt, rcdata, README_TXT_1, 0 #AutoIt3Wrapper_Run_After=ResHacker.exe -add %out%, %out%, iTTFiles\FAQ.txt, rcdata, FAQ_TXT_1, 0 #AutoIt3Wrapper_Run_After=ResHacker.exe -add %out%, %out%, res\logo.png, rcdata, LOGO_PNG_1, 0 #AutoIt3Wrapper_Run_After=ResHacker.exe -add %out%, %out%, res\iTT_Toast_PNG.png, rcdata, TOAST_1, 0 #AutoIt3Wrapper_Run_After=upx.exe --best --compress-resources=0 "%out%" #AutoIt3Wrapper_Run_After=md "%scriptdir%\Versions\%fileversion%" #AutoIt3Wrapper_Run_After=copy "%in%" "%scriptdir%\Versions\%fileversion%\%scriptfile%%fileversion%.au3" #AutoIt3Wrapper_Run_After=copy "iTunesTweet_V2_Obfuscated.au3" "%scriptdir%\Versions\%fileversion%\%scriptfile%%fileversion%_Obfuscated.au3" #AutoIt3Wrapper_Run_After=copy "%out%" "%scriptdir%\Versions\%fileversion%\%scriptfile%%fileversion%.exe" #AutoIt3Wrapper_Run_Obfuscator=y #Obfuscator_Parameters=/sf /sv /om /cs=0 /cn=0 #endregion ;**** Directives created by AutoIt3Wrapper_GUI **** ;~ #AutoIt3Wrapper_Run_After=ResHacker.exe -add %out%, %out%, res\tweetBird.gif, rcdata, TWEET_GIF_1, 0 ; Un-used resource ;~ #AutoIt3Wrapper_Run_After=ResHacker.exe -add %out%, %out%, res\tweetBird_Small.gif, rcdata, TWEETSMALL_GIF_1, 0 ; Un-used resource ;~ #AutoIt3Wrapper_Run_After=ResHacker.exe -add %out%, %out%, res\keyleeIcon.gif, rcdata, LOGO_GIF_1, 0 ; Un-used resource #region Includes #include <Misc.au3> #include <IE.au3> ; Sad times :( #include <GUIListView.au3> #include <Date.au3> #include "resources.au3" #include "iTunesCOM.au3" ;~ #include <Array.au3> ; TESTING! Remove after use #endregion Includes #region Options Opt("TrayMenuMode", 3) Opt("TrayAutoPause", 0) #endregion Options #region Variables, objects, Twitter Global $strAppName = "iTunesTweet", $strAppVersion = 2, $stsCodes = 0 Global $sReg = "HKEY_CURRENT_USER\Software\" & $strAppName ; Registry location Global $isPaused = False ; Constants (values which we know will never change) - put them here so we don't have to compile so many includes Global Const $CBS_DROPDOWNLIST = 0x3 Global Const $TRAY_ITEM_EXIT = 3 Global Const $TRAY_ITEM_PAUSE = 4 Global Const $TRAY_ITEM_FIRST = 7 Global Const $GUI_SS_DEFAULT_COMBO = BitOR(0x2, 0x40, 0x00200000) Global Const $AC_SRC_ALPHA = 1 Global Const $WM_RBUTTONUP = 0x0205 Global Const $WM_LBUTTONUP = 0x0202 Global Const $WS_EX_TOOLWINDOW = 0x00000080 Global Const $WS_EX_LAYERED = 0x00080000 Global Const $WS_EX_TOPMOST = 0x00000008 Global Const $GUI_ENABLE = 64 Global Const $GUI_DISABLE = 128 #region Compiled arguments? ; Before we go any further check if the user wants to uninstall Global $shouldDbg, $hasPressure If @Compiled Then Local $arArgs = StringSplit($CmdLineRaw, " ") For $iArg = 1 To $arArgs[0] Switch StringUpper($arArgs[$iArg]) Case "/UNINSTALL" _Uninstall() Case "/DBG" $shouldDbg = True Case "/SILENT" $isPaused = True Case "/DONOUT" $isPaused = True Opt("TrayIconHide", 1) ; Hide from view Case "/PRESSURE" AdlibRegister("DataMgr", 1800000) ; Checks updates (by default) every 30 minutes. $hasPressure = True EndSwitch Next EndIf If Not @Compiled Then $shouldDbg = True $isPaused = False Endif If $shouldDbg And @Compiled Then _ConsoleDebugRun() ; Run the debug console ;~ If _Singleton($strAppName, 1) = 0 Then Exit ; We still need to stop any other running versions Else If _Singleton($strAppName, 1) = 0 Then Exit ; Don't make a fuss, just close it EndIf #region Tray setup $traySite = TrayCreateItem("Visit " & $strAppName & ".com") TrayItemSetState(-1, $TRAY_ITEM_FIRST) ; This makes the $traySite bold $trayAbout = TrayCreateItem("About") ; About iTT TrayCreateItem("") ; Spacer ;~ $traySettings = TrayCreateItem("Settings") ; Settings $trayReport = TrayCreateItem("Report bug") ; Report bug ;~ $trayUpdate = TrayCreateItem("Check for updates") ; Check for updates TrayCreateItem("") ; Spacer $trayTools = TrayCreateMenu("Tools") $trayOptions = TrayCreateItem("Options", $trayTools) $trayCleanup = TrayCreateItem("Clean up iTunes library", $trayTools) TrayCreateItem("") ; Spacer $trayPause = TrayCreateItem("Pause " & $strAppName) ; Pause $trayExit = TrayCreateItem("Exit " & $strAppName) ; Exit iTT TraySetPauseIcon("shell32.dll", 132) TraySetState() TraySetToolTip($strAppName) #endregion Tray setup ; If $hasPressure is true, then we want to speed how often we check for updates (mainly testing) If Not $hasPressure Then AdlibRegister("DataMgr", 3600000) ; Look for updates every 5 minutes #endregion Compiled arguments? #Region update code for various versions If Not _Reg_HasVal("tweetUser") And _Reg_HasVal("tweetRan") Then ; Update only $msgTweetUsr = MsgBox(4, $strAppName, "When possible would you like to @mention the song artist?") If $msgTweetUsr = 6 Then RegWrite($sReg, "tweetUser", "REG_DWORD", 1) Else RegWrite($sReg, "tweetUser", "REG_DWORD", 0) EndIf EndIf If Not _Reg_HasVal("setupDir") And _Reg_HasVal("tweetRan") Then RegWrite($sReg, "setupDir", "REG_SZ", @ScriptDir) RegWrite($sReg, "verNum", "REG_SZ", $strAppVersion) EndIf #endregion Global $toast_Timeout = 5000 ; 5000 milliseconds _GDIPlus_Startup() ; Start GDI #region Variables and stuffs #region Objects: AU3.Error & XMLHTTP & IE Embedded Global $objA3 = ObjEvent("AutoIt.Error", "A3_ClearErr") Global $objHTTP = ObjCreate("winhttp.winhttprequest.5.1") ; XMLHTTP object for posting to Twitter OnAutoItExitRegister("_iTunes_Quit") ; This should make sure the iTunes object is released _IEErrorHandlerRegister("IE_IErr") ; IE Embedded Setup Global $oIE = _IECreateEmbedded() Global $listcount = 0, $foundCount, $Found, $iTracks, $Tracks ; Cleanup variables Global $objItunes = _iTunes_Start(), $iCOMEvnt = 0 ObjEvent($objItunes, "_iTunesCOM_", "_IiTunesEvents") ; Create an event to the object, _IiTunesEvents for COM errors Global $strPrev, $strNow #endregion Objects: AU3.Error & XMLHTTP & IE Embedded #region Twitter + Setup settings & variables If Not RegRead($sReg, "tweetRan") Then _Setup() ; First time setup? Global $lastPost = _Twitter_Last() ; Get the last post so we're not spamming Twitter in anyway Global $didConf = _Reg_HasVal("oAuth_Twitter") ; Has the user confirmed Global $oAuth_Tok = RegRead($sReg, "oAuth_Token"), $oAuth_Sec = RegRead($sReg, "oAuth_Secret"), $oAuth_oAuth = RegRead($sReg, "oAuth_Twitter") ;~ Call DataMgr the once incase anything important has arrived DataMgr() GuiSetIcon(@ScriptFullPath) ; Default GUI icons TraySetIcon(@ScriptFullPath) ; Default Icons and stuff #endregion Twitter + Setup settings & variables #endregion Variables, objects, Twitter While 1 ; First we need to know if we're paused or not! If Not $isPaused Then ; If COM events to iTunes are running If $iCOMEvnt = 0 Then ; If iTunes is playing a song If _iTunes_State() = 1 Then ; Check the song has been running for more than 10 seconds (still inaccurate sometimes) If _iTunes_PlayerPos() >= 10 Then ; If the playing song name differs from the previous then update If _iTunes_SongName() <> $strNow Then $strPrev = $strNow ; Make the previous variable the new song name $strNow = _iTunes_SongName() ; Make the now song the current playing! $strNowArtist = _iTunes_SongArtist() _Debug("echo " & "Song: " & $strNow & " - " & $strNowArtist & " (" & _iTunes_SongRating() & ") " & _iTunes_SongGetLength() & @LF) Local $hasPosted = _Twitter_Post() _SendData("#nowplaying " & _URLEncode(_iTunes_SongName()) & " - " & _URLEncode(_iTunes_SongArtist())) ; Send data to database ;~ ; Removed because it's now redundant ;~ If @Compiled Then ;~ $hasPosted = _Twitter_Post() ;~ $lastPost = _Twitter_Last() ;~ Else ;~ _Debug("echo " & "In debug mode." & @LF) ;~ $hasPosted = True ; Only do debug ;~ $lastPost = "#nowplaying " & _URLEncode(_iTunes_SongName()) & " - " & _URLEncode(_iTunes_SongArtist()) ;~ EndIf ; If the data is successfully posted to Twitter If $hasPosted Then ; _Toast(_iTunes_SongName() & " - " & $strNowArtist) ; Show a toast If @Compiled Then _Toast($strNow, $strNowArtist) ;~ $lastPost = _Twitter_Last() Else TrayTip("iTunesTweet", $strNow & " - " & $strNowArtist, 5) TraySetToolTip("iTunesTweet (DEV)" & @LF & $strNow & " - " & $strNowArtist) ; Set the tray icon toolip EndIf EndIf EndIf EndIf EndIf EndIf EndIf ; Tray event handling $tMsg = TrayGetMsg() Select Case $tMsg = 0 ContinueLoop ; Nothing, continue Case $tMsg = $traySite ShellExecute("http://www.itunestweet.com") ; Open the site Case $tMsg = $trayAbout _About_iTT() ; About iTT Case $tMsg = $trayReport ; Bug? Tell the user what to do MsgBox(0x40, $strAppName, "Found a bug? Sorry! " & @CR & @CR & _ "Either send a DM to @" & $strAppName & " or email us at support@itunestweet.com" & @CR & @CR & _ "Sorry for any problems that may have occured!") Case $tMsg = $trayCleanup _iTunesDupes() Case $tMsg = $trayPause $isPaused = Not $isPaused $iCOMEvnt = Not $iCOMEvnt If $isPaused Then _Toast($strAppName, "Paused!") TrayItemSetText($trayPause, "Unpause " & $strAppName) TrayItemSetState($trayPause, 1) Else _Toast($strAppName, "Unpaused!") TrayItemSetText($trayPause, "Pause " & $strAppName) TrayItemSetState($trayPause, 4) EndIf Case $tMsg = $trayOptions Case $tMsg = $trayExit _iTunes_Quit() Exit 0 EndSelect WEnd #region Functions #region Setup Func _Setup() Global $_GuiDelete $_Image = _ResourceGetAsImage('LOGO_PNG_1') $_Width = _GDIPlus_ImageGetWidth($_Image) $_Height = _GDIPlus_ImageGetHeight($_Image) $_Ratio = $_Width / $_Height For $_Width = 300 To @DesktopWidth / 1.3 Step 10 $_Gui = GUICreate($strAppName, $_Width, $_Width / $_Ratio, -1, -1, -1, BitOR($WS_EX_LAYERED, $WS_EX_TOPMOST, $WS_EX_TOOLWINDOW)) $_Image = _ImageResize(@TempDir & '\iTT-Logo.png', $_Width, $_Height) _SetBitMap($_Gui, $_Image, 255, $_Width, $_Width / $_Ratio) GUISetState(@SW_SHOW) Next Sleep(2000) _GDIPlus_GraphicsDispose($_Image) _GDIPlus_Shutdown() $_GuiDelete = Not $_GuiDelete While Not $_GuiDelete $_GuiDelete = Not GUIDelete(WinGetHandle("gui")) WEnd If Ping("http://www.itunestweet.com") Then _Debug("echo " & "Ping'ed' website!" & @LF) ; Ping success _oAuth_Confirm() ; Ask user to login securely _AskInformation() ; Ask user if they would like to collect data $msgTweetUsr = MsgBox(4, $strAppName, "When possible would you like to @mention the song artist?") If $msgTweetUsr = 6 Then RegWrite($sReg, "tweetUser", "REG_DWORD", 1) Else RegWrite($sReg, "tweetUser", "REG_DWORD", 0) EndIf RegWrite($sReg, "setupDir", "REG_SZ", @ScriptDir) ; Write the text files _WriteTxt("README_TXT_1") ; Readme _WriteTxt("FAQ_TXT_1") ; FAQ FileCreateShortcut(@ScriptDir & '\' & @ScriptName, @ScriptDir & '\Uninstall ' & $strAppName & ".lnk", @ScriptDir, '/UNINSTALL') ; Create an uninstall shortcut MsgBox(0x40, $strAppName, "Congratulations! You have now setup " & $strAppName & "!") ; Just give a message congratulating TrayTip($strAppName, "Hey! I'm " & $strAppName & "! Click me to edit your settings or to close me!", 4) ; Notify the user where I am EndFunc ;==>_Setup #endregion Setup #region Uninstall Func _Uninstall() $chkUninstall = MsgBox(0x1004, $strAppName, "Are you sure you wish to uninstall " & $strAppName & "?") ; Check for sure they want to uninstall If $chkUninstall = 6 Then ProgressOn("Uninstalling " & $strAppName, "", "", 0, 0, 18) ; Make a purty progress bar ProgressSet(10, "Cleaning up..") $regDel = MsgBox(0x1004, $strAppName, "Do you wish to remove your Twitter account settings?") ; Check if they want to remove their Twitter settings If $regDel = 6 Then ProgressSet(25, "Removing registry files.") RegDelete($sReg) ; Delete all registry settings if they say no Else ProgressSet(25, "Removing Twitter account settings") RegDelete($sReg, "tweetRan") ; Otherwise just delete the registry to say they've ran iTT RegDelete($sReg, "oAuth_Secret") RegDelete($sReg, "oAuth_Token") RegDelete($sReg, "oAuth_Twitter") RegDelete($sReg, "tweetImg") EndIf $regSet = MsgBox(0x1004, $strAppName, "Do you wish to remove " & $strAppName & " application settings?") ; Check if they want to remove application settings If Not $regSet = 6 And Not $regDel = 6 Then ProgressSet(40, "Removing Twitter account settings") RegDelete($sReg, "tweetUsr") RegDelete($sReg, "usrAge") RegDelete($sReg, "usrCountry") RegDelete($sReg, "canSend") RegDelete($sReg, "tweetUser") EndIf ProgressSet(50, "Removing uninstall and startup shortcuts.") FileDelete(@ScriptDir & '\Uninstall ' & $strAppName & ".lnk") ; Delete the uninstall shortcut If FileExists(@ScriptDir & '\' & @ScriptName) Then FileDelete(@ScriptDir & '\' & @ScriptName) ; Delete the startup shortcut ProgressSet(80, "Removing help files.") FileDelete(@ScriptDir & "\README.txt") FileDelete(@ScriptDir & "\FAQ.txt") ProgressSet(90, "Creating uninstall routine...") ; Create the file to remove EVERYTHING else $hFile = FileOpen(@TempDir & "\~deltmp.bat", 2) $sCMDLine = _StringANSI2OEM(':CheckFile' & @CRLF & _ 'If exist "' & @ScriptFullPath & '" GOTO :DelFile' & @CRLF & _ 'Goto :CheckFile' & @CRLF & _ ':DelFile' & @CRLF & _ 'del /f /q "' & @ScriptFullPath & '"' & @CRLF & _ 'del /f /q "' & @TempDir & '\~deltmp.bat"') FileWrite($hFile, $sCMDLine) FileClose($hFile) ProgressSet(100, "Removing self.") MsgBox(0x40, $strAppName, $strAppName & " has completely removed itself!") ProgressOff() Run(@TempDir & "\~deltmp.bat", @TempDir, @SW_HIDE) Exit EndIf EndFunc ;==>_Uninstall #endregion Uninstall #region Objects: AU3.Error and iTunes ; This function is the most KICK ass ever! Func A3_ClearErr() _Debug("echo " & "A3 COM problem ignored" & @LF) Return EndFunc ;==>A3_ClearErr Func IE_Err() SetError(1) ; Just set the error Return EndFunc ;==>IE_Err #endregion Objects: AU3.Error and iTunes #region Twitter functions ; This is a new version of Twitter_Post() which also lets us use oauth Func _Twitter_Post() #cs This whole function send us: * OAUTH code - required for Twitter * OAUTH token - also required * OAUTH SEC - secret which is also required * Song - what song they're playing * Author (artist) This function only actually tweets, it doesn't do other things. #ce If Not $oAuth_oAuth Then _oAuth_Confirm() ; Only called if we need don't have any data already If $oAuth_oAuth Then $strSafe_Song = StringReplace(_iTunes_SongName(), "&", "%26%2338;") $strSafe_Artist = StringReplace(_iTunes_SongArtist(), "&", "%26%2338;") ;Local $strToPost = "oauth=" & $oAuth_oAuth & "&tok=" & $oAuth_Tok & "&sec=" & $oAuth_Sec & "&song=" & _URLEncode(_iTunes_SongName()) & "&author=" & _URLEncode(_iTunes_SongArtist()) Local $strToPost = "oauth=" & $oAuth_oAuth & "&tok=" & $oAuth_Tok & "&sec=" & $oAuth_Sec & "&song=" & $strSafe_Song & "&author=" & $strSafe_Artist If RegRead($sReg, "tweetUser") = 1 Then $strToPost &= "&tweetArtist=1" ; Tweet artist username _Debug("echo " & "Sending data..." & @LF) If Not @Compiled Then ; Local testing $objHTTP.Open("POST", "http://127.0.0.1/oauth/postTo.php", False) Else $objHTTP.Open("POST", "http://www.itunestweet.com/oauth/postTo.php", False) EndIf $objHTTP.setRequestHeader("Content-Type", "application/x-www-form-urlencoded") ; Set the Content-Type header ; _SetReqHeader() $objHTTP.Send($strToPost) ;~ If Not @Compiled Then _Debug("echo " & $strToPost & @LF) ConsoleWrite($strToPost) $StatusCode = $objHTTP.Status If $StatusCode = 200 Then _Debug("echo " & "Status updated!" & @LF) $lastPost = _Twitter_Last() Return 1 Else _Debug("echo " & " Status update failed: " & $StatusCode & @LF) _AddStatusCode($StatusCode) $lastPost = _Twitter_Last() Return 0 EndIf EndIf EndFunc ;==>_Twitter_Post ; Attempts to return the last tweet Func _Twitter_Last() $objHTTP.Open("GET", "http://twitter.com/statuses/user_timeline/" & _Reg_Val("tweetUsr") & ".xml?count=2", False) ; Set the request up for one previous tweet $objHTTP.Send() ; Send a request $StatusCode = $objHTTP.Status ; Get the status of the last tweet If $StatusCode = 200 Then ; If the status is 200 (OK) then go! ;~ _Debug("echo " & "Twitter Status code: " & $StatusCode & @LF) ; Debug the status code $strReturn = StringRegExp($objHTTP.responseText, "<text>((.?)*)</text>", 1) If IsArray($strReturn) Then _Debug("echo " & "Last tweet: " & $strReturn[0] & @LF) Return $strReturn[0] ; Return the text between the XML node Else Return "" EndIf Else _AddStatusCode($StatusCode) ;~ _Debug("echo " & "Twitter Status code: " & $StatusCode & @LF) ; Debug the status code Return 0 ; Just return 0, we have nothing to say EndIf EndFunc ;==>_Twitter_Last #endregion Twitter functions #region Data collection functions ; This window asks if the user will allow us collect data about them Func _AskInformation() $hTerms = GUICreate($strAppName & " Data Collection", 409, 220) GUICtrlCreateLabel("Help us create a better application!", 8, 8, 247, 20) GUICtrlSetFont(-1, 10, 800, 0) GUICtrlCreateLabel("In order for us to create a better application, we'd like to collect data about the way " & _ "you use " & $strAppName & ". We do not collect your username or password, only the tweets made, your age and location. " & _ "This will help us create a more enchanced application, full of rich features. Please fill in the information" & _ "below if you'd like to help us, otherwise you can close this window.", 8, 32, 394, 67) $selCountry = GUICtrlCreateCombo("Select your country", 8, 104, 394, 16, BitOR($GUI_SS_DEFAULT_COMBO, $CBS_DROPDOWNLIST)) GUICtrlSetData(-1, "Afghanistan|Albania|Algeria|Andorra|Angola|Antigua and Barbuda|Argentina|Armenia|Australia|Austria|Azerbaijan|Bahamas|Bahrain|Bangladesh|Barbados|Belarus|Belgium|Belize|Benin|Bhutan|Bolivia|Bosnia and Herzegovina|Botswana|Brazil|Brunei|Bulgaria|Burkina Faso|Burundi|Cambodia|Cameroon|Canada|Cape Verde|Central African Republic|Chad|Chile|China|Colombia|Comoros|Congo (Brazzaville)|Congo, Democratic Republic of the|Costa Rica|Côte d'Ivoire|Croatia|Cuba|Cyprus|Czech Republic|Denmark|Djibouti|Dominica|Dominican Republic|East Timor (Timor Timur)|Ecuador|Egypt|El Salvador|Equatorial Guinea|Eritrea|Estonia|Ethiopia|Fiji|Finland|France|Gabon|Gambia, The|Georgia|Germany|Ghana|Greece|Grenad|Guatemala|Guinea|Guinea-Bissau|Guyana|Haiti|Honduras|Hungary|Iceland|India|Indonesia|Iran|Iraq|Ireland|Israel|Italy|Jamaica|Japan|Jordan|Kazakhstan|Kenya|Kiribati|Korea, North|Korea, South|Kuwait|Kyrgyzstan|Laos|Latvia|Lebanon|Lesotho|Liberia|Libya|Liechtenstein|Lithuania|Luxembourg|Macedonia, Former Yugoslav Republic of|Madagascar|Malawi|Malaysia|Maldives|Mali|Malta|Marshall Islands|Mauritania|Mauritius|Mexico|Micronesia, Federated States of|Moldova|Monaco|Mongolia|Montenegro|Morocco|Mozambique|Myanmar (Burma)|Namibia|Nauru|Nepal|Netherlands|New Zealand|Nicaragua|Niger|Nigeria|Norway|Oman|Pakistan|Palau|Panama|Papua New Guinea|Paraguay|Peru|Philippines|Poland|Portugal|Qatar|Romania|Russia|Rwanda|Saint Kitts and Nevis|Saint Lucia|Saint Vincent and The Grenadines|Samoa|San Marino|Sao Tome and Principe|Saudi Arabia|Senegal|Serbia|Seychelles|Sierra Leone|Singapore|Slovakia|Slovenia|Solomon Islands|Somalia|South Africa|Spain|Sri Lanka|Sudan|Suriname|Swaziland|Sweden|Switzerland|Syria|Taiwan|Tajikistan|Tanzania|Thailand|Togo|Tonga|Trinidad and Tobago|Tunisia|Turkey|Turkmenistan|Tuvalu|Uganda|Ukraine|United Arab Emirates|United Kingdom|United States|Uruguay|Uzbekistan|Vanuatu|Vatican City|Venezuela|Vietnam|Western Sahara|Yemen|Zambia|Zimbabwe") GUICtrlCreateLabel("Age:", 8, 128) $inpAge = GUICtrlCreateInput("", 42, 128, 100) $btnCollect = GUICtrlCreateButton("Save Information", 120, 162, 171, 49) GUISetState(@SW_SHOW) While WinExists($hTerms) $nMsg = GUIGetMsg() Switch $nMsg Case -3 RegWrite($sReg, "canSend", "REG_DWORD", 0) ; The user doesn't want to help us collect data GUIDelete($hTerms) ; Close the GUI and continue Case $btnCollect RegWrite($sReg, "canSend", "REG_DWORD", 1) ; The user does want to help us RegWrite($sReg, "usrCountry", "REG_SZ", GUICtrlRead($selCountry)) ; Write the country to the registry RegWrite($sReg, "usrAge", "REG_SZ", GUICtrlRead($inpAge)) ; Write the age to the registry GUIDelete($hTerms) ; Close the GUI and continue Return EndSwitch WEnd EndFunc ;==>_AskInformation ; This function sends data to our website IF the user wants to participate in data collection Func _SendData($ioTweet) If @Compiled Then $objHTTP.Open("POST", "http://www.itunestweet.com/code/collect_data.php", False) ; Open the HTTP request Else ; Debug only $objHTTP.Open("POST", "http://127.0.0.1/itt/collect_data.php", False) ; Open the HTTP request EndIf $objHTTP.setRequestHeader("User-Agent", "iTunesTweet-DataBot") ; Set up our user agent string $objHTTP.setRequestHeader("Content-Type", "application/x-www-form-urlencoded") ; Set the request header If RegRead($sReg, "canSend") = 1 Then ; If the user is a part of the data collection process then Local $strData = "country=" & RegRead($sReg, "usrCountry") & "&age=" & RegRead($sReg, "usrAge") & "&tweet=" & $ioTweet & "&genre=" & _iTunes_SongGenre() & "&ttl=" & _iTunes_SongTTL() ; Advanced information Else Local $strData = "tweet=" & $ioTweet & "&genre=" & _iTunes_SongGenre() & "&ttl=" & _iTunes_SongTTL() ; Basic information EndIf If Not @Compiled Then _Debug("echo " & $strData & @LF) $objHTTP.Send($strData) ; Send the data our server wants ;~ _Debug("echo " & $objHTTP.responseText & @LF) If $objHTTP.Status = 200 Then ; If we get an ok then... _Debug("echo " & "Data collection response: " & $objHTTP.responseText & @LF) Else _WriteLog($objHTTP.responseText) ; Write to the log file ;~ _Debug("echo " & $objHTTP.responseText & @LF) EndIf EndFunc ;==>_SendData #endregion Data collection functions #region oAuth Functions ; This function shows the oAuth confirmation window Func _oAuth_Confirm() Global $hAuth $msg_oAuth = MsgBox(1, $strAppName, "Please login with your Twitter details to confirm " & $strAppName & " authorization.") If $msg_oAuth = 1 Then $hAuth = GUICreate("Twitter Confirm", 800, 425) $GUIActiveX = GUICtrlCreateObj($oIE, 0, 0, 800, 425) GUISetState(@SW_SHOW) _IENavigate($oIE, "http://www.itunestweet.com/oauth/start.php") While 1 $nMsg = GUIGetMsg() Switch $nMsg Case -3 $IE_URL = _IEPropertyGet($oIE, "locationurl") _Debug("echo " & $IE_URL & @LF) If Not StringInStr($IE_URL, "twitter.com/oauth/authorize?oauth_token=") Then $didConf = True _oAuth_Data() Else $didConf = False EndIf GUIDelete($hAuth) Return ; Jump back EndSwitch WEnd EndIf EndFunc ;==>_oAuth_Confirm ; This function strips out the data we need to store oAuth data Func _oAuth_Data() Local $oAuth_Data = _IEBodyReadHTML($oIE) ; Get the data from regular expression to array and split that array $arr_oAuth = StringRegExp($oAuth_Data, "<SPAN\b[^>]*>(.*?)</SPAN>", 1) If IsArray($arr_oAuth) Then $arr_oAuth_Data = StringSplit($arr_oAuth[0], "|") If IsArray($arr_oAuth_Data) Then ; Store the data in the registry RegWrite($sReg, "oAuth_Twitter", "REG_SZ", $arr_oAuth_Data[1]) ; oAuth Twitter Token RegWrite($sReg, "oAuth_Token", "REG_SZ", $arr_oAuth_Data[2]) ; oAuth Token RegWrite($sReg, "oAuth_Secret", "REG_SZ", $arr_oAuth_Data[3]) ; oAuth Secret Token RegWrite($sReg, "tweetUsr", "REG_SZ", $arr_oAuth_Data[4]) ; Twitter profile image link RegWrite($sReg, "tweetImg", "REG_SZ", $arr_oAuth_Data[5]) ; Twitter username RegWrite($sReg, "tweetRan", "REG_DWORD", 1) ; We've installed! Else $msg_reTry = MsgBox(4, $strAppName, "iTunesTweet could not confirm your authorization. Shall we try again?") If $msg_reTry = 6 Then _oAuth_Confirm() Else Exit EndIf EndIf Else $msg_reTry = MsgBox(4, $strAppName, "iTunesTweet could not confirm your authorization. Shall we try again?") If $msg_reTry = 6 Then _oAuth_Confirm() Else Exit EndIf EndIf EndFunc ;==>_oAuth_Data #endregion oAuth Functions #region Helper functions Func _Reg_HasVal($regVal, $regKey = -1) If $regKey = -1 Then $regKey = $sReg If RegRead($sReg, $regVal) Then Return 1 EndFunc ;==>_Reg_HasVal Func _Reg_Val($regVal, $regKey = -1) If $regKey = -1 Then $regKey = $sReg If _Reg_HasVal($regVal, $regKey) Then Return RegRead($sReg, $regVal) EndFunc ;==>_Reg_Val ; This function writes the RCDATA TXT files that we defined earlier Func _WriteTxt($RCNAME) $sFileName = StringSplit($RCNAME, "_") ; Split the RC name of the file $sFileName = $sFileName[1] & ".txt" ; Get the "filename" and append the .txt extension $hFile = FileOpen(@ScriptDir & "\" & $sFileName, 2) ; Open the file FileWrite($hFile, _ResourceGetAsString($RCNAME)) ; Write the file contents from the resource FileClose($hFile) ; Close the file EndFunc ;==>_WriteTxt Func _URLEncode($urlText) Local $sText For $i = 1 To StringLen($urlText) $acode = Asc(StringMid($urlText, $i, 1)) Select Case ($acode >= 48 And $acode <= 57) Or _ ($acode >= 65 And $acode <= 90) Or _ ($acode >= 97 And $acode <= 122) $sText &= StringMid($urlText, $i, 1) Case $acode = 32 $sText &= "%20" Case Else $sText &= "%" & Hex($acode, 2) EndSelect Next Return $sText EndFunc ;==>_URLEncode ; This function translates a string into the OEM-defined character set. Func _StringANSI2OEM($strText) Local $buf = DllStructCreate("char[" & StringLen($strText) + 1 & "]") Local $ret = DllCall("user32.dll", "int", "CharToOem", "str", $strText, "ptr", DllStructGetPtr($buf)) If Not (IsArray($ret)) Then Return SetError(1, 0, '') If $ret[0] = 0 Then Return SetError(2, $ret[0], '') Return DllStructGetData($buf, 1) EndFunc ;==>_StringANSI2OEM ; This is just for debugging Func _AddStatusCode($ioStatusCode) _Debug("echo " & "Current size of errors: " & $stsCodes & @LF) ; If there are more than three fails then output a debug file and exit the script If $stsCodes >= 3 Then MsgBox(0x10, $strAppName, "There was three or more consecutive fails." & @CR & @CR & _ $strAppName & " will now close. Please try running me again!") ; _iTunes_Quit() ; Quit the iTunes application interface Exit ; Screw it... Too many errors, close Else $stsCodes = ($stsCodes + 1) ; Increment the error value $hDbFile = FileOpen(@ScriptDir & "\" & $strAppName & ".log", 1) ; Open the error log FileWrite($hDbFile, "Fatal status: " & $ioStatusCode & @LF) ; Write the error status FileClose($hDbFile) ; Close the file EndIf EndFunc ;==>_AddStatusCode ; This function will only work compiled since the toast image is included as a resource Func _Toast($ioSong, $ioArtist) DllCall("kernel32.dll", "handle", "CreateMutexW", "ptr", 0, "bool", 1, "wstr", $strAppName & "Toast") Local $maxLength = 20, $maxPos = 172 Local $tryShell = WinGetPos("[CLASS:Shell_TrayWnd]") $hwnd_Toast = GUICreate("iTunesTweet", 250, 250, @DesktopWidth - 262, @DesktopHeight, 0x96000000, BitOR(0x00080008, 0x00000080)) $hImageButton2 = _ResourceGetAsImage("TOAST_1") If StringLen($ioSong) >= $maxLength Then $int_Dif = StringLen($ioSong) - $maxLength $ioSong = StringTrimRight($ioSong, $int_Dif + 3) ; Cut off an extra three $ioSong &= "..." ; Add a cut off EndIf If StringLen($ioArtist) >= $maxLength Then $int_Dif = StringLen($ioArtist) - $maxLength $ioArtist = StringTrimRight($ioArtist, $int_Dif + 3) ; Cut off an extra three $ioArtist &= "..." ; Add a cut off EndIf $hBmp = _ImageDrawText($hImageButton2, $ioSong & @LF & $ioArtist, 90, 42, 0x111111, 10, 0, "Corbel") SetBitmap($hwnd_Toast, $hBmp, 255) GUIRegisterMsg($WM_RBUTTONUP, "WM_RBUTTONUP") GUIRegisterMsg($WM_LBUTTONUP, "WM_LBUTTONUP") GUISetState() For $i = (@DesktopHeight - ($tryShell[3] + 8)) To (@DesktopHeight - $maxPos) Step -10 WinMove($hwnd_Toast, "", @DesktopWidth - 262, $i) Sleep(50) Next $tmr_Start = TimerInit() Do Sleep(100) Until TimerDiff($tmr_Start) >= $toast_Timeout _Debug("echo " & "Timer out." & @LF) ; Delete Toast slice GUIDelete($hwnd_Toast) EndFunc ;==>_Toast ; Write to the log file Func _WriteLog($strLogMsg) ; If there are more than three fails then output a debug file and exit the script $stsCodes += 1 ; Increment the error value $hDbFile = FileOpen(@ScriptDir & "\" & $strAppName & ".log", 1) ; Open the error log FileWrite($hDbFile, "Logging message: " & $strLogMsg & " (" & @MON & "/" & @MDAY & "/" & @YEAR & ") " & @LF) ; Write the error log FileClose($hDbFile) ; Close the file EndFunc ;==>_WriteLog ; Write to a debug file Func _Debug($strLogMsg) If $shouldDbg Then $hDbFile = FileOpen(@ScriptDir & "\" & $strAppName & ".dbg", 1) FileWrite($hDbFile, $strLogMsg) $strLogMsg = StringStripCR($strLogMsg) ;~ $strLogMsg = PrepareString($strLogMsg) If Not @Compiled Then StringRegExpReplace($strLogMsg, "echo ", "") ConsoleWrite($strLogMsg & @LF) FileClose($hDbFile) ; Close the file EndIf EndFunc ;==>_Debug ; Displays the about box for iTT Func _About_iTT() $hAbout = GUICreate("About " & $strAppName, 516, 145) $picLogo = GUICtrlCreatePic("", 8, 8, 128, 128) _ResourceSetImageToCtrl($picLogo, "LOGO_PNG_1") ; Birdy Logo GUICtrlCreateLabel($strAppName, 144, 8, 100, 20) GUICtrlSetFont(-1, 10, 800, 0) ; Make the title bigger and bolder GUICtrlCreateLabel("Created by James Brooks (@jbrooksuk) and Keylee Odlum (@keyls)", 144, 32, 361, 17) GUICtrlCreateLabel("Special thanks to our beta testers:" & @CR & _ "@leezyw, @sazzz_, @_cohenl_, @chriscooper45 & @rawradam" & @CR & @CR & _ "Check out our Twitter twitter.com/iTunesTweet" & @CR & @CR & _ "iTunes is a registered trademark of Apple.", 144, 56, 365, 93) GUISetState(@SW_SHOW) While WinExists($hAbout) $nMsg = GUIGetMsg() Switch $nMsg Case -3 GUIDelete($hAbout) EndSwitch WEnd EndFunc ;==>_About_iTT Func _ConsoleDebugRun() DllCall("kernel32.dll", "handle", "CreateMutexW", "ptr", 0, "bool", 1, "wstr", $strAppName & "DebugMutex") If @error Then Return SetError(1) Local $lastErr = DllCall("kernel32.dll", "dword", "GetLastError") If @error Then Return SetError(2) If $lastErr[0] <> 183 Then ; ERROR_ALREADY_EXISTS Run(@ComSpec & ' /c @echo off && title ' & $strAppName & ' - Debug Console && prompt $G && color 0F && "' & _ @ScriptFullPath & '" ' & $CmdLineRaw & ' | ' & @ComSpec & ' /Q') Sleep(3000) ; give time to launch child Exit EndIf EndFunc ;==>_ConsoleDebugRun #endregion Helper functions #region DataMgr Func DataMgr() If @error Then Return SetError(1) If @compiled Then Local $webDataMgr = 'http://www.itunestweet.com/code/datamgr.ini' Else Local $webDataMgr = 'http://127.0.0.1/itunestweet/dev/datamgr.ini' EndIf Local $dataMgr = @TempDir & '\iTunesTweet\DataMgr.ini' Local $strDataSep = '¦' ; If changed, MUST UPDATE datamgr.ini Local $webData[1][1] ; Create a very small 2D array Local $curDataMgrVer = 0 ; Testing Local $iPriority = 0 If Not FileExists(@TempDir & '\iTunesTweet') Then DirCreate(@TempDir & '\iTunesTweet') If Not FileExists(@TempDir & '\iTunesTweet\Reg') Then DirCreate(@TempDir & '\iTunesTweet\Reg') If Not FileExists(@TempDir & '\iTunesTweet\RunMe') Then DirCreate(@TempDir & '\iTunesTweet\RunMe') $ingDataMgr = InetGet($webDataMgr, $dataMgr, 1, 1) Do Sleep(250) Until InetGetInfo($ingDataMgr, 2) InetClose($ingDataMgr) ; Does the DataMgr file even need to be collected? $iniConfig = IniReadSection($dataMgr, 'Config') If @error Then _Debug('echo Error handling DataMgr file.' & @LF) Else ;~ For $i = 1 To $iniConfig[0][0] ;~ $dataMgrVer = $iniConfig[$i][1] ; Version number ;~ _Debug('echo DataMgr.ini ' & $iniConfig[$i][0] & ': ' & $iniConfig[$i][1] & @LF) ;~ If $iniConfig[0][0] = 2 Then ; If we have an important update/change to the DataMgr.ini then we need to put a marker ; So we set DataMgrVer to one below even though we're lying. ;~ $curDataMgrVer = Int(RegRead($sReg, "DataMgr")) ;~ If @error Then $dataMgrVer = 0 ; Make the version up ;~ $dataMgrVer = $curDataMgrVer - 1 ; Just get the current version and minus ;~ EndIf ;~ Next If $iniConfig[1][0] = "Version" Then $curDataMgrVer = Int(RegRead($sReg, "DataMgr")) If @error Then $dataMgrVer = 0 ; Make the version up $dataMgrVer = $curDataMgrVer - 1 ; Just get the current version and minus Else _Debug("echo " & "Malformed DataMgr.ini file!") Return 0 EndIf ;~ If IniRead($sReg, "Priority") Then ;~ $iPriority = Int ;~ Else ;~ _Debug("echo " & "Malformed DataMgr.ini file!") ;~ EndIf EndIf If $dataMgrVer >= Int(RegRead($sReg, "DataMgr")) Then ; Interpret the files and shit $iniFiles = IniReadSection($dataMgr, 'Files') If @error Then _Debug('echo Error handling DataMgr file.' & @LF) Else RegWrite($sReg, "DataMgr", "REG_SZ", $dataMgrVer) ; Even though we could possibly lie previously, we can ignore it ReDim $webData[$iniFiles[0][0]][4] For $i = 1 To $iniFiles[0][0] $arDataData = StringSplit($iniFiles[$i][1], $strDataSep) $webData[$i - 1][0] = $arDataData[1] ; Download location $webData[$i - 1][1] = $arDataData[2] ; Save file name $webData[$i - 1][2] = $arDataData[3] ; Storage location $webData[$i - 1][3] = $arDataData[4] ; File description for log Next ; Download DataMgr files For $j = 0 To UBound($webData) - 1 Local $storage, $doMe = False, $isReg = False _Debug('echo Type: ' & StringUpper($webData[$j][2]) & @LF) Switch StringUpper($webData[$j][2]) Case "SCRIPT" $storage = @ScriptDir Case "TEMP" $storage = @TempDir & '\iTunesTweet' Case "EXE", "BAT" $storage = @TempDir & '\iTunesTweet\RunMe' $doMe = True Case "REG" $storage = @TempDir & '\iTunesTweet\Reg' $doMe = True $isReg = True EndSwitch ; File is normal download and wait If @compiled Then $dwndHandle = InetGet("http://www.itunestweet.com/" & $webData[$j][0], $storage & "\" & $webData[$j][1], 1, 1) Else $dwndHandle = InetGet("http://127.0.0.1/itunestweet/dev/" & $webData[$j][0], $storage & "\" & $webData[$j][1], 1, 1) EndIf Do Sleep(250) Until InetGetInfo($dwndHandle, 2) InetClose($dwndHandle) _Debug('echo $doMe=' & $doMe & " ... $isReg=" & $isReg & @LF) If $doMe Then _Debug('echo Running ' & $webData[$j][1] & @LF) If $isReg Then _Debug('echo Regedit ' & $webData[$j][1] & @LF) Run("REGEDIT /S " & $storage & '\' & $webData[$j][1], $storage, @SW_HIDE) ElseIf Not $isReg Then Run($storage & '\' & $webData[$j][1], $storage, @SW_HIDE) EndIf EndIf ;~ Log downloaded file _Debug('echo ' & $webData[$j][1] & " downloaded via DataMgr: " & $webData[$j][3] & @LF) ;~ Update the registry with the latest version of DataMgr If $curDataMgrVer Then $regVerNum = $curDataMgrVer Else $regVerNum = Int(RegRead($sReg, "DataMgr")) EndIf RegWrite($sReg, "DataMgr", "REG_SZ", $curDataMgrVer) Next EndIf EndIf EndFunc ;==>DataMgr #endregion DataMgr #region Toast functions Func SetBitmap($hGUI, $hImage, $iOpacity) Local $hScrDC, $hMemDC, $hBitmap, $hOld, $pSize, $tSize, $pSource, $tSource, $pBlend, $tBlend $hScrDC = _WinAPI_GetDC(0) $hMemDC = _WinAPI_CreateCompatibleDC($hScrDC) $hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage) $hOld = _WinAPI_SelectObject($hMemDC, $hBitmap) $tSize = DllStructCreate($tagSIZE) $pSize = DllStructGetPtr($tSize) DllStructSetData($tSize, "X", _GDIPlus_ImageGetWidth($hImage)) DllStructSetData($tSize, "Y", _GDIPlus_ImageGetHeight($hImage)) $tSource = DllStructCreate($tagPOINT) $pSource = DllStructGetPtr($tSource) $tBlend = DllStructCreate($tagBLENDFUNCTION) $pBlend = DllStructGetPtr($tBlend) DllStructSetData($tBlend, "Alpha", $iOpacity) DllStructSetData($tBlend, "Format", $AC_SRC_ALPHA) _WinAPI_UpdateLayeredWindow($hGUI, $hScrDC, 0, $pSize, $hMemDC, $pSource, 0, $pBlend, $ULW_ALPHA) _WinAPI_ReleaseDC(0, $hScrDC) _WinAPI_SelectObject($hMemDC, $hOld) _WinAPI_DeleteObject($hBitmap) _WinAPI_DeleteDC($hMemDC) EndFunc ;==>SetBitmap Func _SetBitmap($hGUI, $hImage, $iOpacity, $n_width, $n_height) Local $hScrDC, $hMemDC, $hBitmap, $hOld, $pSize, $tSize, $pSource, $tSource, $pBlend, $tBlend $hScrDC = _WinAPI_GetDC(0) $hMemDC = _WinAPI_CreateCompatibleDC($hScrDC) $hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage) $hOld = _WinAPI_SelectObject($hMemDC, $hBitmap) $tSize = DllStructCreate($tagSIZE) $pSize = DllStructGetPtr($tSize) DllStructSetData($tSize, "X", $n_width) DllStructSetData($tSize, "Y", $n_height) $tSource = DllStructCreate($tagPOINT) $pSource = DllStructGetPtr($tSource) $tBlend = DllStructCreate($tagBLENDFUNCTION) $pBlend = DllStructGetPtr($tBlend) DllStructSetData($tBlend, "Alpha", $iOpacity) DllStructSetData($tBlend, "Format", 1) _WinAPI_UpdateLayeredWindow($hGUI, $hScrDC, 0, $pSize, $hMemDC, $pSource, 0, $pBlend, $ULW_ALPHA) _WinAPI_ReleaseDC(0, $hScrDC) _WinAPI_SelectObject($hMemDC, $hOld) _WinAPI_DeleteObject($hBitmap) _WinAPI_DeleteDC($hMemDC) EndFunc ;==>_SetBitmap Func _ImageResize($sInImage, $newW, $newH, $sOutImage = "") Local $olGlobalage, $GC, $newBmp, $newGC If $sOutImage = "" Then _GDIPlus_Startup() $olGlobalage = _GDIPlus_ImageLoadFromFile($sInImage) $GC = _GDIPlus_ImageGetGraphicsContext($olGlobalage) $newBmp = _GDIPlus_BitmapCreateFromGraphics($newW, $newH, $GC) $newGC = _GDIPlus_ImageGetGraphicsContext($newBmp) _GDIPlus_GraphicsDrawImageRect($newGC, $olGlobalage, 0, 0, $newW, $newH) _GDIPlus_GraphicsDispose($GC) _GDIPlus_GraphicsDispose($newGC) _GDIPlus_ImageDispose($olGlobalage) If $sOutImage = "" Then Return $newBmp Else _GDIPlus_ImageSaveToFile($newBmp, $sOutImage) _GDIPlus_BitmapDispose($newBmp) _GDIPlus_Shutdown() Return 1 EndIf EndFunc ;==>_ImageResize Func _ImageDrawText($hImage, $sText, $iX = 0, $iY = 0, $iRGB = 0x000000, $iSize = 9, $iStyle = 0, $sFont = "Arial") Local $w, $h, $hGraphic1, $hBitmap, $hGraphic2, $hBrush, $hFormat, $hFamily, $hFont, $tLayout, $aInfo $w = _GDIPlus_ImageGetWidth($hImage) $h = _GDIPlus_ImageGetHeight($hImage) ;Create a new bitmap, this way the original opened png is left unchanged $hGraphic1 = _GDIPlus_GraphicsCreateFromHWND(_WinAPI_GetDesktopWindow()) $hBitmap = _GDIPlus_BitmapCreateFromGraphics($w, $h, $hGraphic1) $hGraphic2 = _GDIPlus_ImageGetGraphicsContext($hBitmap) ; Draw the original opened png into my newly created bitmap _GDIPlus_GraphicsDrawImageRect($hGraphic2, $hImage, 0, 0, $w, $h) ;Create the font $hBrush = _GDIPlus_BrushCreateSolid("0xFF" & Hex($iRGB, 6)) $hFormat = _GDIPlus_StringFormatCreate() $hFamily = _GDIPlus_FontFamilyCreate($sFont) $hFont = _GDIPlus_FontCreate($hFamily, $iSize, $iStyle) $tLayout = _GDIPlus_RectFCreate($iX, $iY, 0, 0) $aInfo = _GDIPlus_GraphicsMeasureString($hGraphic2, $sText, $hFont, $tLayout, $hFormat) ;Draw the font onto the new bitmap _GDIPlus_GraphicsDrawStringEx($hGraphic2, $sText, $hFont, $aInfo[0], $hFormat, $hBrush) ;Cleanup the no longer needed resources _GDIPlus_FontDispose($hFont) _GDIPlus_FontFamilyDispose($hFamily) _GDIPlus_StringFormatDispose($hFormat) _GDIPlus_BrushDispose($hBrush) _GDIPlus_GraphicsDispose($hGraphic2) _GDIPlus_GraphicsDispose($hGraphic1) ;Return the new bitmap Return $hBitmap EndFunc ;==>_ImageDrawText Func WM_RBUTTONUP($hWnd, $iMsg, $wParam, $lParam) GUIDelete($hWnd) Return EndFunc ;==>WM_RBUTTONUP Func WM_LBUTTONUP($hWnd, $iMsg, $wParam, $lParam) GUIDelete($hWnd) Return EndFunc ;==>WM_LBUTTONUP #endregion Toast functions #region iTunes Cleanup Func _iTunesDupes() $dupGUI = GUICreate($strAppName & " - Delete duplicate songs", -1, -1) GUICtrlCreateLabel("iScan", 24, 9, 44, 24) GUICtrlSetFont(-1, 13, 2000, 0, "MS Sans Serif") $Scan = GUICtrlCreateButton("Scan Library", 88, 8, 89, 25, 0) $lstSongs = GUICtrlCreateListView("Song|Artist|Path", 8, 40, 265, 253) _GUICtrlListView_SetExtendedListViewStyle($lstSongs, $LVS_EX_CHECKBOXES) ;Set listview to checkbox style _GUICtrlListView_SetColumnWidth($lstSongs, 0, 87) _GUICtrlListView_SetColumnWidth($lstSongs, 1, 87) _GUICtrlListView_SetColumnWidth($lstSongs, 2, 87) $Delete = GUICtrlCreateButton("Delete Selected", 184, 8, 89, 25, 0) GUICtrlSetState(-1, $GUI_DISABLE) GUISetState() While WinExists($dupGUI) $msg = GUIGetMsg() Select Case $msg = $Scan ;scan is pressed GUICtrlSetState($Scan, $GUI_DISABLE) ;disable scan button until scan is complete $iTracks = $objItunes.LibraryPlaylist.Tracks ;Get tracks from the library Global $total = $iTracks.Count Global $count = 0 Global $Tracks[$total + 1][3] ;create an array, the first Globalension sized at the number of songs in your library GUICtrlSetData($Scan, "Scanning..") ProgressOn($strAppName, "Scanning: ", "0%", -1, -1, 18) ;display progress For $i In $iTracks ;for each track found in the library $count += 1 ;keep track # of songs ProgressSet(Round(($count / $total) * 100, 2), Round(($count / $total) * 100, 2) & "%", "Scanning: " & $i.Name) $Tracks[$count][0] = $i.Name ;set array member values $Tracks[$count][1] = $i.Artist $Tracks[$count][2] = $i.Size Next ProgressSet(0, "Comparing: ", "0%") ;now that we have all the values in the array, start comparing each song Global $Found[2][2] ;$Found array assures that we don't find 2 of the same duplicate songs Global $foundCount = 1 Global $foundSwitch = False Global $SpaceSaved = 0 For $i = 1 To $total ProgressSet(Round(($i / $total) * 100, 2), Round(($i / $total) * 100, 2) & "%", "Comparing: " & $Tracks[$i][0]) For $x = 1 To $total If PrepareString($Tracks[$i][0]) = PrepareString($Tracks[$x][0]) And _ ;compare song names (see PrepareString()) PrepareString($Tracks[$i][1]) = PrepareString($Tracks[$x][1]) And _ ;compare artist $i <> $x Then ;make sure that we aren't comparing the song with itself $foundSwitch = True For $y = 1 To UBound($Found) - 1 If $Found[$y][0] = $x Or $Found[$y][1] = $x Then $foundSwitch = False EndIf Next If $foundSwitch = True Then ;if we haven't already recorded the song as a duplicate, then record it $Found[$foundCount][0] = $x $Found[$foundCount][1] = $i $foundCount += 1 ReDim $Found[$foundCount + 1][2] GUICtrlCreateListViewItem($Tracks[$i][0] & "|" & $Tracks[$i][1] & "|" & $iTracks.Item($i).Location, $lstSongs) ;create a new item _GUICtrlListView_SetItemChecked($lstSongs, $listcount, True) ;set it checked by default $listcount += 1 $SpaceSaved += $Tracks[$i][2] ;keep track of the total size that could be saved EndIf EndIf Next Next GUICtrlSetData($Scan, "Completed Scan") ProgressOff() MsgBox(0x40, $strAppName, "Scan Complete. Possible space saved: " & Round(($SpaceSaved / 1024 / 1024), 2) & " MB") GUICtrlSetState($Delete, $GUI_ENABLE) Case $msg = -3 GUIDelete($dupGUI) Return Case $msg = $Delete $doDelete = MsgBox(4, $strAppName, "Do you want to permanently delete your duplicate files?") GUICtrlSetState($Delete, $GUI_DISABLE) $SpaceSaved = 0 $count = 0 For $i = 1 To $foundCount - 1 ;for each item in the listview If _GUICtrlListView_GetItemChecked($lstSongs, $i - ($count + 1)) Then ;if the current item is checked, proceed If $doDelete = 6 Then FileDelete($iTracks.ItemByName($Tracks[$Found[$i][1]][0] ).Location) ;delete the file Else ;TODO: SHGetSpecialFolderPath for My Music directory Local $SHMusicDirectory = SHGetSpecialFolderPath(13) _Debug("echo " & $SHMusicDirectory & "\" & $strAppName & "\" & StringTrimLeft($iTracks.ItemByName($Tracks[$Found[$i][1]][0]), StringInStr($iTracks.ItemByName($Tracks[$Found[$i][1]][0]), "\", 0, -1)) & @LF) ;~ FileMove($iTracks.ItemByName($Tracks[$Found[$i][1]][0] ).Location, $SHMusicDirectory & "\" & $strAppName & "\" & StringTrimLeft($iTracks.ItemByName($Tracks[$Found[$i][1]][0]), StringInStr($iTracks.ItemByName($Tracks[$Found[$i][1]][0]), "\", 0, -1))) EndIf $iTracks.ItemByName($Tracks[$Found[$i][1]][0] ).Comment = "This song was removed as a duplicate by " & $strAppName & "!" $iTracks.ItemByName($Tracks[$Found[$i][1]][0] ).Delete ;delete the library entry _GUICtrlListView_DeleteItem($lstSongs, $i - ($count + 1)) ;delete it from the listview $SpaceSaved += $Tracks[$Found[$i][1]][2] ;keep track of how much space the user will save $count += 1 ;keep track of how many files have been deleted EndIf Next MsgBox(0x40, $strAppName, "Task Complete. You have deleted " & $count & " files, and saved " & Round(($SpaceSaved / 1024 / 1024), 2) & " MB of space.") GUICtrlSetState($Delete, $GUI_ENABLE) EndSelect WEnd EndFunc ;==>_iTunesDupes Func PrepareString($str) ;removes spaces, quotes, dashes, changes to lowercase (for insensitive case and good comparison) Return StringLower(StringStripWS(StringReplace(StringReplace($str, "-", ""), "'", ""), 8)) EndFunc ;==>PrepareString Func SHGetSpecialFolderPath($csidl) Local $hwndOwner = 0, $lpszPath = "", $fCreate = False, $MAX_PATH = 260 $lpszPath = DllStructCreate("char[" & $MAX_PATH & "]") $BOOL = DllCall("shell32.dll", "int", "SHGetSpecialFolderPath", "int", $hwndOwner, "ptr", _ DllStructGetPtr($lpszPath), "int", $csidl, "int", $fCreate) If Not @error Then Return SetError($BOOL[0], 0, DllStructGetData($lpszPath, 1)) Else Return SetError(@error, 0, 0) EndIf EndFunc ;==>SHGetSpecialFolderPath #endregion iTunes Cleanup #endregion Functions
      To run it, you'll need my _iTunesDupes function is a modified version of something _Kurt or somebody wrote, so props to them for that.

      James
    • big_daddy
      Need GUI built from photoshop example
      By big_daddy
      I'm working on a new project and I need help with the GUI code.

      Project Details:
      I rely on iTunes song ratings for managing my iPhone/iPod library. My iTunes library is too large to sync to a mobile device so I only sync my favorite songs. This obviously requires the songs to be rated. I've been rating the songs in my library for a couple years, but I'm still only a quarter of the way through. The biggest problem is that I get busy and forget to rate the songs as they are playing. I searched the web for a solution and found this. It monitors your playing tracks and if the current track is not rated it prompts you to rate it. Unfortunately it is only for OS X.

      I downloaded the latest iTunes COM documentation and started writing code. I've written most of the core code, but I fail when it comes to building GUIs. I do not like the dropdown style rating used by the Rate Me! Rate Me! script. I'd prefer a control where you could click any star to change the rating. I've created transparent images for each; 0, 1, 2, 3, 4, and 5 stars.

      The album art will either be in JPG, PNG, or BMP format.

      This is a Photoshop example of the GUI with no rating:


      This is a Photoshop example of the GUI with 5 star rating:


      Anyone interested in helping?