AppleScriptによるMusic Player(再掲)

下記で公開したスクリプトの改善版です。

AppleScriptによるMusic… - Apple コミュニティ


主な改善点は以下の通り。

1.(ローカルの)Musicライブラリ内のテキスト検索ができるようにしました。

検索条件をテキストで入力します。(*をAND、+をORとして条件判定します)

例えば、”ショスタコービッチの交響曲第5番「革命」の第4楽章とショパンのエチュード「革命」”を再生したい場合、

検索テキストに”ショスタコ*5番*4楽章+ショパン*エチュード*革命”のように、*と+でキーワードを連結して入力します。


2.ミニプレーヤーの表示切り替えができるようにしました。


3.その他、ロジックを改善しました。


コメントの文字数が5,000文字までという制限がありますので、

ソースコードはこのコメントに対する返信として3分割して掲載します。

利用の際は、3つのコードを連結してください。



投稿日 2022/07/14 21:23

返信
スレッドに付いたマーク ランキングトップの返信

投稿日 2022/07/15 05:33

一部に誤りがありましたので訂正します。


(誤り箇所)

ソースコード その1

>誤

			set mSearchText to do shell script "sed 's/^ *//' <<< " & quoted form of mSearchText --先頭の空白を削除
			set mSearchText to do shell script "sed 's/* $//' <<< " & quoted form of mSearchText --末尾の空白を削除


>正

			set mSearchText to do shell script "sed -e 's/ / /g' <<< " & quoted form of mSearchText --すべてのの全角スペースを半角スペースに置換
			set mSearchText to do shell script "sed -e 's/^ *//' <<< " & quoted form of mSearchText --先頭の半角スペースを削除
			set mSearchText to do shell script "sed -e 's/ *$//' <<< " & quoted form of mSearchText --末尾の半角スペースを削除


※ sedコマンドについて、いろいろ調べましたがなかなか難しくて解釈が誤っていました、(汗)


返信: 21
スレッドに付いたマーク ランキングトップの返信

2022/07/15 05:33 Pajerow への返信

一部に誤りがありましたので訂正します。


(誤り箇所)

ソースコード その1

>誤

			set mSearchText to do shell script "sed 's/^ *//' <<< " & quoted form of mSearchText --先頭の空白を削除
			set mSearchText to do shell script "sed 's/* $//' <<< " & quoted form of mSearchText --末尾の空白を削除


>正

			set mSearchText to do shell script "sed -e 's/ / /g' <<< " & quoted form of mSearchText --すべてのの全角スペースを半角スペースに置換
			set mSearchText to do shell script "sed -e 's/^ *//' <<< " & quoted form of mSearchText --先頭の半角スペースを削除
			set mSearchText to do shell script "sed -e 's/ *$//' <<< " & quoted form of mSearchText --末尾の半角スペースを削除


※ sedコマンドについて、いろいろ調べましたがなかなか難しくて解釈が誤っていました、(汗)


2022/07/16 14:03 Pajerow への返信

「検索」機能における弱点についての考察。


例えば、DREAM COME TRUEの"LOVE LOVE LOVE"という曲を再生したい場合、

検索キーワードに”LOVE LOVE LOVE"と指定すると単語"LOVE"を含む他の曲までヒットしてしまい絞り込みができません。


これを解決する方法は?

・曲情報の「読みがな」に"LOVELOVELOVE"(空白なし)と設定しておく。

・検索キーワードに"LOVELOVELOVE"(空白なし)を入力する。


上記方法は、本スクリプトのようなAppleScriptのSearch命令では有効に機能します、(読みがなを含めたすべての情報を検索することが可能なため)

しかし、Musicアプリ本体の「検索」機能でキーワードに"LOVELOVELOVE"と入力してもヒットしません。(読みがなは検索してくれないため)


2022/07/17 03:22 Pajerow への返信

Pajerow さん、こんばんは。このボードの仕様変更のせい?で、勝手にニックネームを変えられた Hiro__S (旧 Hiro.S) です。モチベーションだだ下がり。愚痴ってすみません...。


さて、automator コマンドでは -i オプションで Automator ワークフローに引数を渡せますが、「ミュージック項目を検索」アクションの入力欄には変数を指定できないようで、引数を受け取ることができません。つまり、AppleScript (検索条件の入力)-> Automator(検索条件の受け取り)はできません。


Automator (検索条件の入力と、database ID の取得) -> AppleScript (database ID の受け取りとその後の処理) はできるので、Alfred からはアプリケーションを起動するのみとし、その後表示される「ミュージック項目を検索」に検索語句を入力するしかないと思います。



Parallels Desktop 上の Monterey の Music.app に2000曲登録して AppleScript の do shell script から automator コマンドにより「ミュージック項目を検索」を実行したところ、速度面では特に問題なさそうです。この速度はちょっと魅力的かもしれません。

2022/08/01 05:10 Pajerow への返信

ええと、本題から微妙に逸れてしまって申し訳ないのですが...、気になる点があるので一応指摘しておきますね。


ASCII character と ASCII number は Leopard で deprecated になりました。Big Sur でも Monterey でもエラーにならないので間違いではないのでしょうが、もうそろそろ使わない方が良いと思います。後継は character id と id。


StandardAdditions より


ASCII character integer
This command is deprecated; use ‘character id …’.


ASCII number text
This command is deprecated; use ‘id …’.


空白文字については、tab、linefeed、return、space といった定数を使うのも良いかと。


ASCII character 9 : character id 9 : tab
ASCII character 10 : character id 10 : linefeed
ASCII character 13 : character id 13 : return
ASCII character 32 : character id 32 : space


2022/08/17 14:10 Pajerow への返信

以下の通り、スクリプトを変更しました。


1. テキスト検索に自作ルーチンを採用。

AppleScript標準のSearch命令では検索できない曲があるため。

例えば、曲名"Love Love Love"や"Sweet Sweet Sweet"など(共にドリカムの曲)が絞り込み検索できない。

"Love"あるいは"Sweet"を含む曲がすべて検索されてしまう。

AppleScriptによるMusic… - Apple コミュニティ


2. ミニプレーヤー切り替え機能を削除。

ミニプレーヤーへの切り替えは外出しの別途スクリプトで行うこととした。

macOS「ミュージック」アプリでのミ… - Apple コミュニティ


3.スクリプトコードから日本語(全角文字)を完全排除。

ここのコミュニティに「追加テキスト」としてコードを登録した際に、全角文字がすべて文字化けしてしまうため。

ダイアログやコメントをすべて英語化しているため、少しわかりにくくなってしまいました。

コメントの「追加テキスト」で日本語を文… - Apple コミュニティ


追記)

今、気づきましたが、「追加テキスト」ではダブルクォーテーション(")やクォーテーション(')の文字もおかしくなりますね。

ちょっとこれでは「追加テキスト」も使い物にならないなぁ...


2022/07/16 19:44 Pajerow への返信

>これを解決する方法は?

自前で検索ルーチンを作ってみました。


以下、テスト用スクリプトと実行結果です。

set mPlaylist to "ライブラリ"
set mSearchText to "LOVE LOVE LOVE"

--カスタム検索ルーチン
set sTime to (current date)

set mSearchTracks to my TextSearchCustom(mSearchText, mPlaylist)

set eTime to (current date)
set mMessage1 to "カスタム  ヒット件数:" & (count of mSearchTracks) & "  処理時間:" & eTime - sTime & "秒"


--オリジナル検索(Search命令)
set sTime to (current date)

set mSearchTracks to my TextSearchOriginal(mSearchText, mPlaylist)

set eTime to (current date)
set mMessage2 to "オリジナル ヒット件数:" & (count of mSearchTracks) & "  処理時間:" & eTime - sTime & "秒"

display dialog "検索テキスト:" & mSearchText & (ASCII character (10)) & mMessage1 & (ASCII character (10)) & mMessage2



-- テキスト検索 in Library (Custom 検索ルーチン)
on TextSearchCustom(mText, mPlaylist)
	tell application "Music"
		set mTracks to {}
		set mLibraryTracks to every track of playlist (mPlaylist)
		repeat with i in mLibraryTracks
			set mProperties to properties of i
			if (mText is in mProperties's name) or ¬
				(mText is in mProperties's artist) or ¬
				(mText is in mProperties's album artist) or ¬
				(mText is in mProperties's album) or ¬
				(mText is in mProperties's genre) or ¬
				(mText is in mProperties's composer) or ¬
				(mText is in mProperties's lyrics) or ¬
				(mText is in mProperties's sort name) or ¬
				(mText is in mProperties's sort album) or ¬
				(mText is in mProperties's sort composer) or ¬
				(mText is in mProperties's sort album artist) or ¬
				(mText is in mProperties's comment) then
				set end of mTracks to i
			end if
		end repeat
		quit
	end tell
	return mTracks
end TextSearchCustom

-- テキスト検索 in Library (Original Search命令)
on TextSearchOriginal(mText, mPlaylist)
	tell application "Music"
		set mTracks to (search playlist (mPlaylist) for mText)
		quit
	end tell
	return mTracks
end TextSearchOriginal

処理速度については、さすがに「Search」命令とは雲泥の差がありますが、

自前の検索ルーチンでみごとに”LOVE LOVE LOVE」の検索に成功しました。


ちょっと処理時間の差が大きすぎるので、本体スクリプトへの組み込みは止めておこうと思います。


※ テスト環境のライブラリ内曲数は、約3,800曲です。

2022/08/17 15:28 Pajerow への返信

ソースコード その4

-- List Sorting
on SortOfList(my_list)
	set index_list to {}
	set sorted_list to {}
	repeat (my_list's length) times
		set low_item to "*"
		repeat with i from 1 to (my_list's length)
			if i is not in index_list then
				set this_item to (my_list's item i) as string
				if low_item is "*" then
					set low_item to this_item
					set low_item_index to i
				else if this_item comes before low_item then
					set low_item to this_item
					set low_item_index to i
				end if
			end if
		end repeat
		set end of sorted_list to low_item
		set end of index_list to low_item_index
	end repeat
	return the sorted_list
end SortOfList


-- HH:MM:SS to Seconds
on TimeToSeconds(hhmmss)
	set hh to (hhmmss's text from character 1 to character 2) as integer
	set mm to (hhmmss's text from character 4 to character 5) as integer
	set ss to (hhmmss's text from character 7 to character 8) as integer
	return (hh * hours + mm * minutes + ss)
end TimeToSeconds


-- Seconds to HH:MM:SS
on SecondsToTime(ssNum)
	set hhStr to my ZeroPadding((ssNum div hours) as string, 2)
	set mmStr to my ZeroPadding((ssNum mod hours div minutes) as string, 2)
	set ssStr to my ZeroPadding((ssNum mod hours mod minutes) as string, 2)
	return hhStr & ":" & mmStr & ":" & ssStr
end SecondsToTime


-- ゼロパディング
on ZeroPadding(aNum, aLen)
	do shell script "printf '%0" & aLen & "d' " & aNum
end ZeroPadding


-- 文字列分割
on devText(theText, aDelimiter)
	set tmp to AppleScript's text item delimiters
	set AppleScript's text item delimiters to aDelimiter
	set theList to theText's every text item
	set AppleScript's text item delimiters to tmp
	return theList
end devText


-- 全角半角変換:先頭と最後のスペース削除
on RepAndTrim(str)
	do shell script "osascript -l JavaScript <<'EOF' - " & str's quoted form & "
'use strict';
function run(argv) {
    return argv[0].replace(/\\uFF0A/g, '*').replace(/\\uFF0B/g, '+').replace(/\\u3000/g, ' ').trim();
}
EOF"
end RepAndTrim


-- カスタムテキスト検索
on TextSearch(mPlaylist, mText)
	tell application "Music"
		set mTracks to playlist (mPlaylist)'s every file track whose ¬
			name contains mText or ¬
			artist contains mText or ¬
			album contains mText or ¬
			album artist contains mText or ¬
			genre contains mText or ¬
			sort name contains mText or ¬
			sort artist contains mText or ¬
			sort album contains mText or ¬
			sort album artist contains mText
		--composer contains mText or ¬
		--sort composer contains mText or ¬
		--lyrics contains mText or ¬
		--comment contains mText or ¬
		return mTracks
	end tell
end TextSearch



2022/07/16 17:58 Pajerow への返信

sed による文字列の置き換え部分についてですが、(もし問題ないのであれば)下記のように一回だけにしてはどうでしょうか?


set mSearchText to my func(" Love*Love*Love    ")

on func(str)
    do shell script "osascript -l JavaScript <<'EOF' - " & str's quoted form & "
'use strict';
function run(argv) {
    return argv[0].replace(/*/g, '*').replace(/+/g, '+').replace(/\\u3000/g, ' ').trim();
}
EOF"
end func


追記: コードを修正しました。

2022/07/16 23:42 Pajerow への返信

”正規表現”について調べてみましたが、あらゆる場所で使われているんですね。


シェルスクリプトだったら sed、awk、grep で正規表現が使えますし、Perl、Python、Ruby、PHP などでもよく使います。


AppleScript は do shell script 経由でこれらを使うことができますし、AppleScript Objective-C なら Objective-C の正規表現が使えます。超便利。


検索ルーチン


Automator の「ミュージックトラックを検索」アクションを AppleScript から実行して、database ID を取得するとか。database ID から Music.app のトラックオブジェクトを取得するのに時間がかかるのでかえって遅くなるかもしれませんが、、、一応、ご参考まで。



Automator - AppleScript を実行

on run {argv}
    if argv is {} then return

    set database_id_list to {}
    tell application "Music"
        repeat with i in argv
            set end of database_id_list to i's database ID
        end repeat
    end tell
    return database_id_list
end run


AppleScript - Automator ワークフローファイルは適当な場所に置いてください。

set ary to run script (do shell script "automator ~/Desktop/a1.workflow")


2022/07/17 04:45 Hiro__S への返信

Hiro__Sさん、こんばんわ。


>「ミュージック項目を検索」アクションの入力欄には変数を指定できないようで、引数を受け取ることができません。

やはりそうでしたか。


>この速度はちょっと魅力的かもしれません。

なんですけどね。


せっかくご提案いただきましたがAutomatorの利用は諦めます。

AppleScriptのSearch命令でも結構速いようなので、このままでいこうかと思います。

このSearch命令での不都合は、"LOVE LOVE LOVE"のような特殊なものだけなので、試した限りではほとんどの場合問題なさそうです。


下記スクリーンショットはAlfredの入力画面とMusicミニプレーヤの再生画面(合成)ですが、このような連携処理の作り込みが可能です。

(現在、Alfredワークフローにどっぷりとハマってしまってまして、購入額の分は充分に償却できています。非常に面白いです)



Alfredワークフローの設定画面(ショートカットが満載...)



2022/08/17 15:25 Pajerow への返信

「追加テキスト」が使えないことになったので、もう一度ここにソースコードを貼付。


ソースコード その1


-- ダイアログ表示用:タイトル:改行:タブ
set mTitle to me's name
set mLF to linefeed
set mTB to tab

-- テキスト検索時プレイリスト選択ダイアログ:表示スイッチ
set mSearchPlaylist to true

-- 1アイテム選択ダイアログ:表示スイッチ
set mOneItem to true

-- シャッフル選択ダイアログ:表示スイッチ:シャッフルパターン:最小曲数
set mShuffle to true
set mShuffleList to {"曲", "アルバム"}
set mShuffleMinimum to 2

-- タイマー選択ダイアログ:表示スイッチ:タイマーパターン:監視間隔秒数
set mTimer to true
set mTimerList to {"00:05:00", "00:15:00", "00:30:00", "01:00:00", "01:30:00", "02:00:00"}
set mTimerDelay to 5


try
	tell application "Music"
		
		delay 0.5
		-- ウィンドウ名
		set mMusicWindow to name of browser window 1
		
		-- プレイリスト名
		set mLibraryPlaylist to name of library playlist 1
		set mMusicPlaylist to name of user playlist 1
		set mMyPlaylist to "Music Player"
		set mSearchResult to "Search Result"
		set mSearchResult1 to "Search Result1"
		set mSearchResult2 to "Search Result2"
		set mExcludePlaylist to {mMusicPlaylist, "Alfred Playlist"}
		
		
		-- アプリケーション起動:メインウィンドウ非表示
		activate
		--set (window mMusicWindow)'s collapsed to true
		
		
		-- 検索テキスト入力:キャンセルで処理停止
		display dialog "検索テキストを入力:                       ( *:AND , +:OR )" default answer "" with title mTitle buttons {"Cancel", "OK"} default button 2
		set mSearchText to result's text returned
		set mSearchText to my RepAndTrim(mSearchText)
		
		
		-- プレイリスト選択:未選択でライブラリ全体:キャンセルで処理停止
		if ((count mSearchText) is 0) or mSearchPlaylist then
			set mList to {}
			repeat with i in ((every playlist's name) as list)
				if ((count playlist (i)'s tracks) > 0) and (not (mExcludePlaylist contains playlist (i)'s name)) then set mList's end to i
			end repeat
			set mChoose to choose from list mList with title mTitle with prompt "検索するプレイリストを選択:" cancel button name "Cancel" with multiple selections allowed
			if mChoose is false then error number -128
			if (count mChoose) is 0 then set mChoose to {mLibraryPlaylist}
		else
			set mChoose to {mLibraryPlaylist}
		end if
		
		
		-- テキスト検索実行
		if (count mSearchText) is not 0 then
			if mSearchResult is not in ((every playlist's name) as list) then set mSearchTrack to make new playlist with properties {name:mSearchResult}
			set mSearchTrack to playlist (mSearchResult)
			delete mSearchTrack's every track
			set mSearchTrack1 to make new playlist with properties {name:mSearchResult1}
			set mSearchTrack2 to make new playlist with properties {name:mSearchResult2}
			set mList to my devText(mSearchText, "+")
			repeat with h in mChoose
				repeat with i in mList
					set mList1 to my devText(i, "*")
					set mPlaylist to h
					set mText to (mList1's item 1) as string
					set mTracks to my TextSearch(mPlaylist, mText)
					repeat with j in mTracks
						duplicate j to mSearchTrack1
					end repeat
					if (count mList1) > 1 then
						set mList1 to mList1's rest
						repeat with j in mList1
							set mPlaylist to mSearchResult1
							set mText to j as string
							set mTracks to my TextSearch(mPlaylist, mText)
							repeat with k in mTracks
								duplicate k to mSearchTrack2
							end repeat
							delete mSearchTrack1's tracks
							duplicate mSearchTrack2's tracks to mSearchTrack1
							delete mSearchTrack2's tracks
						end repeat
					end if
					duplicate mSearchTrack1's tracks to mSearchTrack
				end repeat
			end repeat
			delete playlist (mSearchResult1)
			delete playlist (mSearchResult2)
			set mChoose to {mSearchResult}
		end if
		
		
		-- 重複トラックを除外:トラック情報取得:トラックなしで終了
		set mID to {}
		set mList to {}
		set mListGenre to {}
		set mListArtist to {}
		set mListAlbum to {}
		repeat with i in mChoose
			repeat with j in playlist (i)'s tracks
				tell j
					if database ID is not in mID then
						set mID's end to database ID
						if genre is not in mListGenre then set mListGenre's end to genre as string
						if artist is not in mListArtist then set mListArtist's end to artist as string
						if album is not in mListAlbum then set mListAlbum's end to album as string
					end if
				end tell
			end repeat
		end repeat
		if mSearchResult is in ((every playlist's name) as list) then delete playlist (mSearchResult)
		if (count mID) is 0 then error number -129
		set mPrompt to "検索テキスト : " & mSearchText & mLF & mLF & "ヒット件数 : " & mLF & (count mListGenre) & mTB & "ジャンル" & mLF & (count mListArtist) & mTB & "アーティスト" & mLF & (count mListAlbum) & mTB & "アルバム" & mLF & (count mID) & mTB & "トラック" & mLF
		set mList to mListGenre
		
					

2022/07/14 21:25 Pajerow への返信

ソースコード その2

		-- 曲数判定:複数曲シャッフル選択
		set shuffle enabled to false
		set mSeconds to mPlayTrack's duration
		set mCount to count mPlayTrack's track
		if mCount > 1 then
			set mChoose to choose from list mShuffle with title mMyName with prompt ("シャッフル再生をしますか? ( " & mCount & " 曲)") as text with empty selection allowed
			if (mChoose is not false) and ((count of mChoose) is not 0) then
				if mChoose is {"曲"} then set shuffle mode to songs
				if mChoose is {"アルバム"} then set shuffle mode to albums
				set shuffle enabled to true
			end if
		end if
		
		-- 再生時間選択
		set song repeat to off
		set mList to mTimer
		if mSeconds is 0 then
			set mChoose to choose from list mList with title mMyName with prompt "再生時間を選択してください。"
			if mChoose is false then error number -128
			set mSeconds to my TimeToSeconds(mChoose as string)
		else
			set mDuration to mSeconds
			set mChoose to choose from list mList with title mMyName with prompt ("再生時間を選択しますか? ( " & mCount & " 曲)       未選択で全曲を再生............" & my SecondsToTime(mDuration)) as text with empty selection allowed
			if (mChoose is not false) and ((count of mChoose) is not 0) then
				set mSeconds to my TimeToSeconds(mChoose as string)
				if mSeconds > mDuration then set song repeat to all
			end if
		end if
		
		-- ミニプレーヤー切替
		try
			set mMiniPlayer to false
			display dialog "ミニプレーヤーに切り替えますか?" buttons {"はい", "いいえ"} default button 1 cancel button 2 with title mMyName giving up after 5
			set button_returned to button returned of result
			if button_returned is not "いいえ" then set mMiniPlayer to true
		end try
		
		if mMiniPlayer then
			activate
			delay 1
			tell application "System Events"
				keystroke "m" using {shift down, command down}
				delay 1
				--tell process "Music"'s front window to set focused of radio group 1's radio button 1 to true
				tell process "Music"'s window "ミニプレーヤー" to set focused of radio group 1's radio button "次に再生" to true
			end tell
		end if
		
		-- 再生開始
		play playlist mMyPlaylist
		set mOldTrack to current track
		if not mMiniPlayer then reveal mOldTrack
		
		-- 再生時間監視ループ
		set mStartTime to my (current date)
		set mEndTime to mStartTime + mSeconds
		set mNowTime to mStartTime
		repeat while mNowTime < mEndTime
			with timeout of (30 * 60) seconds -- タイムアウト30分
				if player state is not playing then exit repeat
			end timeout
			set mNewTrack to current track
			if mNewTrack is not mOldTrack then
				set mOldTrack to mNewTrack
				if not mMiniPlayer then reveal mNewTrack
			end if
			delay mDelay
			set mNowTime to my (current date)
		end repeat
		
		-- フェードアウト:再生停止
		set mVolume to sound volume
		if player state is playing then
			repeat with i from mVolume to 0 by -1
				set sound volume to i
				delay 0.1
			end repeat
		end if
		stop
		
		-- 再生モード復元
		set sound volume to mVolume
		set shuffle enabled to false
		set song repeat to off
		
		-- メインウィンドウ切替
		if mMiniPlayer then
			activate
			delay 1
			tell application "System Events" to keystroke "m" using {shift down, command down}
			delay 1
		end if
		
		-- アプリケーション終了
		quit
		
	end tell
	
	-- エラー出口
on error mCaption number mErrorNumber
	tell me to activate
	if mErrorNumber = -129 then
		-- "再生データなし"
		display alert "再生するデータがありません。" as informational giving up after 5
		tell application "Music" to quit
	else if mErrorNumber = -128 then
		-- "処理キャンセル"
		display alert "処理が中止されました。" as warning giving up after 5
		tell application "Music" to quit
	else
		-- "その他エラー発生"
		display alert mCaption & return & "エラー番号:" & mErrorNumber as critical
	end if
end try

2022/07/14 21:24 Pajerow への返信

ソースコード その1

global mMyName, mList, mID

set mMyName to me's name
set mLibraryPlaylist to "ライブラリ"
set mMusicPlaylist to "ミュージック"
set mMyPlaylist to "Music Player"
set mSearchResult to "Search Result"
set mSearchResult1 to "Search Result 1"
set mSearchResult2 to "Search Result 2"
set mExclude to {mLibraryPlaylist, mMusicPlaylist, mMyPlaylist, mSearchResult, "Alfred Playlist"}
set mShuffle to {"曲", "アルバム"}
set mTimer to {"00:05:00", "00:15:00", "00:30:00", "01:00:00", "01:30:00", "02:00:00"}
set mDelay to 5

try
	tell application "Music"
		
		-- メインウィンドウ非表示
		activate
		delay 1
		set (front window)'s collapsed to true
		
		-- 専用プレイリスト定義
		set mAllPlaylist to every playlist's name
		if mMyPlaylist is not in mAllPlaylist then set mPlayTrack to make new playlist with properties {name:mMyPlaylist}
		if mSearchResult is not in mAllPlaylist then set mSearchTrack to make new playlist with properties {name:mSearchResult}
		set mPlayTrack to playlist (mMyPlaylist)
		set mSearchTrack to playlist (mSearchResult)
		
		-- 検索テキスト入力
		try
			display dialog "テキスト検索をしますか? (*:AND , +:OR)" default answer "" with title mMyName default button 2
			set mSearchText to text returned of result
			set mSearchText to do shell script "sed 's/^ *//' <<< " & quoted form of mSearchText --先頭の空白を削除
			set mSearchText to do shell script "sed 's/* $//' <<< " & quoted form of mSearchText --末尾の空白を削除
		on error
			set mSearchText to ""
		end try
		
		if mSearchText is "" then
			-- プレイリスト選択:選択なしで終了
			set mList to {}
			set mCount to (count playlist (mLibraryPlaylist)'s tracks)
			repeat with i in mAllPlaylist
				if ((count playlist (i)'s tracks) > 0) and (not (mExclude contains playlist (i)'s name)) then set end of mList to i
			end repeat
			set mChoose to choose from list mList with title mMyName with prompt ("プレイリストを選択してください。 ( " & mCount & " 曲)") as text with multiple selections allowed and empty selection allowed
			if mChoose is false then error number -128
		else
			-- テキスト検索実行
			delete mSearchTrack's every track
			set mSearchTrack1 to make new playlist with properties {name:mSearchResult1}
			set mSearchTrack2 to make new playlist with properties {name:mSearchResult2}
			set mSearchText to do shell script "sed 's|+|+|g' <<< " & quoted form of mSearchText
			set mList to my devText(mSearchText, "+")
			try
				repeat with i in mList
					set i to do shell script "sed 's|*|*|g' <<< " & quoted form of i
					set mList1 to my devText(i, "*")
					repeat with j in (search playlist (mLibraryPlaylist) for (mList1's item 1) as text)
						duplicate j to mSearchTrack1
					end repeat
					if (count mList1) > 1 then
						set mList1 to rest of mList1
						repeat with j in mList1
							repeat with k in (search playlist (mSearchResult1) for j)
								duplicate k to mSearchTrack2
							end repeat
							delete mSearchTrack1's every track
							repeat with k in playlist (mSearchResult2)'s tracks
								duplicate k to mSearchTrack1
							end repeat
							delete mSearchTrack2's every track
						end repeat
					end if
					repeat with j in playlist (mSearchResult1)'s tracks
						duplicate j to mSearchTrack
					end repeat
				end repeat
			end try
			delete playlist (mSearchResult1)
			delete playlist (mSearchResult2)
			set mChoose to {mSearchResult}
		end if
		
		-- 重複トラック除外:ジャンル取得
		set mID to {}
		set mList to {}
		repeat with i in mChoose
			repeat with j in playlist (i)'s tracks
				set mProperties to j's properties
				set mSelect to (mProperties's database ID)
				if mSelect is not in mID then
					set end of mID to mSelect
					set mGet to (mProperties's genre)
					if mGet is not in mList then set end of mList to mGet
				end if
			end repeat
		end repeat
		
		my SelectTrack("ジャンル") -- ジャンル選択:アーティスト情報取得
		my SelectTrack("アーティスト") -- アーティスト選択:アルバム情報取得
		my SelectTrack("アルバム") -- アルバム選択:トラック情報取得
		my SelectTrack("トラック") -- トラック選択: 
		if (count mID) = 0 then error number -129 -- 選択トラックなし終了
		
		-- 再生プレイリスト作成:リンク切れエラー無視
		try
			delete mPlayTrack's every track
			repeat with i in mID
				duplicate (tracks whose database ID is i) to mPlayTrack
			end repeat
		end try
		

2022/07/14 21:26 Pajerow への返信

ソースコード その3

-- トラック抽出:トラック情報取得
on SelectTrack(mInf)
	tell application "Music"
		if mInf is not "トラック" then set mList to my SortOfList(the mList)
		set mCount to count mID
		if mList's number > 1 then
			set mChoose to choose from list mList with title mMyName with prompt (mInf & "を選択しますか? ( " & mCount & " 曲)") as text with multiple selections allowed and empty selection allowed
		else
			set mChoose to false
		end if
		set mList to {}
		set mID2 to {}
		repeat with i in mID
			set mProperties to ((tracks whose database ID is i)'s properties)'s item 1
			if mInf is "ジャンル" then set mSelect to (mProperties's genre)
			if mInf is "アーティスト" then set mSelect to (mProperties's artist)
			if mInf is "アルバム" then set mSelect to (mProperties's album)
			if mInf is "トラック" then set mSelect to (mProperties's name)
			if (mChoose is false) or ((count of mChoose) is 0) or (mSelect is in mChoose) then
				set end of mID2 to i
				if mInf is "ジャンル" then set mGet to (mProperties's artist)
				if mInf is "アーティスト" then set mGet to (mProperties's album)
				if mInf is "アルバム" then set mGet to (mProperties's name)
				if mInf is "トラック" then set mGet to ""
				if mGet is not in mList then set end of mList to mGet
			end if
		end repeat
		set mID to mID2
	end tell
end SelectTrack

-- リスト並べ替え
on SortOfList(my_list)
	set index_list to {}
	set sorted_list to {}
	repeat (my_list's length) times
		set low_item to "*"
		repeat with i from 1 to (my_list's length)
			if i is not in index_list then
				set this_item to (my_list's item i) as text
				if low_item is "*" then
					set low_item to this_item
					set low_item_index to i
				else if this_item comes before low_item then
					set low_item to this_item
					set low_item_index to i
				end if
			end if
		end repeat
		set end of sorted_list to low_item
		set end of index_list to low_item_index
	end repeat
	return the sorted_list
end SortOfList

-- HH:MM:SS秒数変換
on TimeToSeconds(hhmmss)
	set hh to (hhmmss's text from character 1 to character 2) as integer
	set mm to (hhmmss's text from character 4 to character 5) as integer
	set ss to (hhmmss's text from character 7 to character 8) as integer
	return (hh * hours + mm * minutes + ss)
end TimeToSeconds

-- 秒数HH:MM:SS変換
on SecondsToTime(ssNum)
	set hhStr to my ZeroPadding((ssNum div hours) as string, 2)
	set mmStr to my ZeroPadding((ssNum mod hours div minutes) as string, 2)
	set ssStr to my ZeroPadding((ssNum mod hours mod minutes) as string, 2)
	return hhStr & ":" & mmStr & ":" & ssStr
end SecondsToTime

-- ゼロパディング
on ZeroPadding(aNum, aLen)
	do shell script "printf '%0" & aLen & "d' " & aNum
end ZeroPadding

-- 文字列分割
on devText(theText, aDelimiter)
	set tmp to AppleScript's text item delimiters
	set AppleScript's text item delimiters to aDelimiter
	set theList to every text item of theText
	set AppleScript's text item delimiters to tmp
	return theList
end devText

2022/08/17 15:26 Pajerow への返信

ソースコード その2

		-- ジャンル選択:トラック情報取得:キャンセルで処理停止
		if ((count mList) ≥ 2) or mOneItem then
			set mDefault to ""
			if (count mList) = 1 then set mDefault to mList's item 1
			set mList to my SortOfList(the mList)
			set mChoose to choose from list mList with title mTitle with prompt (mPrompt & mLF & "ジャンルを選択:         (未選択ですべて選択)") as string default items mDefault cancel button name "Cancel" with multiple selections allowed and empty selection allowed
		else
			set mChoose to {}
		end if
		if mChoose is false then error number -128
		set mID1 to {}
		set mList to {}
		set mListGenre to {}
		set mListArtist to {}
		set mListAlbum to {}
		repeat with i in mID
			tell (tracks whose database ID is i)
				if ((count mChoose) is 0) or (genre is in mChoose) then
					set mID1's end to i
					if genre is not in mListGenre then set mListGenre's end to genre as string
					if artist is not in mListArtist then set mListArtist's end to artist as string
					if album is not in mListAlbum then set mListAlbum's end to album as string
				end if
			end tell
		end repeat
		set mID to mID1
		set mPrompt to "検索テキスト : " & mSearchText & mLF & mLF & "ヒット件数 : " & mLF & (count mListGenre) & mTB & "ジャンル" & mLF & (count mListArtist) & mTB & "アーティスト" & mLF & (count mListAlbum) & mTB & "アルバム" & mLF & (count mID) & mTB & "トラック" & mLF
		set mList to mListArtist
		
		
		-- アーティスト選択:トラック情報取得:キャンセルで処理停止
		if ((count mList) ≥ 2) or mOneItem then
			set mDefault to ""
			if (count mList) = 1 then set mDefault to mList's item 1
			set mList to my SortOfList(the mList)
			set mChoose to choose from list mList with title mTitle with prompt (mPrompt & mLF & "アーティストを選択:          (未選択ですべて選択)") as string default items mDefault cancel button name "Cancel" with multiple selections allowed and empty selection allowed
		else
			set mChoose to {}
		end if
		if mChoose is false then error number -128
		set mID1 to {}
		set mList to {}
		set mListGenre to {}
		set mListArtist to {}
		set mListAlbum to {}
		repeat with i in mID
			tell (tracks whose database ID is i)
				if ((count mChoose) is 0) or (artist is in mChoose) then
					set mID1's end to i
					if genre is not in mListGenre then set mListGenre's end to genre as string
					if artist is not in mListArtist then set mListArtist's end to artist as string
					if album is not in mListAlbum then set mListAlbum's end to album as string
				end if
			end tell
		end repeat
		set mID to mID1
		set mPrompt to "検索テキスト : " & mSearchText & mLF & mLF & "ヒット件数 : " & mLF & (count mListGenre) & mTB & "ジャンル" & mLF & (count mListArtist) & mTB & "アーティスト" & mLF & (count mListAlbum) & mTB & "アルバム" & mLF & (count mID) & mTB & "トラック" & mLF
		set mList to mListAlbum
		
		
		-- アルバム選択:トラック情報取得:キャンセルで処理停止
		if ((count mList) ≥ 2) or mOneItem then
			set mDefault to ""
			if (count mList) = 1 then set mDefault to mList's item 1
			set mList to my SortOfList(the mList)
			set mChoose to choose from list mList with title mTitle with prompt (mPrompt & mLF & "アルバムを選択:          (未選択ですべて選択)") as string default items mDefault cancel button name "Cancel" with multiple selections allowed and empty selection allowed
		else
			set mChoose to {}
		end if
		if mChoose is false then error number -128
		set mID1 to {}
		set mList to {}
		set mListGenre to {}
		set mListArtist to {}
		set mListAlbum to {}
		set mListName to {}
		repeat with i in mID
			tell (tracks whose database ID is i)
				if ((count mChoose) is 0) or (album is in mChoose) then
					set mID1's end to i
					if genre is not in mListGenre then set mListGenre's end to genre as string
					if artist is not in mListArtist then set mListArtist's end to artist as string
					if album is not in mListAlbum then set mListAlbum's end to album as string
					if name is not in mListName then set mListName's end to name as string
				end if
			end tell
		end repeat
		set mID to mID1
		set mPrompt to "検索テキスト : " & mSearchText & mLF & mLF & "ヒット件数 : " & mLF & (count mListGenre) & mTB & "ジャンル" & mLF & (count mListArtist) & mTB & "アーティスト" & mLF & (count mListAlbum) & mTB & "アルバム" & mLF & (count mID) & mTB & "トラック" & mLF
		set mList to mListName
		
		
		-- トラック選択:キャンセルで処理停止
		--if ((count mList) ≥ 2) or mOneItem then
		if (count mList) ≥ 1 then
			set mDefault to ""
			if (count mList) = 1 then set mDefault to mList's item 1
			set mChoose to choose from list mList with title mTitle with prompt (mPrompt & mLF & "トラックを選択:         (未選択ですべて選択)") as string default items mDefault cancel button name "Cancel" with multiple selections allowed and empty selection allowed
		else
			set mChoose to {}
		end if
		if mChoose is false then error number -128
		
		


このスレッドはシステム、またはAppleコミュニティチームによってロックされました。 問題解決の参考になる情報であれば、どの投稿にでも投票いただけます。またコミュニティで他の回答を検索することもできます。

AppleScriptによるMusic Player(再掲)

Apple サポートコミュニティへようこそ
Apple ユーザ同士でお使いの製品について助け合うフォーラムです。Apple Account を使ってご参加ください。