├── Contents ├── Info.plist ├── QuickLook │ ├── Preview.png │ └── Thumbnail.png └── document.wflow ├── LICENSE └── README.md /Contents/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSServices 6 | 7 | 8 | NSBackgroundColorName 9 | background 10 | NSIconName 11 | NSTouchBarAudioOutputVolumeHigh 12 | NSMenuItem 13 | 14 | default 15 | Create-Playlist 16 | 17 | NSMessage 18 | runWorkflowAsService 19 | NSRequiredContext 20 | 21 | NSApplicationIdentifier 22 | com.apple.finder 23 | 24 | NSSendFileTypes 25 | 26 | public.folder 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /Contents/QuickLook/Preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bmatcuk/Create-Playlist.workflow/1c49ee8b6991fa9e6151949ca4d8cb4143d7cfe7/Contents/QuickLook/Preview.png -------------------------------------------------------------------------------- /Contents/QuickLook/Thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bmatcuk/Create-Playlist.workflow/1c49ee8b6991fa9e6151949ca4d8cb4143d7cfe7/Contents/QuickLook/Thumbnail.png -------------------------------------------------------------------------------- /Contents/document.wflow: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | AMApplicationBuild 6 | 492 7 | AMApplicationVersion 8 | 2.10 9 | AMDocumentVersion 10 | 2 11 | actions 12 | 13 | 14 | action 15 | 16 | AMAccepts 17 | 18 | Container 19 | List 20 | Optional 21 | 22 | Types 23 | 24 | * 25 | 26 | 27 | AMActionVersion 28 | v.1.0.2 29 | AMApplication 30 | 31 | Automator 32 | 33 | AMParameterProperties 34 | 35 | variableUUID 36 | 37 | isPathPopUp 38 | 39 | selectedVariableUUID 40 | 7C26CE02-E8A4-45A7-B218-26DB5A8B7F94 41 | 42 | 43 | AMProvides 44 | 45 | Container 46 | List 47 | Types 48 | 49 | * 50 | 51 | 52 | AMRequiredResources 53 | 54 | ActionBundlePath 55 | /System/Library/Automator/Set Value of Variable.action 56 | ActionName 57 | Set Value of Variable 58 | ActionParameters 59 | 60 | variableUUID 61 | 7C26CE02-E8A4-45A7-B218-26DB5A8B7F94 62 | 63 | BundleIdentifier 64 | com.apple.Automator.SetValueofVariable 65 | CFBundleVersion 66 | 1.0.2 67 | CanShowSelectedItemsWhenRun 68 | 69 | CanShowWhenRun 70 | 71 | Category 72 | 73 | AMCategoryUtilities 74 | 75 | Class Name 76 | Set_Value_of_Variable 77 | InputUUID 78 | 386FA3FC-C20C-4CF4-B1DA-826F5936E17C 79 | Keywords 80 | 81 | variable 82 | binding 83 | input 84 | output 85 | storage 86 | 87 | OutputUUID 88 | 3B5081E1-0596-4ED8-A51F-7581F8DC81C4 89 | UUID 90 | 70F6F4D7-0B41-4AA2-8A57-D056BEE53D21 91 | UnlocalizedApplications 92 | 93 | Automator 94 | 95 | arguments 96 | 97 | 0 98 | 99 | default value 100 | 101 | name 102 | variableUUID 103 | required 104 | 0 105 | type 106 | 0 107 | uuid 108 | 0 109 | 110 | 111 | isViewVisible 112 | 113 | location 114 | 309.000000:228.000000 115 | nibPath 116 | /System/Library/Automator/Set Value of Variable.action/Contents/Resources/Base.lproj/main.nib 117 | 118 | isViewVisible 119 | 120 | 121 | 122 | action 123 | 124 | AMAccepts 125 | 126 | Container 127 | List 128 | Optional 129 | 130 | Types 131 | 132 | com.apple.applescript.object 133 | 134 | 135 | AMActionVersion 136 | 1.0.2 137 | AMApplication 138 | 139 | Automator 140 | 141 | AMParameterProperties 142 | 143 | source 144 | 145 | 146 | AMProvides 147 | 148 | Container 149 | List 150 | Types 151 | 152 | com.apple.applescript.object 153 | 154 | 155 | ActionBundlePath 156 | /System/Library/Automator/Run AppleScript.action 157 | ActionName 158 | Run AppleScript 159 | ActionParameters 160 | 161 | source 162 | on run choose from list {"Name - Ascending", "Name - Descending", "Creation Date - Ascending", "Creation Date - Descending", "Modified Date - Ascending", "Modified Date - Descending"} with title "Create Playlist" with prompt "Sort songs by:" default items {"Name - Ascending"} without multiple selections allowed and empty selection allowed return the result as string end run 163 | 164 | BundleIdentifier 165 | com.apple.Automator.RunScript 166 | CFBundleVersion 167 | 1.0.2 168 | CanShowSelectedItemsWhenRun 169 | 170 | CanShowWhenRun 171 | 172 | Category 173 | 174 | AMCategoryUtilities 175 | 176 | Class Name 177 | RunScriptAction 178 | IgnoresInput 179 | 180 | InputUUID 181 | B513D523-8391-4F9D-B8EA-A60666EA8F0E 182 | Keywords 183 | 184 | Run 185 | 186 | OutputUUID 187 | 32930339-DD5E-4300-BAEF-102C888EB92E 188 | UUID 189 | 88EF14DB-E3E0-4650-8AD7-5838C1FA3FDB 190 | UnlocalizedApplications 191 | 192 | Automator 193 | 194 | arguments 195 | 196 | 0 197 | 198 | default value 199 | on run {input, parameters} 200 | 201 | (* Your script goes here *) 202 | 203 | return input 204 | end run 205 | name 206 | source 207 | required 208 | 0 209 | type 210 | 0 211 | uuid 212 | 0 213 | 214 | 215 | isViewVisible 216 | 217 | location 218 | 309.000000:473.000000 219 | nibPath 220 | /System/Library/Automator/Run AppleScript.action/Contents/Resources/Base.lproj/main.nib 221 | 222 | isViewVisible 223 | 224 | 225 | 226 | action 227 | 228 | AMAccepts 229 | 230 | Container 231 | List 232 | Optional 233 | 234 | Types 235 | 236 | * 237 | 238 | 239 | AMActionVersion 240 | v.1.0.2 241 | AMApplication 242 | 243 | Automator 244 | 245 | AMParameterProperties 246 | 247 | variableUUID 248 | 249 | isPathPopUp 250 | 251 | selectedVariableUUID 252 | 7C26CE02-E8A4-45A7-B218-26DB5A8B7F94 253 | 254 | 255 | AMProvides 256 | 257 | Container 258 | List 259 | Types 260 | 261 | * 262 | 263 | 264 | AMRequiredResources 265 | 266 | ActionBundlePath 267 | /System/Library/Automator/Get Value of Variable.action 268 | ActionName 269 | Get Value of Variable 270 | ActionParameters 271 | 272 | variableUUID 273 | 7C26CE02-E8A4-45A7-B218-26DB5A8B7F94 274 | 275 | BundleIdentifier 276 | com.apple.Automator.GetValueofVariable 277 | CFBundleVersion 278 | 1.0.2 279 | CanShowSelectedItemsWhenRun 280 | 281 | CanShowWhenRun 282 | 283 | Category 284 | 285 | AMCategoryUtilities 286 | 287 | Class Name 288 | Get_Value_of_Variable 289 | InputUUID 290 | 8F45ED39-A62C-477B-B06F-75EDD8C4AAEF 291 | Keywords 292 | 293 | variable 294 | binding 295 | input 296 | output 297 | storage 298 | 299 | OutputUUID 300 | 77EE0214-6DED-417B-BF6B-EC74C11490F6 301 | UUID 302 | 4751531C-B72C-4308-AD90-21392D94B713 303 | UnlocalizedApplications 304 | 305 | Automator 306 | 307 | arguments 308 | 309 | 0 310 | 311 | default value 312 | 313 | name 314 | variableUUID 315 | required 316 | 0 317 | type 318 | 0 319 | uuid 320 | 0 321 | 322 | 323 | isViewVisible 324 | 325 | location 326 | 309.000000:575.000000 327 | nibPath 328 | /System/Library/Automator/Get Value of Variable.action/Contents/Resources/Base.lproj/main.nib 329 | 330 | isViewVisible 331 | 332 | 333 | 334 | action 335 | 336 | AMAccepts 337 | 338 | Container 339 | List 340 | Optional 341 | 342 | Types 343 | 344 | com.apple.cocoa.string 345 | 346 | 347 | AMActionVersion 348 | 2.0.3 349 | AMApplication 350 | 351 | Automator 352 | 353 | AMParameterProperties 354 | 355 | COMMAND_STRING 356 | 357 | CheckedForUserDefaultShell 358 | 359 | inputMethod 360 | 361 | shell 362 | 363 | source 364 | 365 | 366 | AMProvides 367 | 368 | Container 369 | List 370 | Types 371 | 372 | com.apple.cocoa.string 373 | 374 | 375 | ActionBundlePath 376 | /System/Library/Automator/Run Shell Script.action 377 | ActionName 378 | Run Shell Script 379 | ActionParameters 380 | 381 | COMMAND_STRING 382 | SORT="$1" 383 | shift 384 | 385 | # SORT == false means the user canceled 386 | if [ "$SORT" != "false" ]; then 387 | # SORT = "Field - Ascending/Descending" 388 | # If Descending, set SORT_ORDER to --reverse 389 | SORT_ORDER="sort" 390 | SORT_ORDER_NAME="cat" 391 | if [ "${SORT##* - }" == "Descending" ]; then 392 | SORT_ORDER="sort --reverse" 393 | SORT_ORDER_NAME="tail -r" 394 | fi 395 | 396 | # SORT = "Field" now 397 | SORT="${SORT%% - *}" 398 | 399 | for dir; do 400 | cd "$dir" 401 | PLAYLIST="../${PWD##*/}.m3u" 402 | 403 | # Find all music and output to tmp file as: 404 | # CreationDate ModifiedDate Filename 405 | find -Es . -type f -iregex '.*\.(mp3|aac|m4a|wav|wma|flac|ogg|pcm|aiff|alac)' -exec bash -c 'file="{}"; stat -f "%SB %Sm ${PWD##*/}/${file#*/}" -t "%s" "$file"' > "${PLAYLIST}.tmp" \; 406 | 407 | # Sort, cut, and copy to playlist 408 | if [ "$SORT" == "Creation Date" ]; then 409 | $SORT_ORDER -s -n -k 1 "${PLAYLIST}.tmp" | cut -d' ' -f3- > "$PLAYLIST" 410 | elif [ "$SORT" == "Modified Date" ]; then 411 | $SORT_ORDER -s -n -k 2 "${PLAYLIST}.tmp" | cut -d' ' -f3- > "$PLAYLIST" 412 | else 413 | $SORT_ORDER_NAME "${PLAYLIST}.tmp" | cut -d' ' -f3- > "$PLAYLIST" 414 | fi 415 | 416 | # remove temp file 417 | rm "${PLAYLIST}.tmp" 418 | done 419 | fi 420 | CheckedForUserDefaultShell 421 | 422 | inputMethod 423 | 1 424 | shell 425 | /bin/bash 426 | source 427 | 428 | 429 | BundleIdentifier 430 | com.apple.RunShellScript 431 | CFBundleVersion 432 | 2.0.3 433 | CanShowSelectedItemsWhenRun 434 | 435 | CanShowWhenRun 436 | 437 | Category 438 | 439 | AMCategoryUtilities 440 | 441 | Class Name 442 | RunShellScriptAction 443 | Disabled 444 | 445 | InputUUID 446 | 990185A7-F7E4-49BB-A084-19881523CEEA 447 | Keywords 448 | 449 | Shell 450 | Script 451 | Command 452 | Run 453 | Unix 454 | 455 | OutputUUID 456 | 24A327E0-39E1-4A97-B005-F3C3F5049958 457 | UUID 458 | 8D841DED-DE6C-4090-8653-D34304093735 459 | UnlocalizedApplications 460 | 461 | Automator 462 | 463 | arguments 464 | 465 | 0 466 | 467 | default value 468 | 0 469 | name 470 | inputMethod 471 | required 472 | 0 473 | type 474 | 0 475 | uuid 476 | 0 477 | 478 | 1 479 | 480 | default value 481 | 482 | name 483 | CheckedForUserDefaultShell 484 | required 485 | 0 486 | type 487 | 0 488 | uuid 489 | 1 490 | 491 | 2 492 | 493 | default value 494 | 495 | name 496 | source 497 | required 498 | 0 499 | type 500 | 0 501 | uuid 502 | 2 503 | 504 | 3 505 | 506 | default value 507 | 508 | name 509 | COMMAND_STRING 510 | required 511 | 0 512 | type 513 | 0 514 | uuid 515 | 3 516 | 517 | 4 518 | 519 | default value 520 | /bin/sh 521 | name 522 | shell 523 | required 524 | 0 525 | type 526 | 0 527 | uuid 528 | 4 529 | 530 | 531 | isViewVisible 532 | 533 | location 534 | 309.000000:757.000000 535 | nibPath 536 | /System/Library/Automator/Run Shell Script.action/Contents/Resources/Base.lproj/main.nib 537 | 538 | isViewVisible 539 | 540 | 541 | 542 | connectors 543 | 544 | 24DA740A-C501-4120-BF67-5CBC45884DCF 545 | 546 | from 547 | 4751531C-B72C-4308-AD90-21392D94B713 - 4751531C-B72C-4308-AD90-21392D94B713 548 | to 549 | 8D841DED-DE6C-4090-8653-D34304093735 - 8D841DED-DE6C-4090-8653-D34304093735 550 | 551 | B96CAFE2-EA4A-4D40-89B9-3AC49D8C3BA3 552 | 553 | from 554 | 70F6F4D7-0B41-4AA2-8A57-D056BEE53D21 - 70F6F4D7-0B41-4AA2-8A57-D056BEE53D21 555 | to 556 | 88EF14DB-E3E0-4650-8AD7-5838C1FA3FDB - 88EF14DB-E3E0-4650-8AD7-5838C1FA3FDB 557 | 558 | DDDDEC8B-84D5-4F82-B0B9-C3F585CA33BC 559 | 560 | from 561 | 88EF14DB-E3E0-4650-8AD7-5838C1FA3FDB - 88EF14DB-E3E0-4650-8AD7-5838C1FA3FDB 562 | to 563 | 4751531C-B72C-4308-AD90-21392D94B713 - 4751531C-B72C-4308-AD90-21392D94B713 564 | 565 | 566 | variables 567 | 568 | 569 | UUID 570 | 7C26CE02-E8A4-45A7-B218-26DB5A8B7F94 571 | identifier 572 | com.apple.Automator.Variable.Storage 573 | name 574 | Directories 575 | 576 | 577 | workflowMetaData 578 | 579 | applicationBundleID 580 | com.apple.finder 581 | applicationBundleIDsByPath 582 | 583 | /System/Library/CoreServices/Finder.app 584 | com.apple.finder 585 | 586 | applicationPath 587 | /System/Library/CoreServices/Finder.app 588 | applicationPaths 589 | 590 | /System/Library/CoreServices/Finder.app 591 | 592 | inputTypeIdentifier 593 | com.apple.Automator.fileSystemObject.folder 594 | outputTypeIdentifier 595 | com.apple.Automator.nothing 596 | presentationMode 597 | 15 598 | processesInput 599 | 0 600 | serviceApplicationBundleID 601 | com.apple.finder 602 | serviceApplicationPath 603 | /System/Library/CoreServices/Finder.app 604 | serviceInputTypeIdentifier 605 | com.apple.Automator.fileSystemObject.folder 606 | serviceOutputTypeIdentifier 607 | com.apple.Automator.nothing 608 | serviceProcessesInput 609 | 0 610 | systemImageName 611 | NSTouchBarAudioOutputVolumeHigh 612 | useAutomaticInputType 613 | 0 614 | workflowTypeIdentifier 615 | com.apple.Automator.servicesMenu 616 | 617 | 618 | 619 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Bob Matcuk 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Create-Playlist.workflow 2 | ======================== 3 | 4 | An OSX Automator Workflow for creating relative-pathed m3u playlists from audio 5 | files in the selected folder. 6 | 7 | Installation 8 | ------------ 9 | 10 | To install, simply `git clone 11 | https://github.com/bmatcuk/Create-Playlist.workflow.git 12 | ~/Library/Services/Create-Playlist.workflow`. You may need to "open" the 13 | workflow to get it to appear in the Services menu. To do that, just navigate to 14 | ~/Library/Services and double click Create-Playlist.workflow to open it in 15 | Automator. You don't need to do anything here; just close Automator. 16 | 17 | You may also encounter permission problems (it will appear locked in 18 | Automator). To fix that in your terminal, run the following commands: 19 | 20 | ```bash 21 | chown -R "$(id -un):$(id -gn)" ~/Library/Services/Create-Playlist.workflow 22 | chmod -R 0755 ~/Library/Services/Create-Playlist.workflow 23 | ``` 24 | 25 | The first command ensures that the current user owns the files, and the second 26 | ensures that you have read, write, and execute permission. 27 | 28 | To use, open a Finder window and locate a folder for which you want to create a 29 | playlist. Right click on this folder and select Services, Create-Playlist. In a 30 | moment, a file will be created in the current folder with the same name as the 31 | folder you selected and the .m3u extension. You can also select multiple 32 | folders. Right click and select Services, Create Playlist as before and you'll 33 | get a .m3u file for each folder selected! Note: There may be a limit to the 34 | number of folders the workflow can process at a time... 35 | 36 | This script will find .mp3, .aac, .m4a, .wav, .wma, .flac, .ogg, .pcm, .aiff, 37 | and .alac files. If there are any others you think it should support, file an 38 | Issue. 39 | 40 | How Does it Work? 41 | ----------------- 42 | 43 | This is an [Automator](http://macosxautomation.com/automator/) workflow that 44 | runs a simple shell script. The script loops through the arguments (the 45 | selected folders, in this case), switches to that folder, and then searches for 46 | audio files recursively. Whenever an audio file is found, it is appended to the 47 | m3u file using some appropriate formatting. 48 | 49 | Why? 50 | ---- 51 | 52 | My car can read music off a USB keychain drive. It seems to understand artists 53 | and albums from the MP3 headers, but it just ends up playing songs in 54 | alphabetic order by filename. I could rename all my files so they'll end up 55 | playing in the order I'd like... but my car also understands m3u files. It 56 | seemed easier to make this work =) 57 | --------------------------------------------------------------------------------