final touches to interface to include album covers, and more
This commit is contained in:
parent
1fedcdf92b
commit
a1b0439bd0
|
@ -15,6 +15,7 @@
|
||||||
"urlpattern-polyfill": "^9.0.0"
|
"urlpattern-polyfill": "^9.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"chokidar": "^3.5.3",
|
||||||
"eslint": "^8.49.0",
|
"eslint": "^8.49.0",
|
||||||
"eslint-plugin-lit": "^1.9.1",
|
"eslint-plugin-lit": "^1.9.1",
|
||||||
"sass": "^1.67.0",
|
"sass": "^1.67.0",
|
||||||
|
|
|
@ -1,50 +1,51 @@
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"title": "Late Junction",
|
"title": "Fireside Chat",
|
||||||
"details": "BBC, 2019",
|
"details": "Mark \"Frosty\" McNeil, Red Bull Radio, 2019",
|
||||||
"parent_dir": "documentaries_interviews_audio",
|
"parent_dir": "documentaries_interviews_audio",
|
||||||
"media": "-21 08_Late Junction_2019 - Meredith Monk v2 BBC"
|
"media": "Fireside Chat_Mark \"Frosty\" McNeil, Red Bull Radio, 2019.mp3",
|
||||||
|
"image": "Fireside Chat_Mark \"Frosty\" McNeil, Red Bull Radio, 2019.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Speaking of Music",
|
"title": "Irene Ferchl, Bayerischer Rundfunk",
|
||||||
"details": "Meredith Monk, 1984 Part 1 of 2",
|
"details": "Kulturjournal, 1986",
|
||||||
"parent_dir": "documentaries_interviews_audio",
|
"parent_dir": "documentaries_interviews_audio",
|
||||||
"media": "-22 02_Speaking of Music Meredith Monk 1984 Part 1 of 2"
|
"media": "Irene Ferchl, Bayerischer Rundfunk_Kulturjournal, 1986.mp3",
|
||||||
},
|
"image": "Irene Ferchl, Bayerischer Rundfunk_Kulturjournal, 1986.png"
|
||||||
{
|
|
||||||
"title": "Speaking of Music",
|
|
||||||
"details": "Meredith Monk, 1984 Part 2 of 2",
|
|
||||||
"parent_dir": "documentaries_interviews_audio",
|
|
||||||
"media": "-23 03_Speaking of Music_ Meredith Monk 1984 Part 2 of 2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Interview with I Frechl-Bayn Rundfunk",
|
|
||||||
"details": "1986",
|
|
||||||
"parent_dir": "documentaries_interviews_audio",
|
|
||||||
"media": "-24 04 Meredith Monk Interview with I Ferchl_Bayn Rundfunk 1986"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Terry Gross Interview",
|
|
||||||
"details": "1987",
|
|
||||||
"parent_dir": "documentaries_interviews_audio",
|
|
||||||
"media": "-25 05 Terry Gross interview_1987"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Interview with David Garland",
|
|
||||||
"details": "WNYC, Sacred Sundays, 2008",
|
|
||||||
"parent_dir": "documentaries_interviews_audio",
|
|
||||||
"media": "-26 06 WNYC Interview w_ David Garland_SacredSundays_2008"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Frosty McNeil and Meredith Monk",
|
|
||||||
"details": "Fireside Chat, Red Bull Radio",
|
|
||||||
"parent_dir": "documentaries_interviews_audio",
|
|
||||||
"media": "-27 07_Red Bull Radio_Fireside Chat_M frosty McNeil and MM_41119"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Late Junction",
|
"title": "Late Junction",
|
||||||
"details": "BBC, 2019",
|
"details": "Jennifer Lucy Allan, BBC Radio 3, 2019",
|
||||||
"parent_dir": "documentaries_interviews_audio",
|
"parent_dir": "documentaries_interviews_audio",
|
||||||
"media": "-28 08_Late Junction_2019 - Meredith Monk v2 BBC"
|
"media": "Late Junction_Jennifer Lucy Allan, BBC Radio 3, 2019.mp3",
|
||||||
|
"image": "Late Junction_Jennifer Lucy Allan, BBC Radio 3, 2019.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Sacred Sundays",
|
||||||
|
"details": "David Garland, WNYC, 2008",
|
||||||
|
"parent_dir": "documentaries_interviews_audio",
|
||||||
|
"media": "Sacred Sundays_David Garland, WNYC, 2008.mp3",
|
||||||
|
"image": "Sacred Sundays_David Garland, WNYC, 2008.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Speaking of Music",
|
||||||
|
"details": "Charles Amirkhanian, Other Minds, 1984. Part 1 of 2",
|
||||||
|
"parent_dir": "documentaries_interviews_audio",
|
||||||
|
"media": "Speaking of Music_Charles Amirkhanian, Other Minds, 1984. Part 1 of 2..mp3",
|
||||||
|
"image": "Speaking of Music_Charles Amirkhanian, Other Minds, 1984. Part 1 of 2..png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Speaking of Music",
|
||||||
|
"details": "Charles Amirkhanian, Other Minds, 1984. Part 2 of 2",
|
||||||
|
"parent_dir": "documentaries_interviews_audio",
|
||||||
|
"media": "Speaking of Music_Charles Amirkhanian, Other Minds, 1984. Part 2 of 2..mp3",
|
||||||
|
"image": "Speaking of Music_Charles Amirkhanian, Other Minds, 1984. Part 2 of 2..png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Terry Gross",
|
||||||
|
"details": "unedited, 1987",
|
||||||
|
"parent_dir": "documentaries_interviews_audio",
|
||||||
|
"media": "Terry Gross_unedited, 1987.mp3",
|
||||||
|
"image": "Terry Gross_unedited, 1987.png"
|
||||||
}
|
}
|
||||||
]
|
]
|
|
@ -1,92 +1,114 @@
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"title": "Michael Blackwood Making Dances",
|
"title": "4 American Composers",
|
||||||
"details": "",
|
"details": "documentary by Peter Greenaway, 1983",
|
||||||
"parent_dir": "documentaries_interviews_video",
|
"parent_dir": "documentaries_interviews_video",
|
||||||
"media": "--2 MichaelBlackwoodMakingDances.m4v"
|
"media": "4 American Composers_documentary by Peter Greenaway, 1983.m4v",
|
||||||
},
|
"image": "4 American Composers_documentary by Peter Greenaway, 1983.jpg"
|
||||||
{
|
|
||||||
"title": "ECM 1981",
|
|
||||||
"details": "2019",
|
|
||||||
"parent_dir": "documentaries_interviews_video",
|
|
||||||
"media": "--3 ECM1981 Video Meredith Monk V2_2019.m4v"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Andere Avantgarde",
|
"title": "Andere Avantgarde",
|
||||||
"details": "TV Interview 1982",
|
"details": "television documentary by Peter Greenaway, 1983",
|
||||||
"parent_dir": "documentaries_interviews_video",
|
"parent_dir": "documentaries_interviews_video",
|
||||||
"media": "--4 Meredith Monk_Andere Avantgarde_TV Interview_1982_.m4v"
|
"media": "Andere Avantgarde_television documentary by Peter Greenaway, 1983.m4v",
|
||||||
},
|
"image": "Andere Avantgarde_television documentary by Peter Greenaway, 1983.jpg"
|
||||||
{
|
|
||||||
"title": "New Sounds for a New World",
|
|
||||||
"details": "1982",
|
|
||||||
"parent_dir": "documentaries_interviews_video",
|
|
||||||
"media": "--5 New Sounds for a New World_1982.m4v"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Four American Composers",
|
|
||||||
"details": "PeterGreenaway",
|
|
||||||
"parent_dir": "documentaries_interviews_video",
|
|
||||||
"media": "--6 Four American Composers_Peter Greenaway.m4v"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "BBC Late Show",
|
"title": "BBC Late Show",
|
||||||
"details": "",
|
"details": "television interview, 1991",
|
||||||
"parent_dir": "documentaries_interviews_video",
|
"parent_dir": "documentaries_interviews_video",
|
||||||
"media": "--7 bbc_late_show (Original).m4v"
|
"media": "BBC Late Show_television interview, 1991.m4v",
|
||||||
|
"image": "BBC Late Show_television interview, 1991.jpg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Documentary by Sidsel Mundal",
|
"title": "Coffee and Composition",
|
||||||
"details": "Norwegian Television, 1994",
|
"details": "Meredith Monk and Robert Kyr, online, 2021",
|
||||||
"parent_dir": "documentaries_interviews_video",
|
"parent_dir": "documentaries_interviews_video",
|
||||||
"media": "--8 1994 documentary by Sidsel Mundal_for Norwegian Telev.m4v"
|
"media": "Coffee and Composition_Meredith Monk and Robert Kyr, online, 2021.m4v",
|
||||||
|
"image": "Coffee and Composition_Meredith Monk and Robert Kyr, online, 2021.jpg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Television Documentary",
|
"title": "Dorothy and Lillian Gish Award",
|
||||||
"details": "Polish Television, 1995",
|
"details": "portrait interview with Meredith Monk, 2017",
|
||||||
"parent_dir": "documentaries_interviews_video",
|
"parent_dir": "documentaries_interviews_video",
|
||||||
"media": "--9 Meredith Monk - Polish Television Documentary (1995).m4v"
|
"media": "Dorothy and Lillian Gish Award_portrait interview with Meredith Monk, 2017.m4v",
|
||||||
|
"image": "Dorothy and Lillian Gish Award_portrait interview with Meredith Monk, 2017.jpg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Inner Voice",
|
"title": "ECM 50 | 1981 Meredith Monk",
|
||||||
"details": "",
|
"details": "documentary by Ingo Berhman for ECM Records' 50th Anniversary, 2019",
|
||||||
"parent_dir": "documentaries_interviews_video",
|
"parent_dir": "documentaries_interviews_video",
|
||||||
"media": "-12 MeredithMonk_Inner Voice.m4v"
|
"media": "ECM 50 | 1981 Meredith Monk_documentary by Ingo Berhman for ECM Records' 50th Anniversary, 2019.m4v",
|
||||||
|
"image": "ECM 50 | 1981 Meredith Monk_documentary by Ingo Berhman for ECM Records' 50th Anniversary, 2019.jpg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Lecutre Performance",
|
"title": "Girlchild Diary",
|
||||||
"details": "Bennington College, 11 March 2011",
|
"details": "documentary on Education of the Girlchild, ed. Joëlle Schon, 2015",
|
||||||
"parent_dir": "documentaries_interviews_video",
|
"parent_dir": "documentaries_interviews_video",
|
||||||
"media": "-13 Bennington College lecture performance 3.11.11.m4v"
|
"media": "Girlchild Diary_documentary on Education of the Girlchild, ed. Joëlle Schon, 2015.m4v",
|
||||||
|
"image": "Girlchild Diary_documentary on Education of the Girlchild, ed. Joëlle Schon, 2015.jpg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "",
|
"title": "MMonk",
|
||||||
|
"details": "TheSoulsMessenger",
|
||||||
"parent_dir": "documentaries_interviews_video",
|
"parent_dir": "documentaries_interviews_video",
|
||||||
"media": "-14 MMonk_TheSoulsMessenger_Lublin_2012.m4v"
|
"media": "MMonk_TheSoulsMessenger_Lublin_2012.m4v",
|
||||||
|
"image": "MMonk_TheSoulsMessenger_Lublin_2012.jpg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "",
|
"title": "Making Dances",
|
||||||
|
"details": "documentary by Michael Blackwood, 1980",
|
||||||
"parent_dir": "documentaries_interviews_video",
|
"parent_dir": "documentaries_interviews_video",
|
||||||
"media": "-15 Girlchild Diary_61116.m4v"
|
"media": "Making Dances_documentary by Michael Blackwood, 1980.m4v",
|
||||||
|
"image": "Making Dances_documentary by Michael Blackwood, 1980.jpg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "",
|
"title": "Meredith Monk and Adam Shatz",
|
||||||
|
"details": "conversation on Book of Days, online, 2020",
|
||||||
"parent_dir": "documentaries_interviews_video",
|
"parent_dir": "documentaries_interviews_video",
|
||||||
"media": "-16 Q2 Spaces_Meredith Monk_2014.m4v"
|
"media": "Meredith Monk and Adam Shatz_conversation on Book of Days, online, 2020.m4v",
|
||||||
|
"image": "Meredith Monk and Adam Shatz_conversation on Book of Days, online, 2020.jpg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "",
|
"title": "Meredith Monk lecture",
|
||||||
|
"details": "Bennington College, Vermont, 2011",
|
||||||
"parent_dir": "documentaries_interviews_video",
|
"parent_dir": "documentaries_interviews_video",
|
||||||
"media": "-17 Gish Prize Ceremony Camera A.m4v"
|
"media": "Meredith Monk lecture_Bennington College, Vermont, 2011.m4v",
|
||||||
|
"image": "Meredith Monk lecture_Bennington College, Vermont, 2011.jpg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "",
|
"title": "Meredith Monk: Inner Voice",
|
||||||
|
"details": "documentary by Babeth M. VanLoo, Buddhist Broadcasting Foundation, 2009",
|
||||||
"parent_dir": "documentaries_interviews_video",
|
"parent_dir": "documentaries_interviews_video",
|
||||||
"media": "-18 MM and Adam Shatz - Book of Days conversation_2020.m4v"
|
"media": "Meredith Monk: Inner Voice_documentary by Babeth M. VanLoo, Buddhist Broadcasting Foundation, 2009.m4v",
|
||||||
|
"image": "Meredith Monk: Inner Voice_documentary by Babeth M. VanLoo, Buddhist Broadcasting Foundation, 2009.jpg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "",
|
"title": "Meredith Monk",
|
||||||
|
"details": "documentary by Sidsel Mundal for Norwegian Television, 1994",
|
||||||
"parent_dir": "documentaries_interviews_video",
|
"parent_dir": "documentaries_interviews_video",
|
||||||
"media": "-19 Coffee and Composition with Meredith Monk_2021.m4v"
|
"media": "Meredith Monk_documentary by Sidsel Mundal for Norwegian Television, 1994.m4v",
|
||||||
|
"image": "Meredith Monk_documentary by Sidsel Mundal for Norwegian Television, 1994.jpg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Meredith",
|
||||||
|
"details": "documentary by Mariusz Grzegorzeki for Polish Television, 1995",
|
||||||
|
"parent_dir": "documentaries_interviews_video",
|
||||||
|
"media": "Meredith_documentary by Mariusz Grzegorzeki for Polish Television, 1995.m4v",
|
||||||
|
"image": "Meredith_documentary by Mariusz Grzegorzeki for Polish Television, 1995.jpg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Neue Töne aus der Neuen Welt",
|
||||||
|
"details": "(New Sounds for a New World) documentary by Birgitta Ashoff for German Telelvision (in German), 1983",
|
||||||
|
"parent_dir": "documentaries_interviews_video",
|
||||||
|
"media": "Neue Töne aus der Neuen Welt_(New Sounds for a New World) documentary by Birgitta Ashoff for German Telelvision (in German), 1983.m4v",
|
||||||
|
"image": "Neue Töne aus der Neuen Welt_(New Sounds for a New World) documentary by Birgitta Ashoff for German Telelvision (in German), 1983.jpg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Q2 Spaces: Meredith Monk",
|
||||||
|
"details": "documentary, 2014",
|
||||||
|
"parent_dir": "documentaries_interviews_video",
|
||||||
|
"media": "Q2 Spaces: Meredith Monk_documentary, 2014.m4v",
|
||||||
|
"image": "Q2 Spaces: Meredith Monk_documentary, 2014.jpg"
|
||||||
}
|
}
|
||||||
]
|
]
|
|
@ -1,27 +1,44 @@
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"title": "",
|
"title": "16 Millimeter Earrings",
|
||||||
"parent_dir": "films",
|
"details": "Robert S. Withers, 1979",
|
||||||
"media": "_72 01 16_Millimeter_Earrings_1980_Color_IN_HD_23-98_ProRes4444_Pillar Scan GOOD copy v4 2023 0812.m4v"
|
"parent_dir": "Films",
|
||||||
|
"media": "16 Millimeter Earrings_Robert S. Withers, 1979.m4v",
|
||||||
|
"image": "16 Millimeter Earrings_Robert S. Withers, 1979.jpg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "",
|
"title": "Book of Days",
|
||||||
"parent_dir": "films",
|
"details": "Meredith Monk, 1988",
|
||||||
"media": "_74 Ellis Island.m4v"
|
"parent_dir": "Films",
|
||||||
|
"media": "Book of Days_Meredith Monk, 1988.m4v",
|
||||||
|
"image": "Book of Days_Meredith Monk, 1988.jpg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "",
|
"title": "Ellis Island",
|
||||||
"parent_dir": "films",
|
"details": "Meredith Monk and Bob Rosen, 1981",
|
||||||
"media": "_75 Book of Days.m4v"
|
"parent_dir": "Films",
|
||||||
|
"media": "Ellis Island_Meredith Monk and Bob Rosen, 1981.m4v",
|
||||||
|
"image": "Ellis Island_Meredith Monk and Bob Rosen, 1981.jpg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "",
|
"title": "Paris",
|
||||||
"parent_dir": "films",
|
"details": "Meredith Monk and Ping Chong, 1982",
|
||||||
"media": "_76 1982 Paris KTCA (full).m4v"
|
"parent_dir": "Films",
|
||||||
|
"media": "Paris_Meredith Monk and Ping Chong, 1982.m4v",
|
||||||
|
"image": "Paris_Meredith Monk and Ping Chong, 1982.jpg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "",
|
"title": "Quarry",
|
||||||
"parent_dir": "films",
|
"details": "1977",
|
||||||
"media": "_77 TurtleDreams(Waltz)_Stereo_Tranfer1inchApril2018.m4v"
|
"parent_dir": "Films",
|
||||||
|
"media": "Quarry_1977.m4v",
|
||||||
|
"image": "Quarry_1977.jpg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Turtle Dreams (Waltz)",
|
||||||
|
"details": "Meredith Monk, 1983",
|
||||||
|
"parent_dir": "Films",
|
||||||
|
"media": "Turtle Dreams (Waltz)_Meredith Monk, 1983.m4v",
|
||||||
|
"image": "Turtle Dreams (Waltz)_Meredith Monk, 1983.jpg"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,18 +1 @@
|
||||||
[
|
[]
|
||||||
{
|
|
||||||
"title": "Photo One",
|
|
||||||
"media": "photo_one.jpg"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Photo Two",
|
|
||||||
"media": "photo_two.jpg"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Photo Three",
|
|
||||||
"media": "photo_three.jpg"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Photo Four",
|
|
||||||
"media": "photo_four.jpg"
|
|
||||||
}
|
|
||||||
]
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,8 +1 @@
|
||||||
[
|
[]
|
||||||
{
|
|
||||||
"title": "",
|
|
||||||
"parent_dir": "music_sound_unpublished",
|
|
||||||
"media": "no content recieved",
|
|
||||||
"tracks": []
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
|
@ -1,184 +1,510 @@
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"title": "",
|
"title": "Beginnings",
|
||||||
|
"details": "Tzadik, 2009",
|
||||||
"parent_dir": "music_sound_various",
|
"parent_dir": "music_sound_various",
|
||||||
"media": "MONK MIX Remixes and Interpretations of Music by Meredith Monk CD1",
|
"media": "Beginnings_Tzadik, 2009",
|
||||||
|
"image": "Beginnings_Tzadik, 2009.jpg",
|
||||||
"album": true,
|
"album": true,
|
||||||
"tracks": [
|
"tracks": [
|
||||||
"01 Gotham Lullaby (Featuring Björk With The Brodsky Quartet).mp3",
|
{
|
||||||
"02 Caldera Chimera (Featuring Gabriel Prokofiev Remix).mp3",
|
"title": "_60_01 Greensleeves",
|
||||||
"03 Click Song #1 (Featuring Don Byron).mp3",
|
"media": "_60_01 Greensleeves.mp3"
|
||||||
"04 Double Fiesta (Featuring Meredith Monk & Bang On A Can).mp3",
|
},
|
||||||
"05 Astronaut Anthem (Featuring Sakamoto Remix).mp3",
|
{
|
||||||
"06 Shaking (Featuring Lukas Ligeti) [Pyrolator Remix].mp3",
|
"title": "_60_02 Nota",
|
||||||
"07 Last Song (Featuring Caetano Veloso).mp3",
|
"media": "_60_02 Nota.mp3"
|
||||||
"08 Fat Stream (Featuring Nico_s Piano Homage).mp3",
|
},
|
||||||
"09 Wheel (Featuring John Hollenbeck & Theo Bleckmann).mp3",
|
{
|
||||||
"10 Scared Song (Featuring Pamela Z).mp3",
|
"title": "_60_03 Duet For Voice And Echoplex",
|
||||||
"11 Boat Song (Featuring Rubin Kodheli).mp3",
|
"media": "_60_03 Duet For Voice And Echoplex.mp3"
|
||||||
"12 Gathering (Featuring Lee Ranaldo Remix).mp3",
|
},
|
||||||
"13 Evening (Featuring Henry Grimes Remix).mp3"
|
{
|
||||||
|
"title": "_60_04 Candy Bullets And Moon",
|
||||||
|
"media": "_60_04 Candy Bullets And Moon.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_60_05 Trance",
|
||||||
|
"media": "_60_05 Trance.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_60_06 Epic I",
|
||||||
|
"media": "_60_06 Epic I.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_60_07 Paris",
|
||||||
|
"media": "_60_07 Paris.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_60_08 Biography",
|
||||||
|
"media": "_60_08 Biography.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_60_09 Mill",
|
||||||
|
"media": "_60_09 Mill.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_60_10 The Tale",
|
||||||
|
"media": "_60_10 The Tale.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_60_11 Quarry Weave",
|
||||||
|
"media": "_60_11 Quarry Weave.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_60_12 Epic II",
|
||||||
|
"media": "_60_12 Epic II.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_60_13 Tower",
|
||||||
|
"media": "_60_13 Tower.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_60_14 Mill",
|
||||||
|
"media": "_60_14 Mill.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_60_15 Do You Be_",
|
||||||
|
"media": "_60_15 Do You Be_.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_60_16 Quarry Procession",
|
||||||
|
"media": "_60_16 Quarry Procession.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_60_17 Porch",
|
||||||
|
"media": "_60_17 Porch.mp3"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "",
|
"title": "Biography (from Education of the Girlchild)",
|
||||||
|
"details": "Big Ego Records, 1978",
|
||||||
"parent_dir": "music_sound_various",
|
"parent_dir": "music_sound_various",
|
||||||
"media": "MONK MIX Remixes and Interpretations of Music by Meredith Monk CD2",
|
"media": "Biography (from Education of the Girlchild)_Big Ego Records, 1978",
|
||||||
|
"image": "Biography (from Education of the Girlchild)_Big Ego Records, 1978.jpg",
|
||||||
"album": true,
|
"album": true,
|
||||||
"tracks": [
|
"tracks": [
|
||||||
"01 Dawn (feat. Dj Spooky Remix).mp3",
|
{
|
||||||
"02 Rain (feat. Vijay Iyer Revelation Mix Featuring Latasha N. Nevada Diggs).mp3",
|
"title": "_63_13 Biography_Big Ego album",
|
||||||
"03 Atlas Ascending (feat. Todd Reynolds Remix).mp3",
|
"media": "_63_13 Biography_Big Ego album.m4a"
|
||||||
"04 Epic (feat. Dj Rekha & Raj Star Remix).mp3",
|
}
|
||||||
"05 Memory Song (feat. Miho Hatori Remix).mp3",
|
|
||||||
"06 Travellers (feat. King Britt Idm Mix).mp3",
|
|
||||||
"07 Night Vs. Lullaby (feat. Matt Marks Remix).mp3",
|
|
||||||
"08 Double Fiesta (feat. Arto Lindsay Remix).mp3",
|
|
||||||
"09 Long Shadows (feat. Scanner Entwine Mix).mp3",
|
|
||||||
"10 Dolmen Music, Part 1 (feat. Shodekeh's Embody & Continuums Remix).mp3",
|
|
||||||
"11 Braid (feat. High Priest _ Hprizm Ghostlover Remix).mp3",
|
|
||||||
"12 Vocal_ Mill Feuille (feat. Sussan Deyhim Remix).mp3"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "",
|
"title": "KEY: an albm of invisible theater",
|
||||||
|
"details": "Lovely Music, 1971",
|
||||||
"parent_dir": "music_sound_various",
|
"parent_dir": "music_sound_various",
|
||||||
"media": "_55 Songs from the Hill-Tablet",
|
"media": "KEY: an albm of invisible theater_Lovely Music, 1971",
|
||||||
|
"image": "KEY: an albm of invisible theater_Lovely Music, 1971.jpg",
|
||||||
"album": true,
|
"album": true,
|
||||||
"tracks": [
|
"tracks": [
|
||||||
"_55_01 Lullaby.mp3",
|
{
|
||||||
"_55_02 Mesa.mp3",
|
"title": "_57_01 Porch",
|
||||||
"_55_03 Jade (old woman's song).mp3",
|
"media": "_57_01 Porch.mp3"
|
||||||
"_55_04 Wa-lie-oh.mp3",
|
},
|
||||||
"_55_05 Insect.mp3",
|
{
|
||||||
"_55_06 Descending.mp3",
|
"title": "_57_02 Understreet",
|
||||||
"_55_07 Silo.mp3",
|
"media": "_57_02 Understreet.mp3"
|
||||||
"_55_08 Bird Code.mp3",
|
},
|
||||||
"_55_09 Jew's Harp.mp3",
|
{
|
||||||
"_55_10 Prairie Ghost.mp3",
|
"title": "_57_03 What Does It Mean_",
|
||||||
"_55_11 Tablet.mp3"
|
"media": "_57_03 What Does It Mean_.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_57_04 Vision #1",
|
||||||
|
"media": "_57_04 Vision #1.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_57_05 Fat Stream",
|
||||||
|
"media": "_57_05 Fat Stream.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_57_06 Vision #2",
|
||||||
|
"media": "_57_06 Vision #2.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_57_07 Do You Be_",
|
||||||
|
"media": "_57_07 Do You Be_.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_57_08 Vision (#3)",
|
||||||
|
"media": "_57_08 Vision (#3).mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_57_09 Change",
|
||||||
|
"media": "_57_09 Change.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_57_10 Dungeon",
|
||||||
|
"media": "_57_10 Dungeon.mp3"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "",
|
"title": "MEMORY GAME",
|
||||||
|
"details": "Cantaloupe Music, 2020",
|
||||||
"parent_dir": "music_sound_various",
|
"parent_dir": "music_sound_various",
|
||||||
"media": "_56 Our Lady of Late",
|
"media": "MEMORY GAME_Cantaloupe Music, 2020",
|
||||||
|
"image": "MEMORY GAME_Cantaloupe Music, 2020.jpg",
|
||||||
"album": true,
|
"album": true,
|
||||||
"tracks": [
|
"tracks": [
|
||||||
"_56_01 Prologue.mp3",
|
{
|
||||||
"_56_02 Unison.mp3",
|
"title": "_58_01 Spaceship",
|
||||||
"_56_03 Knee.mp3",
|
"media": "_58_01 Spaceship.mp3"
|
||||||
"_56_04 Hey Rhythm.mp3",
|
},
|
||||||
"_56_05 Cow Song.mp3",
|
{
|
||||||
"_56_06 Sigh.mp3",
|
"title": "_58_02 Gamemaster's Song",
|
||||||
"_56_07 Morning.mp3",
|
"media": "_58_02 Gamemaster's Song.mp3"
|
||||||
"_56_08 Slide.mp3",
|
},
|
||||||
"_56_09 Waltz.mp3",
|
{
|
||||||
"_56_10 Prophecy.mp3",
|
"title": "_58_03 Migration",
|
||||||
"_56_11 Dumb.mp3",
|
"media": "_58_03 Migration.mp3"
|
||||||
"_56_12 Conversation.mp3",
|
},
|
||||||
"_56_13 Low Ring.mp3",
|
{
|
||||||
"_56_14 High Ring.mp3",
|
"title": "_58_04 Memory Song",
|
||||||
"_56_15 Free.mp3",
|
"media": "_58_04 Memory Song.mp3"
|
||||||
"_56_16 Edge.mp3",
|
},
|
||||||
"_56_17 Scale Down.mp3",
|
{
|
||||||
"_56_18 Epilogue.mp3"
|
"title": "_58_05 Downfall",
|
||||||
|
"media": "_58_05 Downfall.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_58_06 Waltz In 5s",
|
||||||
|
"media": "_58_06 Waltz In 5s.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_58_07 Tokyo CHa Cha",
|
||||||
|
"media": "_58_07 Tokyo CHa Cha.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_58_08 Totentanz",
|
||||||
|
"media": "_58_08 Totentanz.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_58_09 Double Fiesta",
|
||||||
|
"media": "_58_09 Double Fiesta.mp3"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "",
|
"title": "MONK MIX Remixes and Interpretations of Music by Meredith Monk (CD1)",
|
||||||
|
"details": "The House Foundation for the Arts, 2012",
|
||||||
"parent_dir": "music_sound_various",
|
"parent_dir": "music_sound_various",
|
||||||
"media": "_57 KEY-an album of invisible theater",
|
"media": "MONK MIX Remixes and Interpretations of Music by Meredith Monk (CD1)_The House Foundation for the Arts, 2012",
|
||||||
|
"image": "MONK MIX Remixes and Interpretations of Music by Meredith Monk (CD1)_The House Foundation for the Arts, 2012.jpg",
|
||||||
"album": true,
|
"album": true,
|
||||||
"tracks": [
|
"tracks": [
|
||||||
"_57_01 Porch.mp3",
|
{
|
||||||
"_57_02 Understreet.mp3",
|
"title": "01 Gotham Lullaby (Featuring Björk With The Brodsky Quartet)",
|
||||||
"_57_03 What Does It Mean_.mp3",
|
"media": "01 Gotham Lullaby (Featuring Björk With The Brodsky Quartet).mp3"
|
||||||
"_57_04 Vision #1.mp3",
|
},
|
||||||
"_57_05 Fat Stream.mp3",
|
{
|
||||||
"_57_06 Vision #2.mp3",
|
"title": "02 Caldera Chimera (Featuring Gabriel Prokofiev Remix)",
|
||||||
"_57_07 Do You Be_.mp3",
|
"media": "02 Caldera Chimera (Featuring Gabriel Prokofiev Remix).mp3"
|
||||||
"_57_08 Vision (#3).mp3",
|
},
|
||||||
"_57_09 Change.mp3",
|
{
|
||||||
"_57_10 Dungeon.mp3"
|
"title": "03 Click Song #1 (Featuring Don Byron)",
|
||||||
|
"media": "03 Click Song #1 (Featuring Don Byron).mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "04 Double Fiesta (Featuring Meredith Monk & Bang On A Can)",
|
||||||
|
"media": "04 Double Fiesta (Featuring Meredith Monk & Bang On A Can).mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "05 Astronaut Anthem (Featuring Sakamoto Remix)",
|
||||||
|
"media": "05 Astronaut Anthem (Featuring Sakamoto Remix).mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "06 Shaking (Featuring Lukas Ligeti) [Pyrolator Remix]",
|
||||||
|
"media": "06 Shaking (Featuring Lukas Ligeti) [Pyrolator Remix].mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "07 Last Song (Featuring Caetano Veloso)",
|
||||||
|
"media": "07 Last Song (Featuring Caetano Veloso).mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "08 Fat Stream (Featuring Nico_s Piano Homage)",
|
||||||
|
"media": "08 Fat Stream (Featuring Nico_s Piano Homage).mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "09 Wheel (Featuring John Hollenbeck & Theo Bleckmann)",
|
||||||
|
"media": "09 Wheel (Featuring John Hollenbeck & Theo Bleckmann).mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "10 Scared Song (Featuring Pamela Z)",
|
||||||
|
"media": "10 Scared Song (Featuring Pamela Z).mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "11 Boat Song (Featuring Rubin Kodheli)",
|
||||||
|
"media": "11 Boat Song (Featuring Rubin Kodheli).mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "12 Gathering (Featuring Lee Ranaldo Remix)",
|
||||||
|
"media": "12 Gathering (Featuring Lee Ranaldo Remix).mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "13 Evening (Featuring Henry Grimes Remix)",
|
||||||
|
"media": "13 Evening (Featuring Henry Grimes Remix).mp3"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "",
|
"title": "MONK MIX Remixes and Interpretations of Music by Meredith Monk (CD2)",
|
||||||
|
"details": "The House Foundation for the Arts, 2012",
|
||||||
"parent_dir": "music_sound_various",
|
"parent_dir": "music_sound_various",
|
||||||
"media": "_58 MEMORY GAME",
|
"media": "MONK MIX Remixes and Interpretations of Music by Meredith Monk (CD2)_The House Foundation for the Arts, 2012",
|
||||||
|
"image": "MONK MIX Remixes and Interpretations of Music by Meredith Monk (CD2)_The House Foundation for the Arts, 2012.jpg",
|
||||||
"album": true,
|
"album": true,
|
||||||
"tracks": [
|
"tracks": [
|
||||||
"_58_01 Spaceship.mp3",
|
{
|
||||||
"_58_02 Gamemaster's Song.mp3",
|
"title": "01 Dawn (feat. Dj Spooky Remix)",
|
||||||
"_58_03 Migration.mp3",
|
"media": "01 Dawn (feat. Dj Spooky Remix).mp3"
|
||||||
"_58_04 Memory Song.mp3",
|
},
|
||||||
"_58_05 Downfall.mp3",
|
{
|
||||||
"_58_06 Waltz In 5s.mp3",
|
"title": "02 Rain (feat. Vijay Iyer Revelation Mix Featuring Latasha N. Nevada Diggs)",
|
||||||
"_58_07 Tokyo CHa Cha.mp3",
|
"media": "02 Rain (feat. Vijay Iyer Revelation Mix Featuring Latasha N. Nevada Diggs).mp3"
|
||||||
"_58_08 Totentanz.mp3",
|
},
|
||||||
"_58_09 Double Fiesta.mp3"
|
{
|
||||||
|
"title": "03 Atlas Ascending (feat. Todd Reynolds Remix)",
|
||||||
|
"media": "03 Atlas Ascending (feat. Todd Reynolds Remix).mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "04 Epic (feat. Dj Rekha & Raj Star Remix)",
|
||||||
|
"media": "04 Epic (feat. Dj Rekha & Raj Star Remix).mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "05 Memory Song (feat. Miho Hatori Remix)",
|
||||||
|
"media": "05 Memory Song (feat. Miho Hatori Remix).mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "06 Travellers (feat. King Britt Idm Mix)",
|
||||||
|
"media": "06 Travellers (feat. King Britt Idm Mix).mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "07 Night Vs. Lullaby (feat. Matt Marks Remix)",
|
||||||
|
"media": "07 Night Vs. Lullaby (feat. Matt Marks Remix).mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "08 Double Fiesta (feat. Arto Lindsay Remix)",
|
||||||
|
"media": "08 Double Fiesta (feat. Arto Lindsay Remix).mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "09 Long Shadows (feat. Scanner Entwine Mix)",
|
||||||
|
"media": "09 Long Shadows (feat. Scanner Entwine Mix).mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "10 Dolmen Music, Part 1 (feat. Shodekeh's Embody & Continuums Remix)",
|
||||||
|
"media": "10 Dolmen Music, Part 1 (feat. Shodekeh's Embody & Continuums Remix).mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "11 Braid (feat. High Priest _ Hprizm Ghostlover Remix)",
|
||||||
|
"media": "11 Braid (feat. High Priest _ Hprizm Ghostlover Remix).mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "12 Vocal_ Mill Feuille (feat. Sussan Deyhim Remix)",
|
||||||
|
"media": "12 Vocal_ Mill Feuille (feat. Sussan Deyhim Remix).mp3"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "",
|
"title": "Monk and the Abbess",
|
||||||
|
"details": "BMG, 1996",
|
||||||
"parent_dir": "music_sound_various",
|
"parent_dir": "music_sound_various",
|
||||||
"media": "_60 Beginnings",
|
"media": "Monk and the Abbess_BMG, 1996",
|
||||||
|
"image": "Monk and the Abbess_BMG, 1996.jpg",
|
||||||
"album": true,
|
"album": true,
|
||||||
"tracks": [
|
"tracks": [
|
||||||
"_60_01 Greensleeves.mp3",
|
{
|
||||||
"_60_02 Nota.mp3",
|
"title": "_62_05 Dawn (1985)",
|
||||||
"_60_03 Duet For Voice And Echoplex.mp3",
|
"media": "_62_05 Dawn (1985).mp3"
|
||||||
"_60_04 Candy Bullets And Moon.mp3",
|
},
|
||||||
"_60_05 Trance.mp3",
|
{
|
||||||
"_60_06 Epic I.mp3",
|
"title": "_62_06 Quarry weave 1 (1976)",
|
||||||
"_60_07 Paris.mp3",
|
"media": "_62_06 Quarry weave 1 (1976).mp3"
|
||||||
"_60_08 Biography.mp3",
|
},
|
||||||
"_60_09 Mill.mp3",
|
{
|
||||||
"_60_10 The Tale.mp3",
|
"title": "_62_07 Quarry lullaby (1976)",
|
||||||
"_60_11 Quarry Weave.mp3",
|
"media": "_62_07 Quarry lullaby (1976).mp3"
|
||||||
"_60_12 Epic II.mp3",
|
},
|
||||||
"_60_13 Tower.mp3",
|
{
|
||||||
"_60_14 Mill.mp3",
|
"title": "_62_08 Quarry weave 2 (1976)",
|
||||||
"_60_15 Do You Be_.mp3",
|
"media": "_62_08 Quarry weave 2 (1976).mp3"
|
||||||
"_60_16 Quarry Procession.mp3",
|
},
|
||||||
"_60_17 Porch.mp3"
|
{
|
||||||
|
"title": "_62_09 Farmer's song (1974)",
|
||||||
|
"media": "_62_09 Farmer's song (1974).mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_62_10 Astronaut anthem (1983)",
|
||||||
|
"media": "_62_10 Astronaut anthem (1983).mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_62_11 Nightfall (1995)",
|
||||||
|
"media": "_62_11 Nightfall (1995).mp3"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "",
|
"title": "Our Lady of Late",
|
||||||
|
"details": "Minona Records, 1974 and Wergo, 1986",
|
||||||
"parent_dir": "music_sound_various",
|
"parent_dir": "music_sound_various",
|
||||||
"media": "_61 Radio Songs",
|
"media": "Our Lady of Late_Minona Records, 1974 and Wergo, 1986",
|
||||||
|
"image": "Our Lady of Late_Minona Records, 1974 and Wergo, 1986.jpg",
|
||||||
"album": true,
|
"album": true,
|
||||||
"tracks": [
|
"tracks": [
|
||||||
"_61_01 Quarry Radio.mp3",
|
{
|
||||||
"_61_02 Gotham Blues.mp3",
|
"title": "_56_01 Prologue",
|
||||||
"_61_03 Quarry Waltz.mp3",
|
"media": "_56_01 Prologue.mp3"
|
||||||
"_61_04 Gotham Lullaby.mp3"
|
},
|
||||||
|
{
|
||||||
|
"title": "_56_02 Unison",
|
||||||
|
"media": "_56_02 Unison.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_56_03 Knee",
|
||||||
|
"media": "_56_03 Knee.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_56_04 Hey Rhythm",
|
||||||
|
"media": "_56_04 Hey Rhythm.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_56_05 Cow Song",
|
||||||
|
"media": "_56_05 Cow Song.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_56_06 Sigh",
|
||||||
|
"media": "_56_06 Sigh.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_56_07 Morning",
|
||||||
|
"media": "_56_07 Morning.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_56_08 Slide",
|
||||||
|
"media": "_56_08 Slide.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_56_09 Waltz",
|
||||||
|
"media": "_56_09 Waltz.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_56_10 Prophecy",
|
||||||
|
"media": "_56_10 Prophecy.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_56_11 Dumb",
|
||||||
|
"media": "_56_11 Dumb.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_56_12 Conversation",
|
||||||
|
"media": "_56_12 Conversation.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_56_13 Low Ring",
|
||||||
|
"media": "_56_13 Low Ring.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_56_14 High Ring",
|
||||||
|
"media": "_56_14 High Ring.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_56_15 Free",
|
||||||
|
"media": "_56_15 Free.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_56_16 Edge",
|
||||||
|
"media": "_56_16 Edge.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_56_17 Scale Down",
|
||||||
|
"media": "_56_17 Scale Down.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_56_18 Epilogue",
|
||||||
|
"media": "_56_18 Epilogue.mp3"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "",
|
"title": "Radio Songs",
|
||||||
|
"details": "The sound of White Columns, 2014",
|
||||||
"parent_dir": "music_sound_various",
|
"parent_dir": "music_sound_various",
|
||||||
"media": "_62 Monk and the Abbiss",
|
"media": "Radio Songs_The sound of White Columns, 2014",
|
||||||
|
"image": "Radio Songs_The sound of White Columns, 2014.jpg",
|
||||||
"album": true,
|
"album": true,
|
||||||
"tracks": [
|
"tracks": [
|
||||||
"_62_05 Dawn (1985).mp3",
|
{
|
||||||
"_62_06 Quarry weave 1 (1976).mp3",
|
"title": "_61_01 Quarry Radio",
|
||||||
"_62_07 Quarry lullaby (1976).mp3",
|
"media": "_61_01 Quarry Radio.mp3"
|
||||||
"_62_08 Quarry weave 2 (1976).mp3",
|
},
|
||||||
"_62_09 Farmer's song (1974).mp3",
|
{
|
||||||
"_62_10 Astronaut anthem (1983).mp3",
|
"title": "_61_02 Gotham Blues",
|
||||||
"_62_11 Nightfall (1995).mp3"
|
"media": "_61_02 Gotham Blues.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_61_03 Quarry Waltz",
|
||||||
|
"media": "_61_03 Quarry Waltz.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_61_04 Gotham Lullaby",
|
||||||
|
"media": "_61_04 Gotham Lullaby.mp3"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "",
|
"title": "Songs from the Hill-Tablet",
|
||||||
|
"details": "Wergo, 1979",
|
||||||
"parent_dir": "music_sound_various",
|
"parent_dir": "music_sound_various",
|
||||||
"media": "_63 Biography (from Education of the Girlchild)",
|
"media": "Songs from the Hill-Tablet_Wergo, 1979",
|
||||||
|
"image": "Songs from the Hill-Tablet_Wergo, 1979.jpg",
|
||||||
"album": true,
|
"album": true,
|
||||||
"tracks": [
|
"tracks": [
|
||||||
"_63_13 Biography_Big Ego album.m4a"
|
{
|
||||||
|
"title": "_55_01 Lullaby",
|
||||||
|
"media": "_55_01 Lullaby.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_55_02 Mesa",
|
||||||
|
"media": "_55_02 Mesa.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_55_03 Jade (old woman's song)",
|
||||||
|
"media": "_55_03 Jade (old woman's song).mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_55_04 Wa-lie-oh",
|
||||||
|
"media": "_55_04 Wa-lie-oh.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_55_05 Insect",
|
||||||
|
"media": "_55_05 Insect.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_55_06 Descending",
|
||||||
|
"media": "_55_06 Descending.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_55_07 Silo",
|
||||||
|
"media": "_55_07 Silo.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_55_08 Bird Code",
|
||||||
|
"media": "_55_08 Bird Code.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_55_09 Jew's Harp",
|
||||||
|
"media": "_55_09 Jew's Harp.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_55_10 Prairie Ghost",
|
||||||
|
"media": "_55_10 Prairie Ghost.mp3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "_55_11 Tablet",
|
||||||
|
"media": "_55_11 Tablet.mp3"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
|
@ -1 +0,0 @@
|
||||||
[]
|
|
|
@ -1,63 +1,65 @@
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"title": "Specimen Days",
|
"title": "Cellular Songs",
|
||||||
"details": "The Public Theater, New York, 1981. 1:26:17",
|
"details": "UCLA, Los Angeles, California, 2019",
|
||||||
"media": "-34 Specimen Days.m4v",
|
"parent_dir": "theatre",
|
||||||
|
"media": "Cellular Songs_UCLA, Los Angeles, California, 2019.mp4",
|
||||||
|
"image": "Cellular Songs_UCLA, Los Angeles, California, 2019.jpg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "The Games: a science fiction opera",
|
"title": "Education of the Girlchild",
|
||||||
"details": "Brooklyn Academy of Music (BAM), New York, 1984. 2:00:35",
|
"details": "solo, Common Ground, NYC, 1973",
|
||||||
"media": "-37 MMonk_TheGames_BAM1984.m4v",
|
"parent_dir": "theatre",
|
||||||
|
"media": "Education of the Girlchild_solo, Common Ground, NYC, 1973..m4v",
|
||||||
|
"image": "Education of the Girlchild_solo, Common Ground, NYC, 1973..jpg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Facing North",
|
"title": "Facing North",
|
||||||
"details": "George Washington University, Washington, DC, 1992. 54:32",
|
"details": "George Washington University, Washington, DC, 1992",
|
||||||
},
|
"parent_dir": "theatre",
|
||||||
{
|
"media": "Facing North_George Washington University, Washington, DC, 1992.mp4",
|
||||||
"title": "The Politics of Quiet",
|
"image": "Facing North_George Washington University, Washington, DC, 1992.jpg"
|
||||||
"details": "Brooklyn Academy of Music, BAM, New York, 1996. 1:43:46",
|
|
||||||
"media": "-36 The Politics of Quiet at BAM - 10.13.96.m4v",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Magic Frequencies (excerpts)",
|
"title": "Magic Frequencies (excerpts)",
|
||||||
"details": "Muffathalle, Munich, Germany, 1998. 25:49",
|
"details": "Muffathalle, Munich, Germany, 1998",
|
||||||
"media": "-42 1998 Magic Frequencies (excerpts) BetaCamSP transfer 2021.m4v"
|
"parent_dir": "theatre",
|
||||||
|
"media": "Magic Frequencies (excerpts)_Muffathalle, Munich, Germany, 1998.m4v",
|
||||||
|
"image": "Magic Frequencies (excerpts)_Muffathalle, Munich, Germany, 1998.jpg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title":"A Celebration Service",
|
"title": "Meredith Monk",
|
||||||
"details": "St. Mark’s Church, NYC, 1999. 55:02",
|
"details": "A Celebration Service",
|
||||||
"media": "-35 Meredith Monk - A Celebration Service_ Danspace at St. Mark's Church_1999.m4v",
|
"parent_dir": "theatre",
|
||||||
|
"media": "Meredith Monk_A Celebration Service_ Danspace at St. Mark's Church_1999.m4v",
|
||||||
|
"image": "Meredith Monk_A Celebration Service_ Danspace at St. Mark's Church_1999.jpg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
impermanence, Brooklyn Academy of Music (BAM), New York, 2006. 1:22:03
|
"title": "Songs of Ascension",
|
||||||
|
"details": "Brooklyn Academy of Music (BAM), New York, 2009",
|
||||||
|
"parent_dir": "theatre",
|
||||||
|
"media": "Songs of Ascension_Brooklyn Academy of Music (BAM), New York, 2009.mp4",
|
||||||
|
"image": "Songs of Ascension_Brooklyn Academy of Music (BAM), New York, 2009.jpg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Songs of Ascension, Brooklyn Academy of Music (BAM), New York, 2009. 1:17:29
|
"title": "Specimen Days",
|
||||||
|
"details": "The Public Theater, New York, 1981",
|
||||||
|
"parent_dir": "theatre",
|
||||||
|
"media": "Specimen Days_The Public Theater, New York, 1981.m4v",
|
||||||
|
"image": "Specimen Days_The Public Theater, New York, 1981.jpg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "On Behalf of Nature",
|
"title": "The Games",
|
||||||
"details": "UCLA, Los Angeles, California, 2013. 1:14:55"
|
"details": "a science fiction opera, Brooklyn Academy of Music (BAM), New York, 1984",
|
||||||
"media": ""
|
"parent_dir": "theatre",
|
||||||
|
"media": "The Games_a science fiction opera, Brooklyn Academy of Music (BAM), New York, 1984.m4v",
|
||||||
|
"image": "The Games_a science fiction opera, Brooklyn Academy of Music (BAM), New York, 1984.jpg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "impermanence",
|
||||||
|
"details": "Brooklyn Academy of Music (BAM), New York, 2006",
|
||||||
|
"parent_dir": "theatre",
|
||||||
|
"media": "impermanence_Brooklyn Academy of Music (BAM), New York, 2006.mp4",
|
||||||
|
"image": "impermanence_Brooklyn Academy of Music (BAM), New York, 2006.jpg"
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
Cellular Songs, UCLA, Los Angeles, California, 2019. 1:24:07
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
"media": "-29 Education of the Gildchild solo_Common Ground_1973.m4v",
|
|
||||||
"media": "-30 Quarry_full film_1977_FINAL_20200127_added to dropbox.m4v",
|
|
||||||
"media": "-33 MEREDITH_MONK_SOLO_CONCERT_1980.m4v",
|
|
||||||
"media": "-38 MeredithMonk_SoloConcert_College des Bernadins Paris_20120516.m4v",
|
|
||||||
"media": "-39 Meredith Monk with Katie Geissinger in Concert, Haus der Kunst, Munich, Germany (2012).m4v",
|
|
||||||
"media": "-40 Candy_Bullets_and_Moon.m4v",
|
|
||||||
"media": "-41 Monk_Anthem_Final.m4v",
|
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,6 +1,29 @@
|
||||||
import fs from 'fs/promises'
|
import fs from 'fs/promises'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
|
import { exec } from 'child_process'
|
||||||
|
|
||||||
|
// WAVEFORM GENERATION
|
||||||
|
// TODO@mx use node-js library
|
||||||
|
async function generateWaveform(audioFile, outputDir) {
|
||||||
|
const inputFile = path.join(outputDir, audioFile)
|
||||||
|
audioFile = audioFile.replace(/\.[^/.]+$/, '.png')
|
||||||
|
const outputPath = path.join(outputDir || '.', audioFile)
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
exec(
|
||||||
|
`audiowaveform -i '${inputFile}' -o '${outputPath}' --output-format png -z auto -w 640 -h 180 --background-color 00000000 --waveform-color FFFFFF50 --waveform-style bars --bar-style rounded --border-color 00000000 --bar-width 4 --bar-gap 6 --no-axis-labels`,
|
||||||
|
(error, stdOut) => {
|
||||||
|
if (error) {
|
||||||
|
console.error(error)
|
||||||
|
reject(error)
|
||||||
|
} else {
|
||||||
|
resolve(audioFile)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// MAIN FUNCTION
|
||||||
async function main() {
|
async function main() {
|
||||||
// variable for incoming variable
|
// variable for incoming variable
|
||||||
let mediaDir = ''
|
let mediaDir = ''
|
||||||
|
@ -8,90 +31,189 @@ async function main() {
|
||||||
let recurse = false
|
let recurse = false
|
||||||
let imagesOnly = false
|
let imagesOnly = false
|
||||||
let dryRun = false
|
let dryRun = false
|
||||||
|
let formatted = null
|
||||||
|
let waveform = false
|
||||||
|
let update = []
|
||||||
|
|
||||||
// get command line arguments
|
// get command line arguments
|
||||||
process.argv.forEach(function (val, index) {
|
process.argv.forEach(function (val, index) {
|
||||||
// console.log(index + ': ' + val)
|
// console.log(index + ': ' + val)
|
||||||
if (val == '-dir') {
|
switch (val) {
|
||||||
// console.log(process.argv[index + 1])
|
case '-dir':
|
||||||
mediaDir = process.argv[index + 1] || ''
|
mediaDir = process.argv[index + 1] || ''
|
||||||
}
|
break
|
||||||
|
case '-o':
|
||||||
|
outputDir = process.argv[index + 1] || ''
|
||||||
|
break
|
||||||
|
case '-u':
|
||||||
|
update = process.argv[index + 1].match(/(title|details|media|image[s]*|tracks|)/i)
|
||||||
|
? process.argv[index + 1]
|
||||||
|
.split(',')
|
||||||
|
.filter(a => [
|
||||||
|
'title',
|
||||||
|
'details',
|
||||||
|
'media',
|
||||||
|
'image',
|
||||||
|
'tracks',
|
||||||
|
'images'
|
||||||
|
].includes(a))
|
||||||
|
: true
|
||||||
|
break
|
||||||
|
case '-r':
|
||||||
|
recurse = true
|
||||||
|
break
|
||||||
|
case '--images-only':
|
||||||
|
imagesOnly = true
|
||||||
|
break
|
||||||
|
case '--dry-run':
|
||||||
|
dryRun = true
|
||||||
|
break
|
||||||
|
case '--formatted':
|
||||||
|
formatted = ['parent', 'recurse', 'both' ].includes(process.argv[index + 1]) ? process.argv[index + 1] : 'both'
|
||||||
|
break
|
||||||
|
case '--gen-waveform':
|
||||||
|
waveform = true
|
||||||
|
break
|
||||||
|
|
||||||
if (val == '--dry-run') {
|
default:
|
||||||
dryRun = true
|
break
|
||||||
}
|
|
||||||
|
|
||||||
if (val == '--images') {
|
|
||||||
imagesOnly = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if (val == '-r' || val == '-R') {
|
|
||||||
recurse = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if (val == '-o') {
|
|
||||||
outputDir = process.argv[index + 1]
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// if no media dir jump out
|
// if no media dir passed jump out
|
||||||
if (!mediaDir) {
|
if (!mediaDir) {
|
||||||
console.log('no directory passed to script')
|
console.log('no directory passed to script')
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
//
|
||||||
|
// read directory
|
||||||
|
const dirList = await fs.readdir(mediaDir)
|
||||||
|
|
||||||
// variable to hold media
|
// variable to hold media
|
||||||
let media = []
|
let media = []
|
||||||
let images = []
|
let images = []
|
||||||
|
|
||||||
// read directory
|
|
||||||
const dirList = await fs.readdir(mediaDir)
|
|
||||||
|
|
||||||
if (!recurse) {
|
// If recursing we are making the "media" the directories where we will find the
|
||||||
|
// acutal media to playback or see
|
||||||
|
if (recurse) {
|
||||||
|
media = dirList.filter(i => !i.match(/\.[^/.]+$/))
|
||||||
|
} else {
|
||||||
media = dirList.filter(i => i.match(/.(mp\d|m\d\w)$/i))
|
media = dirList.filter(i => i.match(/.(mp\d|m\d\w)$/i))
|
||||||
images = dirList.filter(i => i.match(/.(jp\w*g|png)$/i))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// create an array of images found in the directory as well
|
||||||
|
images = dirList.filter(i => i.match(/.(jp\w*g|png)$/i))
|
||||||
|
|
||||||
// clean up directory for json
|
// clean up passed directory for json
|
||||||
let parent_dir = mediaDir
|
let parent_dir = mediaDir
|
||||||
.match(/(?<=\/)(\w|\d)+\/*$/i)[0]
|
.match(/(?<=\/)(\w|\d)+\/*$/i)[0]
|
||||||
.replace(/\/$/i, '')
|
.replace(/\/$/i, '')
|
||||||
|
|
||||||
|
// set an output directory if not set by flags
|
||||||
if (!outputDir) {
|
if (!outputDir) {
|
||||||
outputDir = '.'
|
outputDir = '.'
|
||||||
}
|
}
|
||||||
|
|
||||||
const obj = await Promise.all(media.map(async (m, i) => {
|
// THE MAIN EVENT
|
||||||
|
const obj = await Promise.all(media.map(async m => {
|
||||||
|
|
||||||
|
// setup structure
|
||||||
const _r = {
|
const _r = {
|
||||||
title: '',
|
...genMetadata(m, formatted == 'parent' || formatted == 'both'),
|
||||||
details: '',
|
|
||||||
parent_dir,
|
parent_dir,
|
||||||
media: m,
|
media: m,
|
||||||
image: images[i],
|
image: ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if we are scanning for images only, remove the 'image' property
|
||||||
|
// as it will be saved in the media property
|
||||||
|
if (imagesOnly) {
|
||||||
|
delete _r.image
|
||||||
|
} else {
|
||||||
|
if (waveform) {
|
||||||
|
// if waveform generate waveform
|
||||||
|
_r.image = await generateWaveform(m, mediaDir)
|
||||||
|
} else {
|
||||||
|
// if not compare the media name with the image name
|
||||||
|
// and if a match assign it to 'image' variable from earlier
|
||||||
|
_r.image = linkImage(m.replace(/\.[^/.]+$/, ''), images)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if recurse (again) now we are looking for the media in the folders
|
||||||
if (recurse) {
|
if (recurse) {
|
||||||
|
// create full path from the passed dir, and the recuring dir
|
||||||
const rDir = path.join(mediaDir, m)
|
const rDir = path.join(mediaDir, m)
|
||||||
const files = await fs.readdir(rDir)
|
// read the dir
|
||||||
|
let files = await fs.readdir(rDir)
|
||||||
|
// filterout any rogue folders
|
||||||
|
// generate the metadata for each file
|
||||||
|
files = files.filter(f => f.match(/\.[^/.]+$/))
|
||||||
|
files = files.map(f => {
|
||||||
|
const { title, details } = genMetadata(f, formatted == 'recurse' || formatted == 'both')
|
||||||
|
return { title, details, media: f }
|
||||||
|
})
|
||||||
|
|
||||||
_r.album = true
|
// if images only
|
||||||
_r.tracks = files
|
if (imagesOnly) {
|
||||||
|
// setup object per image in array
|
||||||
|
_r.images = files
|
||||||
|
} else {
|
||||||
|
_r.album = true
|
||||||
|
_r.tracks = files
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// return the result to the 'obj' variable
|
||||||
return _r
|
return _r
|
||||||
}))
|
}))
|
||||||
|
|
||||||
const json = JSON.stringify(obj, null, 2)
|
|
||||||
let output = `${parent_dir}.json`
|
|
||||||
|
|
||||||
|
// turn the obj variable into JSON
|
||||||
|
const json = JSON.stringify(obj, null, 2)
|
||||||
|
// set the output filename
|
||||||
|
let outputFile = `${parent_dir}.json`
|
||||||
|
|
||||||
|
// check if file already exists at location
|
||||||
|
// const dataFile = await fs.readFile(path.join(outputDir, outputFile), 'utf8')
|
||||||
|
// console.log(JSON.parse(dataFile) || 'no data file exists')
|
||||||
|
// update only new fields
|
||||||
|
|
||||||
|
// if dryrun
|
||||||
if (dryRun) {
|
if (dryRun) {
|
||||||
|
// just console it out
|
||||||
console.log(json)
|
console.log(json)
|
||||||
} else {
|
} else {
|
||||||
fs.writeFile(path.join(outputDir, output), json)
|
// write it to a file
|
||||||
|
fs.writeFile(path.join(outputDir, outputFile), json)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function genMetadata(dir, formatted) {
|
||||||
|
let title, details
|
||||||
|
|
||||||
|
// if formatted flag set
|
||||||
|
if (formatted) {
|
||||||
|
// split the incoming name from the map on the '_'
|
||||||
|
// and set the first element to title, and the second to details
|
||||||
|
let [ t, d ] = dir.split('_')
|
||||||
|
// assign to return object
|
||||||
|
title = t
|
||||||
|
details = d ? d.replace(/\.+(mp\d|m\dv)$/i, '') : ''
|
||||||
|
} else {
|
||||||
|
// else just set title to filename without extensions
|
||||||
|
title = dir.replace(/\.[^/.]+$/, '')
|
||||||
|
}
|
||||||
|
|
||||||
|
return { title, details }
|
||||||
|
}
|
||||||
|
|
||||||
|
function linkImage(name, images) {
|
||||||
|
return images.find(i => {
|
||||||
|
return i.replace(/\.[^/.]+$/, '') == name
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
main()
|
main()
|
||||||
|
|
50
src/App.js
50
src/App.js
|
@ -1,5 +1,6 @@
|
||||||
import { LitElement, css, html, unsafeCSS } from 'lit'
|
import { LitElement, css, html, unsafeCSS } from 'lit'
|
||||||
import Router from './api/Router.js'
|
import Router from './api/Router.js'
|
||||||
|
import { Task } from '@lit-labs/task'
|
||||||
|
|
||||||
import MainCSS from './assets/styles/main.scss?inline'
|
import MainCSS from './assets/styles/main.scss?inline'
|
||||||
|
|
||||||
|
@ -10,13 +11,17 @@ import './components/Footer.js'
|
||||||
import './assets/styles/main.scss'
|
import './assets/styles/main.scss'
|
||||||
|
|
||||||
export class App extends LitElement {
|
export class App extends LitElement {
|
||||||
static properties = {}
|
static properties = {
|
||||||
|
dialogEl: { state: true }
|
||||||
|
}
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super()
|
super()
|
||||||
}
|
}
|
||||||
|
|
||||||
firstUpdated() {
|
firstUpdated() {
|
||||||
|
this.dialogEl = this.shadowRoot.querySelector('dialog')
|
||||||
|
|
||||||
Router.addEventListener('route-changed', () => {
|
Router.addEventListener('route-changed', () => {
|
||||||
if ('startViewTransition' in document) {
|
if ('startViewTransition' in document) {
|
||||||
return document.startViewTransition(() => {
|
return document.startViewTransition(() => {
|
||||||
|
@ -28,6 +33,27 @@ export class App extends LitElement {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
this.addEventListener('single-fullscreen-image', ({ detail }) => {
|
||||||
|
const { src, details } = detail
|
||||||
|
const img = new Image()
|
||||||
|
img.src = src
|
||||||
|
this.dialogEl.appendChild(img)
|
||||||
|
|
||||||
|
if (detail.details) {
|
||||||
|
const div = document.createElement('div')
|
||||||
|
const p = document.createElement('p')
|
||||||
|
p.textContent = details
|
||||||
|
div.appendChild(p)
|
||||||
|
this.dialogEl.appendChild(div)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.dialogEl.showModal()
|
||||||
|
|
||||||
|
this.dialogEl.addEventListener('click', () => {
|
||||||
|
this.dialogEl.close()
|
||||||
|
this.dialogEl.innerHTML = ''
|
||||||
|
}, { once: true })
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -35,6 +61,8 @@ export class App extends LitElement {
|
||||||
${Router.route.path == '/' ? '' : html`<mm-header title=${Router.route.title}></mm-header>`}
|
${Router.route.path == '/' ? '' : html`<mm-header title=${Router.route.title}></mm-header>`}
|
||||||
${Router.render()}
|
${Router.render()}
|
||||||
${Router.route.path == '/' ? '' : html`<mm-footer path=${Router.route.path}></mm-footer>`}
|
${Router.route.path == '/' ? '' : html`<mm-footer path=${Router.route.path}></mm-footer>`}
|
||||||
|
<dialog class="popup">
|
||||||
|
</dialog>
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,6 +73,26 @@ export class App extends LitElement {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dialog {
|
||||||
|
margin: auto;
|
||||||
|
border: none;
|
||||||
|
|
||||||
|
& div {
|
||||||
|
padding-block-start: 1em;
|
||||||
|
font-size: 1.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
& img {
|
||||||
|
display: block;
|
||||||
|
max-height: calc(100vmin - 2em);
|
||||||
|
max-width: calc(100vmin - 2em);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog::backdrop {
|
||||||
|
background-color: #00000090;
|
||||||
|
}
|
||||||
` ]
|
` ]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -74,6 +74,7 @@ export default new Router({
|
||||||
short: 'Unpublished',
|
short: 'Unpublished',
|
||||||
icon: 'headphones',
|
icon: 'headphones',
|
||||||
group: 'Music & Sound',
|
group: 'Music & Sound',
|
||||||
|
disabled: true,
|
||||||
plugins: [
|
plugins: [
|
||||||
lazy(() => import('../views/audio.js'))
|
lazy(() => import('../views/audio.js'))
|
||||||
],
|
],
|
||||||
|
@ -81,23 +82,23 @@ export default new Router({
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: resolveRouterPath('theatre'),
|
path: resolveRouterPath('theatre'),
|
||||||
title: 'Music - Theatre Works',
|
title: 'Music-Theatre Works',
|
||||||
short: 'Theatre Works',
|
short: 'Music-Theatre',
|
||||||
icon: 'headphones',
|
icon: 'film',
|
||||||
plugins: [
|
plugins: [
|
||||||
lazy(() => import('../views/audio.js'))
|
lazy(() => import('../views/videos.js'))
|
||||||
],
|
],
|
||||||
render: () => html`<mm-audio></mm-audio>`
|
render: () => html`<mm-videos></mm-videos>`
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: resolveRouterPath('concerts'),
|
path: resolveRouterPath('concerts'),
|
||||||
title: 'Concert Recordings',
|
title: 'Concert Recordings',
|
||||||
short: 'Concerts',
|
short: 'Concerts',
|
||||||
icon: 'headphones',
|
icon: 'film',
|
||||||
plugins: [
|
plugins: [
|
||||||
lazy(() => import('../views/audio.js'))
|
lazy(() => import('../views/videos.js'))
|
||||||
],
|
],
|
||||||
render: () => html`<mm-audio></mm-audio>`
|
render: () => html`<mm-videos></mm-videos>`
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: resolveRouterPath('films'),
|
path: resolveRouterPath('films'),
|
||||||
|
@ -114,6 +115,7 @@ export default new Router({
|
||||||
title: 'Scores, Posters, Ephemera',
|
title: 'Scores, Posters, Ephemera',
|
||||||
short: 'images',
|
short: 'images',
|
||||||
icon: 'camera',
|
icon: 'camera',
|
||||||
|
disabled: true,
|
||||||
plugins: [
|
plugins: [
|
||||||
lazy(() => import('../views/images.js'))
|
lazy(() => import('../views/images.js'))
|
||||||
],
|
],
|
||||||
|
|
|
@ -6,7 +6,6 @@ body {
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
|
|
||||||
|
|
||||||
--neutral-900: hsl(0 0% 0%);
|
--neutral-900: hsl(0 0% 0%);
|
||||||
--neutral-700: hsl(220 10% 44%);
|
--neutral-700: hsl(220 10% 44%);
|
||||||
--neutral-400: hsl(220 10% 88%);
|
--neutral-400: hsl(220 10% 88%);
|
||||||
|
@ -18,6 +17,7 @@ body {
|
||||||
--green-400: hsl(147 100% 34%);
|
--green-400: hsl(147 100% 34%);
|
||||||
--green-200: hsl(147 100% 50%);
|
--green-200: hsl(147 100% 50%);
|
||||||
|
|
||||||
|
--neutral-gradient-600: linear-gradient(to top,rgba(208,210,214,1) 0%, rgba(141,142,145,1) 100%);
|
||||||
--neutral-gradient-400: linear-gradient(to bottom, hsl(228, 5%, 82%) 0%, var(--neutral-400) 100%);
|
--neutral-gradient-400: linear-gradient(to bottom, hsl(228, 5%, 82%) 0%, var(--neutral-400) 100%);
|
||||||
--green-gradient-400: linear-gradient(to bottom, var(--green-400) 0%, var(--green-500) 100%);
|
--green-gradient-400: linear-gradient(to bottom, var(--green-400) 0%, var(--green-500) 100%);
|
||||||
--green-inside-gradient-400: linear-gradient(to bottom, rgba(0, 154, 69, 1) 0%,rgba(177, 178, 181, 0) 100%), linear-gradient(rgba(0, 173, 78, 1),rgba(0, 173, 78, 1));
|
--green-inside-gradient-400: linear-gradient(to bottom, rgba(0, 154, 69, 1) 0%,rgba(177, 178, 181, 0) 100%), linear-gradient(rgba(0, 173, 78, 1),rgba(0, 173, 78, 1));
|
||||||
|
|
|
@ -19,18 +19,26 @@ class AudioCard extends LitElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
clickHandler() {
|
clickHandler() {
|
||||||
const event = new CustomEvent('select-audio', {
|
if (!this.selected) {
|
||||||
bubbles: true, composed: true,
|
const event = new CustomEvent('select-audio', {
|
||||||
detail: { ...this.details, idx: this.idx }
|
bubbles: true, composed: true,
|
||||||
})
|
detail: { ...this.details, idx: this.idx }
|
||||||
|
})
|
||||||
|
|
||||||
this.dispatchEvent(event)
|
this.dispatchEvent(event)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return html`
|
return html`
|
||||||
<div class="card ${this.selected ? 'selected' : ''}" @click=${this.clickHandler}>
|
<div class="card ${this.selected ? 'selected' : ''}" @click=${this.clickHandler}>
|
||||||
<mm-icon name=${this.icon}></mm-icon>
|
${this.details.album && this.details.image
|
||||||
|
? html`<img
|
||||||
|
class="albumCover"
|
||||||
|
src=${this.details.image}
|
||||||
|
/>`
|
||||||
|
: html`<mm-icon name=${this.icon}></mm-icon>`
|
||||||
|
}
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
<p class="heading">${this.details?.title}</p>
|
<p class="heading">${this.details?.title}</p>
|
||||||
|
@ -54,10 +62,18 @@ class AudioCard extends LitElement {
|
||||||
font-size: 3em;
|
font-size: 3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.albumCover {
|
||||||
|
display: block;
|
||||||
|
height: 3em;
|
||||||
|
aspect-ratio: 1 / 1;
|
||||||
|
object-fit: cover;
|
||||||
|
background: lightgrey;
|
||||||
|
}
|
||||||
|
|
||||||
.card {
|
.card {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-auto-flow: column;
|
grid-auto-flow: column;
|
||||||
grid-template-columns: min-content 1fr;
|
grid-template-columns: auto 1fr;
|
||||||
gap: 1em;
|
gap: 1em;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding-inline: 0.75em;
|
padding-inline: 0.75em;
|
||||||
|
@ -73,6 +89,10 @@ class AudioCard extends LitElement {
|
||||||
.card.selected {
|
.card.selected {
|
||||||
outline: 2px solid var(--green-400, black);
|
outline: 2px solid var(--green-400, black);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.info {
|
||||||
|
max-width: 30ch;
|
||||||
|
}
|
||||||
` ]
|
` ]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,13 +43,13 @@ class Footer extends LitElement {
|
||||||
|
|
||||||
renderLink(r, first = false) {
|
renderLink(r, first = false) {
|
||||||
return html`
|
return html`
|
||||||
${first ? html`<span class="break"></span>` : '' }
|
${first && !r.disabled ? html`<span class="break"></span>` : '' }
|
||||||
<a href=${r.path} class="${r.path == this.path ? 'selected' : ''}">
|
${!r.disabled ? html`<a href=${r.path} class="${r.path == this.path ? 'selected' : ''}">
|
||||||
<mm-icon name=${r.icon}></mm-icon>
|
<mm-icon name=${r.icon}></mm-icon>
|
||||||
<span>
|
<span>
|
||||||
${r.short}
|
${r.short}
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>` : '' }
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,9 +18,8 @@ class HorizontalScroller extends LitElement {
|
||||||
static styles = css`
|
static styles = css`
|
||||||
:host {
|
:host {
|
||||||
--col-width: 10em;
|
--col-width: 10em;
|
||||||
--gap: 1em;
|
--gap: 0.75em;
|
||||||
display: flex;
|
display: flex;
|
||||||
padding-block-end: 0.5em;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.scroller {
|
.scroller {
|
||||||
|
|
|
@ -39,6 +39,7 @@ class ImageCarousel extends LitElement {
|
||||||
padding-inline-end: 0.5em;
|
padding-inline-end: 0.5em;
|
||||||
padding-block-start: 0.25em;
|
padding-block-start: 0.25em;
|
||||||
padding-block-end: 0.75em;
|
padding-block-end: 0.75em;
|
||||||
|
background: black;
|
||||||
}
|
}
|
||||||
|
|
||||||
mm-image {
|
mm-image {
|
||||||
|
|
|
@ -37,15 +37,19 @@ class ModularPlayer extends LitElement {
|
||||||
this._initAudio()
|
this._initAudio()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
firstUpdated() {
|
||||||
|
console.log(this.details)
|
||||||
|
}
|
||||||
|
|
||||||
_getTrack = new Task(
|
_getTrack = new Task(
|
||||||
this,
|
this,
|
||||||
async () => {
|
async () => {
|
||||||
try {
|
try {
|
||||||
if (this.details) {
|
if (this.details) {
|
||||||
if (this.details?.tracks) {
|
if (this.details?.tracks) {
|
||||||
this.audio.src = `/media${this.details.media}/${this.details.tracks[this.track]}`
|
this.audio.src = `${this.details.media}/${this.details.tracks[this.track].media}`
|
||||||
} else {
|
} else {
|
||||||
this.audio.src = `/media${this.details.media}.mp3`
|
this.audio.src = `${this.details.media}`
|
||||||
}
|
}
|
||||||
this.audio.load()
|
this.audio.load()
|
||||||
if (this.playing && this.audio.paused) {
|
if (this.playing && this.audio.paused) {
|
||||||
|
@ -95,7 +99,7 @@ class ModularPlayer extends LitElement {
|
||||||
this.track = 0
|
this.track = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
this.audio.src = `/media${this.details.media}/${this.details.tracks[this.track]}`
|
this.audio.src = `${this.details.media}/${this.details.tracks[this.track].media}`
|
||||||
this.audio.load()
|
this.audio.load()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -170,20 +174,35 @@ class ModularPlayer extends LitElement {
|
||||||
return `${percentage}%`
|
return `${percentage}%`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
showImage() {
|
||||||
|
const event = new CustomEvent('single-fullscreen-image', {
|
||||||
|
bubbles: true, composed: true,
|
||||||
|
detail: { src: this.details.image }
|
||||||
|
})
|
||||||
|
|
||||||
|
this.dispatchEvent(event)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return html`
|
return html`
|
||||||
${ this.details ?
|
${ this.details ?
|
||||||
html`<div class="player">
|
html`<div class="player">
|
||||||
${this.details.tracks ? html`
|
${this.details.tracks ? html`
|
||||||
<div class="tracklist">
|
<div class="tracklist">
|
||||||
<h2>${this.details.title}</h2>
|
<header>
|
||||||
|
<img src=${this.details.image}
|
||||||
|
@click=${this.showImage}
|
||||||
|
/>
|
||||||
|
<h2>${this.details.title}</h2>
|
||||||
|
</header>
|
||||||
|
|
||||||
<div class="list">
|
<div class="list">
|
||||||
<ul>
|
<ul>
|
||||||
${this.details.tracks.map((t, i) => html`
|
${this.details.tracks.map((t, i) => html`
|
||||||
<li class="${this.track === i ? 'selected' : ''}" data-track-number=${i} @click=${this._selectTrack}>
|
<li class="${this.track === i ? 'selected' : ''}" data-track-number=${i} @click=${this._selectTrack}>
|
||||||
<mm-icon name="notes" class=${this.playing ? 'playing' : ''}></mm-icon>
|
<mm-icon name="notes" class=${this.playing ? 'playing' : ''}></mm-icon>
|
||||||
<span>${t}</span>
|
<span>${t.title}</span>
|
||||||
</li>`)}
|
</li>`)}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@ -191,7 +210,7 @@ ${ this.details ?
|
||||||
` : html``}
|
` : html``}
|
||||||
|
|
||||||
<header>
|
<header>
|
||||||
<h2>${this.details.tracks ? this.details?.tracks[this.track] : this.details.title}</h2>
|
<h2>${this.details.tracks ? this.details?.tracks[this.track].title : this.details.title}</h2>
|
||||||
${this.details.tracks ? '' : html`<p class="details">${this.details.details}</p>`}
|
${this.details.tracks ? '' : html`<p class="details">${this.details.details}</p>`}
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
@ -216,7 +235,7 @@ ${ this.details ?
|
||||||
@input=${this._seekTrack}
|
@input=${this._seekTrack}
|
||||||
class="progress"
|
class="progress"
|
||||||
></mm-range>
|
></mm-range>
|
||||||
<img class="wav-img" loading="eager" src="/media${this.details.media}.png">
|
<img class="wav-img" loading="eager" src="${this.details.image}">
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
|
@ -263,11 +282,11 @@ ${ this.details ?
|
||||||
}
|
}
|
||||||
|
|
||||||
.player:has(.tracklist) {
|
.player:has(.tracklist) {
|
||||||
grid-template-rows: 60% 0.5fr 0.3fr 1fr;
|
grid-template-rows: 67% 0.5fr 0.3fr 1fr;
|
||||||
padding-block-end: 2em;
|
padding-block-end: 2em;
|
||||||
gap: 0;
|
gap: 0;
|
||||||
|
|
||||||
& header {
|
& > header {
|
||||||
margin-block-start: 1.5em;
|
margin-block-start: 1.5em;
|
||||||
margin-block-end: 2em;
|
margin-block-end: 2em;
|
||||||
}
|
}
|
||||||
|
@ -300,23 +319,36 @@ ${ this.details ?
|
||||||
|
|
||||||
.tracklist {
|
.tracklist {
|
||||||
--tracklist-padding: calc(var(--padding) * 2);
|
--tracklist-padding: calc(var(--padding) * 2);
|
||||||
position: relative;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
background: var(--neutral-gradient-400);
|
background: var(--neutral-gradient-400);
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
> h2 {
|
& header {
|
||||||
margin-inline: var(--tracklist-padding);
|
margin-inline: var(--tracklist-padding);
|
||||||
margin-block-start: 0.75em;
|
margin-block-start: 1em;
|
||||||
|
margin-block-end: 0.75em;
|
||||||
padding-block-start: 0.75em;
|
padding-block-start: 0.75em;
|
||||||
border-block-start: thin solid var(--green-400);
|
border-block-start: thin solid var(--green-400);
|
||||||
|
display: flex;
|
||||||
|
gap: 0.5em;
|
||||||
|
align-items: end;
|
||||||
|
color: black;
|
||||||
|
|
||||||
|
& img {
|
||||||
|
height: 4em;
|
||||||
|
aspect-ratio: 1 / 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
& > h2 {
|
||||||
|
line-height: 1;
|
||||||
|
max-width: 15ch;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> .list {
|
& .list {
|
||||||
position: absolute;
|
flex-grow: 1;
|
||||||
bottom: 0;
|
margin-inline: var(--tracklist-padding);
|
||||||
top: calc(var(--tracklist-padding) * 2.5);
|
|
||||||
right: var(--tracklist-padding);
|
|
||||||
left: var(--tracklist-padding);
|
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
border-radius: 0.75em 0.75em 0 0;
|
border-radius: 0.75em 0.75em 0 0;
|
||||||
|
@ -391,6 +423,7 @@ ${ this.details ?
|
||||||
}
|
}
|
||||||
|
|
||||||
.info:has(.waveform) {
|
.info:has(.waveform) {
|
||||||
|
|
||||||
& .time_pos,
|
& .time_pos,
|
||||||
& .time_dur {
|
& .time_dur {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
|
@ -18,34 +18,42 @@ class NavCard extends LitElement {
|
||||||
firstUpdated() {
|
firstUpdated() {
|
||||||
console.log(this.route)
|
console.log(this.route)
|
||||||
this.shadowRoot.host.addEventListener('click', () => {
|
this.shadowRoot.host.addEventListener('click', () => {
|
||||||
Router.navigate(this.route.path)
|
if (!this.route.disabled) {
|
||||||
|
Router.navigate(this.route.path)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
navigate(path) {
|
navigate(path) {
|
||||||
path = path || this.route.path
|
if (!this.route.disabled) {
|
||||||
Router.navigate(path)
|
path = path || this.route.path
|
||||||
|
Router.navigate(path)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return html`
|
return html`
|
||||||
<div class="card">
|
<div class="card">
|
||||||
${Array.isArray(this.route) ? html`
|
${Array.isArray(this.route) ? html`
|
||||||
<p class="title">${this.route[0].group}</p>
|
<header class="title">
|
||||||
|
<span>${this.route[0].group}</span>
|
||||||
|
</header>
|
||||||
${this.route.map(r =>
|
${this.route.map(r =>
|
||||||
html`
|
!r.disabled ? html`
|
||||||
<button @click=${() => this.navigate(r.path)}>
|
<button @click=${() => this.navigate(r.path)}>
|
||||||
<mm-icon name=${r.icon}></mm-icon>
|
<mm-icon name=${r.icon}></mm-icon>
|
||||||
${r.title}
|
${r.title}
|
||||||
</button>
|
</button>
|
||||||
`
|
` : ''
|
||||||
)}
|
)}
|
||||||
`
|
`
|
||||||
:
|
:
|
||||||
html`
|
html`
|
||||||
<p class="title">${this.route?.title}</p>
|
<header class="title">
|
||||||
<button class="iconOnly" @click=${() => this.navigate()}>
|
<span>${this.route?.title}</span>
|
||||||
<mm-icon name=${this.route.icon}></mm-icon>
|
</header>
|
||||||
|
<button class="iconOnly" @click=${this.navigate}>
|
||||||
|
${!this.route.disabled ? html`<mm-icon name=${this.route.icon}></mm-icon>` : html`<span>coming soon...</span>`}
|
||||||
</button>
|
</button>
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
|
@ -88,6 +96,15 @@ class NavCard extends LitElement {
|
||||||
font-size: 0.75em;
|
font-size: 0.75em;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
border-bottom: thin solid var(--highlight-color);
|
border-bottom: thin solid var(--highlight-color);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
min-height: 2.5em;
|
||||||
|
|
||||||
|
& > span {
|
||||||
|
display: block;
|
||||||
|
max-width: 18ch;
|
||||||
|
margin-inline: auto;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
|
@ -105,6 +122,10 @@ class NavCard extends LitElement {
|
||||||
text-shadow: 0 0 5px #ffffff;
|
text-shadow: 0 0 5px #ffffff;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
|
||||||
|
&:has(span) {
|
||||||
|
background: var(--neutral-gradient-600);
|
||||||
|
}
|
||||||
|
|
||||||
&.iconOnly {
|
&.iconOnly {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 0;
|
gap: 0;
|
||||||
|
@ -112,6 +133,10 @@ class NavCard extends LitElement {
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
padding: 1em;
|
padding: 1em;
|
||||||
|
|
||||||
|
& > span {
|
||||||
|
font-size: 0.5em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
& mm-icon {
|
& mm-icon {
|
||||||
|
|
|
@ -13,6 +13,7 @@ class VerticalCard extends LitElement {
|
||||||
super()
|
super()
|
||||||
this.details = {}
|
this.details = {}
|
||||||
this.selected = false
|
this.selected = false
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
select() {
|
select() {
|
||||||
|
@ -30,7 +31,7 @@ class VerticalCard extends LitElement {
|
||||||
return html`
|
return html`
|
||||||
<div @click=${this.select} class=${this.selected ? 'selected' : ''}>
|
<div @click=${this.select} class=${this.selected ? 'selected' : ''}>
|
||||||
<picture>
|
<picture>
|
||||||
<img src="/media/${Router.route.path}/thumbs/${this.details.media}">
|
<img src="/media/${Router.route.path}/${this.details.image}">
|
||||||
</picture>
|
</picture>
|
||||||
<aside>
|
<aside>
|
||||||
<p class="title">${this.details?.title}</p>
|
<p class="title">${this.details?.title}</p>
|
||||||
|
@ -51,7 +52,7 @@ class VerticalCard extends LitElement {
|
||||||
div {
|
div {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-rows: 75% 25%;
|
grid-template-rows: 72% 28%;
|
||||||
background: lightgrey;
|
background: lightgrey;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
@ -59,10 +60,11 @@ class VerticalCard extends LitElement {
|
||||||
background: var(--background-color);
|
background: var(--background-color);
|
||||||
color: var(--font-color);
|
color: var(--font-color);
|
||||||
align-content: start;
|
align-content: start;
|
||||||
|
font-size: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.selected {
|
.selected {
|
||||||
outline: 2px solid var(--color);
|
outline: 1px solid var(--color);
|
||||||
}
|
}
|
||||||
|
|
||||||
picture {
|
picture {
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
import { LitElement, css, html } from 'lit'
|
import { LitElement, css, html } from 'lit'
|
||||||
import { Task } from '@lit-labs/task'
|
import { Task } from '@lit-labs/task'
|
||||||
|
|
||||||
import Photo from '/images/Meredith Monk (1974) Photo Lauretta Harris.jpg'
|
|
||||||
|
|
||||||
// components
|
// components
|
||||||
import '../components/Loading.js'
|
import '../components/Loading.js'
|
||||||
import '../components/AudioCard.js'
|
import '../components/AudioCard.js'
|
||||||
|
@ -27,7 +25,9 @@ class AudioView extends LitElement {
|
||||||
const div = this.shadowRoot.querySelector('mm-audio-player')
|
const div = this.shadowRoot.querySelector('mm-audio-player')
|
||||||
|
|
||||||
div.addEventListener('transitionend', () => {
|
div.addEventListener('transitionend', () => {
|
||||||
this.selected = { ...detail, media: `${Router.route.path}/${detail.media}` }
|
this.selected = {
|
||||||
|
...detail
|
||||||
|
}
|
||||||
div.classList.remove('unloading')
|
div.classList.remove('unloading')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -49,10 +49,19 @@ class AudioView extends LitElement {
|
||||||
const res = await fetch(`/data${Router.route.path}.json`)
|
const res = await fetch(`/data${Router.route.path}.json`)
|
||||||
const json = await res.json()
|
const json = await res.json()
|
||||||
|
|
||||||
this.tracks = json
|
this.tracks = json.map(i => {
|
||||||
// start track (0 is not currently available)
|
i.media = `/media${Router.route.path}/${i.media}`
|
||||||
const idx = 1
|
i.image = i.image ? `/media${Router.route.path}/${i.image}` : ''
|
||||||
this.selected = { ...this.tracks[idx], idx, media: `${Router.route.path}/${this.tracks[idx].media}` }
|
|
||||||
|
return i
|
||||||
|
})
|
||||||
|
|
||||||
|
if (this.tracks.length > 0) {
|
||||||
|
const idx = 0
|
||||||
|
this.selected = {
|
||||||
|
...this.tracks[idx], idx,
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
() => []
|
() => []
|
||||||
)
|
)
|
||||||
|
@ -70,21 +79,20 @@ class AudioView extends LitElement {
|
||||||
<div class="scroll-items">
|
<div class="scroll-items">
|
||||||
${this._getAudio.render({
|
${this._getAudio.render({
|
||||||
pending: () => html`<mm-loading style="--fill-color: grey"></mm-loading>`,
|
pending: () => html`<mm-loading style="--fill-color: grey"></mm-loading>`,
|
||||||
complete: () => html`${this.tracks.map((t, i) => html`
|
complete: () => html`${this.tracks.length > 0 ? this.tracks.map((t, i) => html`
|
||||||
<mm-acard
|
<mm-acard
|
||||||
idx=${i}
|
idx=${i}
|
||||||
icon=${t.album ? 'album' : 'play-circle'}
|
icon=${t.album ? 'album' : 'play-circle'}
|
||||||
?selected=${t.title == this.selected.title && t.details == this.selected.details}
|
?selected=${t.title == this.selected.title && t.details == this.selected.details}
|
||||||
.details=${t}
|
.details=${t}
|
||||||
></mm-acard>`)}`,
|
></mm-acard>`) : 'No tracks added for this category' }`,
|
||||||
error: (err) => html`Error: ${err}`
|
error: (err) => html`Error: ${err}`
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div class="player">
|
<div class="player ${this.selected.tracks ? '' : 'single'}">
|
||||||
<div>
|
<div>
|
||||||
${this.selected?.tracks ? '' : html`<img class="bg-img" src=${Photo} />` }
|
|
||||||
<mm-audio-player .details=${this.selected}></mm-audio-player>
|
<mm-audio-player .details=${this.selected}></mm-audio-player>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -126,6 +134,13 @@ class AudioView extends LitElement {
|
||||||
.player {
|
.player {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
|
&.single > div {
|
||||||
|
background-image: url('/images/Meredith Monk (1974) Photo Lauretta Harris.jpg'), var(--green-gradient-400);
|
||||||
|
background-position: center;
|
||||||
|
background-size: 110%, 110%, cover;
|
||||||
|
background-blend-mode: soft-light, screen;
|
||||||
|
}
|
||||||
|
|
||||||
> div {
|
> div {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
|
|
|
@ -30,10 +30,6 @@ class ImageView extends LitElement {
|
||||||
json.forEach(i => i.path = `/media${Router.route.path}/${i.media}`)
|
json.forEach(i => i.path = `/media${Router.route.path}/${i.media}`)
|
||||||
|
|
||||||
this.images = json
|
this.images = json
|
||||||
this.selected = this.images[0]
|
|
||||||
|
|
||||||
console.log(this.selected)
|
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
}
|
}
|
||||||
|
@ -42,30 +38,54 @@ class ImageView extends LitElement {
|
||||||
)
|
)
|
||||||
|
|
||||||
selectImage({ target }) {
|
selectImage({ target }) {
|
||||||
const { details } = target
|
console.log(target.details)
|
||||||
if (details?.title != this.selected?.title) {
|
const event = new CustomEvent('single-fullscreen-image', {
|
||||||
this.selected = details
|
bubbles: true, composed: true,
|
||||||
}
|
detail: { ...target.details, src: `/media${Router.route.path}/${target.details.section}/${target.details.media}` }
|
||||||
|
})
|
||||||
|
|
||||||
|
this.dispatchEvent(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return html`
|
return html`
|
||||||
<mm-img-carousel .images=${this.images}></mm-img-carousel>
|
<!-- <mm-img-carousel .images=${this.images}></mm-img-carousel> -->
|
||||||
|
|
||||||
<mm-hscroller>
|
${this.images.length > 0 ?
|
||||||
${this._getImages.render({ complete: () => this.images.map(i => html`
|
html`
|
||||||
<mm-vcard @click=${this.selectImage} .details=${i} ?selected=${i.title == this.selected?.title}></mm-vcard>
|
<div class="gallery">
|
||||||
`) })}
|
${this._getImages.render({ complete: () => this.images.map(
|
||||||
</mm-hscroller>
|
section => html`
|
||||||
|
<header class="section-header">
|
||||||
|
<h3>${section.title}</h3>
|
||||||
|
</header>
|
||||||
|
<main>
|
||||||
|
${section.images.map(
|
||||||
|
i => html`
|
||||||
|
<mm-vcard
|
||||||
|
@click=${this.selectImage}
|
||||||
|
.details=${ { ...i, section: section.media } }
|
||||||
|
?selected=${i.title == this.selected?.title}
|
||||||
|
>
|
||||||
|
</mm-vcard>
|
||||||
|
`)}
|
||||||
|
</main>
|
||||||
|
`
|
||||||
|
) })}
|
||||||
|
</div>
|
||||||
|
` :
|
||||||
|
html`<h2>No images added to the gallery</h2>`
|
||||||
|
}
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
|
|
||||||
static styles = [ css`${unsafeCSS(MainCSS)}`, css`
|
static styles = [ css`${unsafeCSS(MainCSS)}`, css`
|
||||||
:host {
|
:host {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
display: grid;
|
height: 100%;
|
||||||
grid-template-rows: 1fr auto;
|
overflow: auto;
|
||||||
gap: 0.5em;
|
padding-inline: 1em;
|
||||||
|
padding-block: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
mm-hscroller {
|
mm-hscroller {
|
||||||
|
@ -77,12 +97,34 @@ class ImageView extends LitElement {
|
||||||
--color: var(--green-400, lime);
|
--color: var(--green-400, lime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
padding-block-start: 1.5em;
|
||||||
|
padding-block-end: 1em;
|
||||||
|
font-size: 1.25em;
|
||||||
|
border-bottom: 1px solid var(--green-400);
|
||||||
|
margin-block-end: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
display: grid;
|
||||||
|
gap: 0.75em;
|
||||||
|
grid-template-columns: repeat(7, 1fr);
|
||||||
|
grid-auto-rows: 10em;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.image {
|
.image {
|
||||||
position: relative;
|
position: relative;
|
||||||
inline-margin: auto;
|
inline-margin: auto;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mm-image-carousel {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
}
|
||||||
` ]
|
` ]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
customElements.define('mm-images', ImageView)
|
customElements.define('mm-images', ImageView)
|
||||||
|
|
|
@ -44,7 +44,7 @@ class VideoView extends LitElement {
|
||||||
<main>
|
<main>
|
||||||
<aside>
|
<aside>
|
||||||
<h2>${this.selected.title}</h2>
|
<h2>${this.selected.title}</h2>
|
||||||
<p class="detail">${this.selected.detail}</p>
|
<p class="details">${this.selected.details}</p>
|
||||||
</aside>
|
</aside>
|
||||||
<mm-vplayer media='/media/${this.selected.media}' ?autoplay=${this.selected.autoplay}></mm-vplayer>
|
<mm-vplayer media='/media/${this.selected.media}' ?autoplay=${this.selected.autoplay}></mm-vplayer>
|
||||||
</main>
|
</main>
|
||||||
|
@ -55,7 +55,7 @@ class VideoView extends LitElement {
|
||||||
complete: () => html`${this.films.map(t => html`
|
complete: () => html`${this.films.map(t => html`
|
||||||
<mm-vcard
|
<mm-vcard
|
||||||
.details=${t}
|
.details=${t}
|
||||||
?selected=${t.title == this.selected.title && t.detail == this.selected.detail}
|
?selected=${t.title == this.selected.title && t.details == this.selected.details}
|
||||||
></mm-vcard>`
|
></mm-vcard>`
|
||||||
)}`
|
)}`
|
||||||
})}
|
})}
|
||||||
|
@ -68,7 +68,7 @@ class VideoView extends LitElement {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-rows: 70% 30%;
|
grid-template-rows: 1fr 0.55fr;
|
||||||
gap: 0.25em;
|
gap: 0.25em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,7 +95,7 @@ class VideoView extends LitElement {
|
||||||
margin-block-end: 0.2em;
|
margin-block-end: 0.2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
> .detail {
|
> .details {
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,12 @@ export default defineConfig({
|
||||||
build: {
|
build: {
|
||||||
sourcemap: true,
|
sourcemap: true,
|
||||||
target: [ 'esnext', 'edge100', 'firefox100', 'chrome100', 'safari18' ],
|
target: [ 'esnext', 'edge100', 'firefox100', 'chrome100', 'safari18' ],
|
||||||
|
rollupOptions: {
|
||||||
|
external: [
|
||||||
|
'scripts',
|
||||||
|
'public/media'
|
||||||
|
],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
server: {
|
server: {
|
||||||
host: '0.0.0.0'
|
host: '0.0.0.0'
|
||||||
|
|
Loading…
Reference in New Issue