melt-change-resolution.hs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. {-
  2. don't use this script if you can help it!
  3. this is a really bad script that could just as well be written
  4. in something like sed; i did it in haskell just because and
  5. had no time to make something sensible instead. it kinda works
  6. for a few effects that i needed. except when it doesn't
  7. -}
  8. {-# LANGUAGE NoMonomorphismRestriction #-}
  9. {-# LANGUAGE LambdaCase #-}
  10. module Main where
  11. import Control.Monad (join)
  12. import Data.Semigroup
  13. import Data.List
  14. import Data.Char
  15. import Debug.Trace
  16. splitOn p s = (takeWhile p s, dropWhile p s)
  17. replaceOnce :: String -> String -> String -> (String, String)
  18. replaceOnce a b = \case
  19. "" -> ("","")
  20. s@(x:xs) ->
  21. let
  22. len = length a
  23. in if take len s == a then
  24. (b, drop len s)
  25. else
  26. ([x], xs)
  27. replace :: String -> String -> String -> String
  28. replace a b = \case
  29. "" -> ""
  30. s ->
  31. let
  32. (ys,xs) = replaceOnce a b s
  33. in
  34. ys <> replace a b xs
  35. processOnce scale s =
  36. let
  37. (fr,recti) = splitOn (/= '=') s
  38. rect = drop 1 recti
  39. nums :: [Double]
  40. nums = fmap read . words $ rect
  41. nums' = take 4 nums
  42. rest = drop 4 nums
  43. nums'' = fmap ((*scale) . floor) nums'
  44. res = traceShowId $ (unwords . fmap show $ nums'') ++ " " ++ unwords (fmap show rest)
  45. in
  46. fr <> "=" <> res
  47. processRectVal scale = \case
  48. "" -> ""
  49. s ->
  50. let
  51. (x,xs) = splitOn (/= ';') s
  52. in
  53. processOnce scale x <> ";" <> processRectVal scale (drop 1 xs)
  54. singletonLists = foldr ((:).(:[])) []
  55. interMix :: [[a]] -> [[a]] -> [a]
  56. interMix (i:ins) (m:ms) = m <> i <> interMix ins ms
  57. interMix [] ms = join ms
  58. interMix ins [] = []
  59. cutBy _ [] = []
  60. cutBy f l =
  61. let
  62. (x,xs) = break f l
  63. in
  64. [x] <> cutBy f (drop 1 xs)
  65. isNumberChar x = isNumber x || x == '-'
  66. keepFrame f s =
  67. case cutBy (== '=') s of
  68. [x] -> f x
  69. [k,x] -> k <> "=" <> f x
  70. processGeomVal scale s =
  71. let
  72. sections = traceShowId $ cutBy (== ';') s
  73. in
  74. intercalate ";" . fmap (keepFrame $ processGeomOneVal scale) $ sections
  75. dropEither :: Either a a -> a
  76. dropEither (Left x) = x
  77. dropEither (Right x) = x
  78. processGeomOneVal scale s =
  79. let
  80. numss = traceShowId $ cutBy (\c -> not $ isNumberChar c || c == '.' || c == '%') s
  81. numsd :: [Either String Double]
  82. numsd = fmap (\ s -> if last s == '%' then Left s else Right (read s)) numss
  83. nums = fmap (fmap floor) numsd
  84. nums' = fmap (fmap (* scale)) (take 4 nums) <> drop 4 nums
  85. sss = fmap (dropEither . fmap show) nums'
  86. -- nums' = fmap (\case { Left pcs -> pcs ; Right x -> show (x * scale) }) (take 4 nums) <> fmap drop 4 nums
  87. in
  88. traceShowId $ interMix (singletonLists " ") sss -- . fmap show $ nums'
  89. processLine (w,h) (w',h') s =
  90. if "<profile" `isInfixOf` s then
  91. replace (show $ show w) (show $ show w') .
  92. replace (show $ show h) (show $ show h') $ s
  93. else if "<property name=\"rect\">" `isInfixOf` s then
  94. let
  95. (pref,ns) = splitOn (not . isNumberChar) s
  96. (val,suff) = splitOn (/= '<') ns
  97. in
  98. pref <> processRectVal (w' `div` w) val <> suff
  99. else if "<property name=\"transition.geometry\">" `isInfixOf` s || "<property name=\"geometry\">" `isInfixOf` s then
  100. let
  101. (pref,ns) = splitOn (not . isNumberChar) s
  102. (val,suff) = splitOn (/= '<') ns
  103. in
  104. pref <> processGeomVal (w' `div` w) val <> suff
  105. else if any (\w -> ("<property name=\""<>w<>"\">") `isInfixOf` s) ["left", "top", "bottom", "right"] then
  106. let
  107. (pref,ns) = splitOn (not . isNumberChar) s
  108. (val,suff) = splitOn (/= '<') ns
  109. in
  110. pref <> processGeomOneVal (w' `div` w) val <> suff
  111. else if "kdenlive:originalurl" `isInfixOf` s then
  112. replace "kdenlive:originalurl" "resource" s
  113. else if "proxy" `isInfixOf` s then
  114. ""
  115. else
  116. s
  117. changeRes wh wh' src dst = do
  118. source <- lines <$> readFile src
  119. writeFile dst . unlines . fmap (processLine wh wh') $ source
  120. -- usage example..
  121. main = changeRes (160,90) (960,540) "proc.kdenlive" "proc_r.kdenlive"